diff --git a/Capnp.Net.Runtime.Tests.Core21/Capnp.Net.Runtime.Tests.Core21.csproj b/Capnp.Net.Runtime.Tests.Core21/Capnp.Net.Runtime.Tests.Core21.csproj
index d4a9e68..2e1fffa 100644
--- a/Capnp.Net.Runtime.Tests.Core21/Capnp.Net.Runtime.Tests.Core21.csproj
+++ b/Capnp.Net.Runtime.Tests.Core21/Capnp.Net.Runtime.Tests.Core21.csproj
@@ -14,6 +14,7 @@
+
diff --git a/Capnp.Net.Runtime.Tests/Issue19.cs b/Capnp.Net.Runtime.Tests/Issue19.cs
new file mode 100644
index 0000000..e07b6e3
--- /dev/null
+++ b/Capnp.Net.Runtime.Tests/Issue19.cs
@@ -0,0 +1,332 @@
+using Capnp;
+using Capnp.Rpc;
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace CapnpGen
+{
+ [TypeId(0x8f85f6df684d47b5UL), Proxy(typeof(GenericAProxy<>)), Skeleton(typeof(GenericASkeleton<>))]
+ public interface IGenericA : IDisposable where TT : class
+ {
+ Task MethodA(TT param1, CancellationToken cancellationToken_ = default);
+ }
+
+ public class GenericAProxy : Proxy, IGenericA where TT : class
+ {
+ public async Task MethodA(TT param1, CancellationToken cancellationToken_ = default)
+ {
+ var in_ = SerializerState.CreateForRpc.Params_methodA.WRITER>();
+ var arg_ = new CapnpGen.GenericA.Params_methodA()
+ {Param1 = param1};
+ arg_.serialize(in_);
+ var d_ = await Call(10341943558714247093UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned;
+ var r_ = CapnpSerializable.Create.Result_methodA>(d_);
+ return;
+ }
+ }
+
+ public class GenericASkeleton : Skeleton> where TT : class
+ {
+ public GenericASkeleton()
+ {
+ SetMethodTable(MethodA);
+ }
+
+ public override ulong InterfaceId => 10341943558714247093UL;
+ async Task MethodA(DeserializerState d_, CancellationToken cancellationToken_)
+ {
+ var in_ = CapnpSerializable.Create.Params_methodA>(d_);
+ await Impl.MethodA(in_.Param1, cancellationToken_);
+ var s_ = SerializerState.CreateForRpc.Result_methodA.WRITER>();
+ return s_;
+ }
+ }
+
+ public static class GenericA
+ where TT : class
+ {
+ [TypeId(0xe67c3d73f913c24fUL)]
+ public class Params_methodA : ICapnpSerializable
+ {
+ public const UInt64 typeId = 0xe67c3d73f913c24fUL;
+ void ICapnpSerializable.Deserialize(DeserializerState arg_)
+ {
+ var reader = READER.create(arg_);
+ Param1 = CapnpSerializable.Create(reader.Param1);
+ applyDefaults();
+ }
+
+ public void serialize(WRITER writer)
+ {
+ writer.Param1.SetObject(Param1);
+ }
+
+ void ICapnpSerializable.Serialize(SerializerState arg_)
+ {
+ serialize(arg_.Rewrap());
+ }
+
+ public void applyDefaults()
+ {
+ }
+
+ public TT Param1
+ {
+ get;
+ set;
+ }
+
+ public struct READER
+ {
+ readonly DeserializerState ctx;
+ public READER(DeserializerState ctx)
+ {
+ this.ctx = ctx;
+ }
+
+ public static READER create(DeserializerState ctx) => new READER(ctx);
+ public static implicit operator DeserializerState(READER reader) => reader.ctx;
+ public static implicit operator READER(DeserializerState ctx) => new READER(ctx);
+ public DeserializerState Param1 => ctx.StructReadPointer(0);
+ }
+
+ public class WRITER : SerializerState
+ {
+ public WRITER()
+ {
+ this.SetStruct(0, 1);
+ }
+
+ public DynamicSerializerState Param1
+ {
+ get => BuildPointer(0);
+ set => Link(0, value);
+ }
+ }
+ }
+
+ [TypeId(0xd6791784c41c75f3UL)]
+ public class Result_methodA : ICapnpSerializable
+ {
+ public const UInt64 typeId = 0xd6791784c41c75f3UL;
+ void ICapnpSerializable.Deserialize(DeserializerState arg_)
+ {
+ var reader = READER.create(arg_);
+ applyDefaults();
+ }
+
+ public void serialize(WRITER writer)
+ {
+ }
+
+ void ICapnpSerializable.Serialize(SerializerState arg_)
+ {
+ serialize(arg_.Rewrap());
+ }
+
+ public void applyDefaults()
+ {
+ }
+
+ public struct READER
+ {
+ readonly DeserializerState ctx;
+ public READER(DeserializerState ctx)
+ {
+ this.ctx = ctx;
+ }
+
+ public static READER create(DeserializerState ctx) => new READER(ctx);
+ public static implicit operator DeserializerState(READER reader) => reader.ctx;
+ public static implicit operator READER(DeserializerState ctx) => new READER(ctx);
+ }
+
+ public class WRITER : SerializerState
+ {
+ public WRITER()
+ {
+ this.SetStruct(0, 0);
+ }
+ }
+ }
+ }
+
+ [TypeId(0xe3cd928b8338eac9UL), Proxy(typeof(B2Proxy)), Skeleton(typeof(B2Skeleton))]
+ public interface IB2 : CapnpGen.IGenericA
+ {
+ Task MethodB(long param1, CancellationToken cancellationToken_ = default);
+ }
+
+ public class B2Proxy : Proxy, IB2
+ {
+ public async Task MethodB(long param1, CancellationToken cancellationToken_ = default)
+ {
+ var in_ = SerializerState.CreateForRpc();
+ var arg_ = new CapnpGen.B2.Params_methodB()
+ {Param1 = param1};
+ arg_.serialize(in_);
+ var d_ = await Call(16414937344734980809UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned;
+ var r_ = CapnpSerializable.Create(d_);
+ return (r_.Res);
+ }
+
+ public async Task MethodA(string param1, CancellationToken cancellationToken_ = default)
+ {
+ var in_ = SerializerState.CreateForRpc.Params_methodA.WRITER>();
+ var arg_ = new CapnpGen.GenericA.Params_methodA()
+ {Param1 = param1};
+ arg_.serialize(in_);
+ var d_ = await Call(10341943558714247093UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned;
+ var r_ = CapnpSerializable.Create.Result_methodA>(d_);
+ return;
+ }
+ }
+
+ public class B2Skeleton : Skeleton
+ {
+ public B2Skeleton()
+ {
+ SetMethodTable(MethodB);
+ }
+
+ public override ulong InterfaceId => 16414937344734980809UL;
+ Task MethodB(DeserializerState d_, CancellationToken cancellationToken_)
+ {
+ var in_ = CapnpSerializable.Create(d_);
+ return Impatient.MaybeTailCall(Impl.MethodB(in_.Param1, cancellationToken_), res =>
+ {
+ var s_ = SerializerState.CreateForRpc();
+ var r_ = new CapnpGen.B2.Result_methodB{Res = res};
+ r_.serialize(s_);
+ return s_;
+ }
+
+ );
+ }
+ }
+
+ public static class B2
+ {
+ [TypeId(0xdf7b0019c911a776UL)]
+ public class Params_methodB : ICapnpSerializable
+ {
+ public const UInt64 typeId = 0xdf7b0019c911a776UL;
+ void ICapnpSerializable.Deserialize(DeserializerState arg_)
+ {
+ var reader = READER.create(arg_);
+ Param1 = reader.Param1;
+ applyDefaults();
+ }
+
+ public void serialize(WRITER writer)
+ {
+ writer.Param1 = Param1;
+ }
+
+ void ICapnpSerializable.Serialize(SerializerState arg_)
+ {
+ serialize(arg_.Rewrap());
+ }
+
+ public void applyDefaults()
+ {
+ }
+
+ public long Param1
+ {
+ get;
+ set;
+ }
+
+ public struct READER
+ {
+ readonly DeserializerState ctx;
+ public READER(DeserializerState ctx)
+ {
+ this.ctx = ctx;
+ }
+
+ public static READER create(DeserializerState ctx) => new READER(ctx);
+ public static implicit operator DeserializerState(READER reader) => reader.ctx;
+ public static implicit operator READER(DeserializerState ctx) => new READER(ctx);
+ public long Param1 => ctx.ReadDataLong(0UL, 0L);
+ }
+
+ public class WRITER : SerializerState
+ {
+ public WRITER()
+ {
+ this.SetStruct(1, 0);
+ }
+
+ public long Param1
+ {
+ get => this.ReadDataLong(0UL, 0L);
+ set => this.WriteData(0UL, value, 0L);
+ }
+ }
+ }
+
+ [TypeId(0xea5fbbd3b20b4347UL)]
+ public class Result_methodB : ICapnpSerializable
+ {
+ public const UInt64 typeId = 0xea5fbbd3b20b4347UL;
+ void ICapnpSerializable.Deserialize(DeserializerState arg_)
+ {
+ var reader = READER.create(arg_);
+ Res = reader.Res;
+ applyDefaults();
+ }
+
+ public void serialize(WRITER writer)
+ {
+ writer.Res = Res;
+ }
+
+ void ICapnpSerializable.Serialize(SerializerState arg_)
+ {
+ serialize(arg_.Rewrap());
+ }
+
+ public void applyDefaults()
+ {
+ }
+
+ public string Res
+ {
+ get;
+ set;
+ }
+
+ public struct READER
+ {
+ readonly DeserializerState ctx;
+ public READER(DeserializerState ctx)
+ {
+ this.ctx = ctx;
+ }
+
+ public static READER create(DeserializerState ctx) => new READER(ctx);
+ public static implicit operator DeserializerState(READER reader) => reader.ctx;
+ public static implicit operator READER(DeserializerState ctx) => new READER(ctx);
+ public string Res => ctx.ReadText(0, "");
+ }
+
+ public class WRITER : SerializerState
+ {
+ public WRITER()
+ {
+ this.SetStruct(0, 1);
+ }
+
+ public string Res
+ {
+ get => this.ReadText(0, "");
+ set => this.WriteText(0, value, "");
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Capnp.Net.Runtime.Tests/TcpRpcAdvancedStuff.cs b/Capnp.Net.Runtime.Tests/TcpRpcAdvancedStuff.cs
index fee316a..7b8c31c 100644
--- a/Capnp.Net.Runtime.Tests/TcpRpcAdvancedStuff.cs
+++ b/Capnp.Net.Runtime.Tests/TcpRpcAdvancedStuff.cs
@@ -120,5 +120,28 @@ namespace Capnp.Net.Runtime.Tests
}
}
}
+
+ [TestMethod]
+ public void InheritFromGenericInterface()
+ {
+ using (var server = SetupServer())
+ {
+ var counters = new Counters();
+ server.Main = new B2Impl();
+
+ using (var client = SetupClient())
+ {
+ client.WhenConnected.Wait();
+
+ using (var main = client.GetMain())
+ {
+ Assert.IsTrue(main.MethodA("42").Wait(MediumNonDbgTimeout));
+ var b = main.MethodB(123);
+ Assert.IsTrue(b.Wait(MediumNonDbgTimeout));
+ Assert.AreEqual("42", b.Result);
+ }
+ }
+ }
+ }
}
}
diff --git a/Capnp.Net.Runtime.Tests/TestCapImplementations.cs b/Capnp.Net.Runtime.Tests/TestCapImplementations.cs
index b00d2be..94d241a 100644
--- a/Capnp.Net.Runtime.Tests/TestCapImplementations.cs
+++ b/Capnp.Net.Runtime.Tests/TestCapImplementations.cs
@@ -753,4 +753,27 @@ namespace Capnp.Net.Runtime.Tests.GenImpls
}
}
#endregion TestHandle
+
+ #region B2
+
+ class B2Impl : CapnpGen.IB2
+ {
+ string _s;
+
+ public void Dispose()
+ {
+ }
+
+ public Task MethodA(string param1, CancellationToken cancellationToken_ = default)
+ {
+ _s = param1;
+ return Task.CompletedTask;
+ }
+
+ public Task MethodB(long param1, CancellationToken cancellationToken_ = default)
+ {
+ return Task.FromResult(_s);
+ }
+ }
+ #endregion B2
}
diff --git a/Capnp.Net.Runtime/Capnp.Net.Runtime.csproj b/Capnp.Net.Runtime/Capnp.Net.Runtime.csproj
index fad4233..984ff3f 100644
--- a/Capnp.Net.Runtime/Capnp.Net.Runtime.csproj
+++ b/Capnp.Net.Runtime/Capnp.Net.Runtime.csproj
@@ -18,7 +18,7 @@
MIT
Git
capnp "Cap'n Proto" RPC serialization cerealization
- 1.1-local$([System.DateTime]::UtcNow.ToString(yyMMddHHmm))
+ 1.2-local$([System.DateTime]::UtcNow.ToString(yyMMddHHmm))
Debug;Release
diff --git a/Capnp.Net.Runtime/Rpc/CapabilityReflection.cs b/Capnp.Net.Runtime/Rpc/CapabilityReflection.cs
index 98b7fe0..0ae96f1 100644
--- a/Capnp.Net.Runtime/Rpc/CapabilityReflection.cs
+++ b/Capnp.Net.Runtime/Rpc/CapabilityReflection.cs
@@ -119,21 +119,20 @@ namespace Capnp.Rpc
try
{
var attrs = (from iface in _.GetInterfaces()
- from attr in iface.GetCustomAttributes(typeof(SkeletonAttribute), true)
- select (SkeletonAttribute)attr).ToArray();
+ let generics = iface.GetGenericArguments()
+ from attr in iface.GetCustomAttributes(typeof(SkeletonAttribute), false)
+ select (Attr: (SkeletonAttribute)attr, Generics: generics)).ToArray();
if (attrs.Length == 0)
throw new InvalidCapabilityInterfaceException("No 'Skeleton' attribute defined, don't know how to create the skeleton");
- Type[] genericArguments = type.GetGenericArguments();
-
if (attrs.Length == 1)
{
- return CreateMonoSkeletonFactory(attrs[0], genericArguments);
+ return CreateMonoSkeletonFactory(attrs[0].Attr, attrs[0].Generics);
}
else
{
- var monoFactories = attrs.Select(a => CreateMonoSkeletonFactory(a, genericArguments)).ToArray();
+ var monoFactories = attrs.Select(a => CreateMonoSkeletonFactory(a.Attr, a.Generics)).ToArray();
return new PolySkeletonFactory(monoFactories);
}
}
@@ -174,7 +173,7 @@ namespace Capnp.Rpc
try
{
var attrs = type
- .GetCustomAttributes(typeof(ProxyAttribute), true)
+ .GetCustomAttributes(typeof(ProxyAttribute), false)
.Cast()
.ToArray();
diff --git a/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj b/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj
index 0f3fa11..cf329b9 100644
--- a/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj
+++ b/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj
@@ -10,7 +10,10 @@
+
+
+
@@ -24,6 +27,7 @@
+
@@ -37,6 +41,7 @@
+
diff --git a/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature
index 239fd3d..8952e00 100644
--- a/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature
+++ b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature
@@ -46,3 +46,12 @@ Scenario: Multiple errors
Then the invocation must fail
And the reason must be bad input
And the error output must contain multiple messages
+
+Scenario Outline: Valid generator output
+ Given I have a binary code generator request
+ When I invoke capnpc-csharp
+ Then the invocation must succeed and the generated code must compile
+
+Examples:
+ | bin |
+ | Issue19.capnp.bin |
diff --git a/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs
index c01b9e3..0fdc738 100644
--- a/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs
+++ b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs
@@ -241,6 +241,34 @@ this.ScenarioInitialize(scenarioInfo);
#line hidden
this.ScenarioCleanup();
}
+
+ public virtual void ValidGeneratorOutput(string bin, string[] exampleTags)
+ {
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Valid generator output", null, exampleTags);
+#line 50
+this.ScenarioInitialize(scenarioInfo);
+ this.ScenarioStart();
+#line 51
+ testRunner.Given(string.Format("I have a binary code generator request {0}", bin), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
+#line 52
+ testRunner.When("I invoke capnpc-csharp", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
+#line 53
+ testRunner.Then("the invocation must succeed and the generated code must compile", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
+#line hidden
+ this.ScenarioCleanup();
+ }
+
+ [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
+ [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Issue19.capnp.bin")]
+ [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
+ [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Issue19.capnp.bin")]
+ [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "Issue19.capnp.bin")]
+ public virtual void ValidGeneratorOutput_Issue19_Capnp_Bin()
+ {
+#line 50
+this.ValidGeneratorOutput("Issue19.capnp.bin", ((string[])(null)));
+#line hidden
+ }
}
}
#pragma warning restore
diff --git a/CapnpC.CSharp.Generator.Tests/Embedded Resources/Issue19.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/Issue19.capnp.bin
new file mode 100644
index 0000000..31aca23
Binary files /dev/null and b/CapnpC.CSharp.Generator.Tests/Embedded Resources/Issue19.capnp.bin differ
diff --git a/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs b/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs
index c539e1c..ee75822 100644
--- a/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs
+++ b/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs
@@ -102,6 +102,13 @@ namespace CapnpC.CSharp.Generator.Tests
Assert.IsNotNull(_result.Exception, "Expected an exception");
}
+ [Then(@"the invocation must succeed and the generated code must compile")]
+ public void ThenTheInvocationMustSucceedAndTheGeneratedCodeMustCompile()
+ {
+ Assert.IsTrue(_result.IsSuccess, "Tool invocation was not successful");
+ Assert.IsTrue(Util.InlineAssemblyCompiler.TryCompileCapnp(_result.GeneratedFiles[0].GeneratedContent), "Compilation was not successful");
+ }
+
[Given(@"capnp\.exe is installed on my system")]
public void GivenCapnp_ExeIsInstalledOnMySystem()
{
diff --git a/CapnpC.CSharp.Generator.Tests/Util/InlineAssemblyCompiler.cs b/CapnpC.CSharp.Generator.Tests/Util/InlineAssemblyCompiler.cs
new file mode 100644
index 0000000..7abc30f
--- /dev/null
+++ b/CapnpC.CSharp.Generator.Tests/Util/InlineAssemblyCompiler.cs
@@ -0,0 +1,49 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Text;
+
+namespace CapnpC.CSharp.Generator.Tests.Util
+{
+ class InlineAssemblyCompiler
+ {
+ public static bool TryCompileCapnp(string code)
+ {
+ var options = new CSharpCompilationOptions(
+ OutputKind.DynamicallyLinkedLibrary,
+ optimizationLevel: OptimizationLevel.Debug);
+
+ SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
+
+ string assemblyRoot = Path.GetDirectoryName(typeof(object).Assembly.Location);
+
+ string capnpRuntimePath = Path.GetFullPath(Path.Combine(
+ Assembly.GetExecutingAssembly().Location,
+ @"..\..\..\..\..\Capnp.Net.Runtime\bin\Debug\netcoreapp2.1\Capnp.Net.Runtime.dll"));
+
+ var capnpRuntimeMetadataRef = MetadataReference.CreateFromFile(capnpRuntimePath);
+
+ var compilation = CSharpCompilation.Create(
+ "CompilationTestAssembly",
+ options: options,
+ references: new MetadataReference[] {
+ MetadataReference.CreateFromFile(Path.Combine(assemblyRoot, "mscorlib.dll")),
+ MetadataReference.CreateFromFile(Path.Combine(assemblyRoot, "System.dll")),
+ MetadataReference.CreateFromFile(Path.Combine(assemblyRoot, "System.Core.dll")),
+ MetadataReference.CreateFromFile(Path.Combine(assemblyRoot, "System.Runtime.dll")),
+ MetadataReference.CreateFromFile(Path.Combine(assemblyRoot, "System.Private.CoreLib.dll")),
+ capnpRuntimeMetadataRef },
+ syntaxTrees: new SyntaxTree[] { syntaxTree });
+
+ using (var stream = new MemoryStream())
+ {
+ var emitResult = compilation.Emit(stream);
+
+ return emitResult.Success;
+ }
+ }
+ }
+}
diff --git a/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs b/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs
index 5476c2f..2a2f9dd 100644
--- a/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs
+++ b/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs
@@ -283,7 +283,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
var allMethods =
from c in Types.FromDefinition(type).AllImplementedClasses
- from m in c.Definition.Methods
+ from m in c.Methods
select m;
foreach (var method in allMethods)
diff --git a/CapnpC.CSharp.Generator/Model/AbstractType.cs b/CapnpC.CSharp.Generator/Model/AbstractType.cs
index 6b6d4c7..0107e08 100644
--- a/CapnpC.CSharp.Generator/Model/AbstractType.cs
+++ b/CapnpC.CSharp.Generator/Model/AbstractType.cs
@@ -5,7 +5,6 @@ namespace CapnpC.CSharp.Generator.Model
abstract class AbstractType
{
public TypeTag Tag { get; set; }
- protected List Fields { get; } = new List();
public uint? FixedBitWidth
{
diff --git a/CapnpC.CSharp.Generator/Model/Method.cs b/CapnpC.CSharp.Generator/Model/Method.cs
index 1d1ba7b..f7f2109 100644
--- a/CapnpC.CSharp.Generator/Model/Method.cs
+++ b/CapnpC.CSharp.Generator/Model/Method.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Linq;
namespace CapnpC.CSharp.Generator.Model
{
@@ -12,5 +13,21 @@ namespace CapnpC.CSharp.Generator.Model
public Type ParamsStruct { get; set; }
public Type ResultStruct { get; set; }
public List GenericParameters { get; } = new List();
+
+ public Method Clone()
+ {
+ var method = new Method()
+ {
+ DeclaringInterface = DeclaringInterface,
+ Id = Id,
+ Name = Name,
+ ParamsStruct = ParamsStruct,
+ ResultStruct = ResultStruct
+ };
+ method.Params.AddRange(Params.Select((p => p.Clone())));
+ method.Results.AddRange(Results.Select(r => r.Clone()));
+ method.GenericParameters.AddRange(GenericParameters);
+ return method;
+ }
}
}
diff --git a/CapnpC.CSharp.Generator/Model/SchemaModel.cs b/CapnpC.CSharp.Generator/Model/SchemaModel.cs
index 9d9e223..f0b9c88 100644
--- a/CapnpC.CSharp.Generator/Model/SchemaModel.cs
+++ b/CapnpC.CSharp.Generator/Model/SchemaModel.cs
@@ -648,8 +648,9 @@ namespace CapnpC.CSharp.Generator.Model
{
foreach (var superClassReader in ifaceReader.Interface_Superclasses)
{
- var superClass = ProcessTypeDef(superClassReader.Id, state, TypeTag.Interface);
- def.Superclasses.Add(Types.FromDefinition(superClass));
+ var superClass = Types.FromDefinition(ProcessTypeDef(superClassReader.Id, state, TypeTag.Interface));
+ ProcessBrand(superClassReader.Brand, superClass, state);
+ def.Superclasses.Add(superClass);
}
return ProcessInterfaceOrStructTail(def, ifaceReader, state);
diff --git a/CapnpC.CSharp.Generator/Model/Type.cs b/CapnpC.CSharp.Generator/Model/Type.cs
index 087f507..a48665e 100644
--- a/CapnpC.CSharp.Generator/Model/Type.cs
+++ b/CapnpC.CSharp.Generator/Model/Type.cs
@@ -83,7 +83,7 @@ namespace CapnpC.CSharp.Generator.Model
}
else
{
- return Types.AnyPointer;
+ return type;
}
}
@@ -117,7 +117,25 @@ namespace CapnpC.CSharp.Generator.Model
return result;
}
- public new IReadOnlyList Fields => Definition.Fields.LazyListSelect(SubstituteGenerics);
+ Method SubstituteGenerics(Method method)
+ {
+ var result = method.Clone();
+ result.ParamsStruct = SubstituteGenerics(result.ParamsStruct);
+ result.ResultStruct = SubstituteGenerics(result.ResultStruct);
+ foreach (var field in result.Params)
+ {
+ field.Type = SubstituteGenerics(field.Type);
+ }
+ foreach (var field in result.Results)
+ {
+ field.Type = SubstituteGenerics(field.Type);
+ }
+ return result;
+ }
+
+ public IReadOnlyList Fields => Definition.Fields.LazyListSelect(SubstituteGenerics);
+
+ public IReadOnlyList Methods => Definition.Methods.LazyListSelect(SubstituteGenerics);
public Type DeclaringType
{
diff --git a/CapnpC.CSharp.Generator/Model/TypeDefinition.cs b/CapnpC.CSharp.Generator/Model/TypeDefinition.cs
index 9a0557c..61e8e64 100644
--- a/CapnpC.CSharp.Generator/Model/TypeDefinition.cs
+++ b/CapnpC.CSharp.Generator/Model/TypeDefinition.cs
@@ -39,7 +39,7 @@ namespace CapnpC.CSharp.Generator.Model
public string Name { get; set; }
public SpecialName SpecialName { get; set; }
public DiscriminationInfo UnionInfo { get; set; }
- public new List Fields => base.Fields;
+ public List Fields { get; } = new List();
public List Enumerants { get; } = new List();
public ICollection NestedDefinitions { get; } = new List();
public IEnumerable NestedTypes { get => this.GetNestedTypes(); }
diff --git a/MsBuildGenerationTest/Issue19.capnp b/MsBuildGenerationTest/Issue19.capnp
new file mode 100644
index 0000000..28aebd2
--- /dev/null
+++ b/MsBuildGenerationTest/Issue19.capnp
@@ -0,0 +1,9 @@
+@0xe169e9301753ca94;
+
+interface GenericA(T) {
+ methodA @0 (param1 :T) -> ();
+}
+
+interface B2 extends (GenericA(Text)) {
+ methodB @0 (param1 :Int64) -> (res :Text);
+}
diff --git a/MsBuildGenerationTest/MsBuildGenerationTest.csproj b/MsBuildGenerationTest/MsBuildGenerationTest.csproj
index b1dd49e..930a851 100644
--- a/MsBuildGenerationTest/MsBuildGenerationTest.csproj
+++ b/MsBuildGenerationTest/MsBuildGenerationTest.csproj
@@ -8,6 +8,14 @@
$(Version)*
+
+
+
+
+
+
+
+
@@ -55,4 +63,10 @@
+
+
+ Issue19.capnp
+
+
+
diff --git a/appveyor.yml b/appveyor.yml
index eb8fafe..7d8f6c5 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-version: '1.1.{build}'
+version: '1.2.{build}'
image: Visual Studio 2019
# branches:
# only:
diff --git a/capnpc-csharp/capnpc-csharp.csproj b/capnpc-csharp/capnpc-csharp.csproj
index 6b51e8e..373c3a3 100644
--- a/capnpc-csharp/capnpc-csharp.csproj
+++ b/capnpc-csharp/capnpc-csharp.csproj
@@ -13,7 +13,7 @@
https://github.com/c80k/capnproto-dotnetcore
Git
capnp capnpc RPC serialization cerealization
- 1.1.0
+ 1.2.0
Debug;Release