This commit is contained in:
Christian Köllner 2019-10-19 13:52:16 +02:00
parent 4637b4c4cf
commit 44d5f7a08c
22 changed files with 551 additions and 17 deletions

View File

@ -14,6 +14,7 @@
<Compile Include="..\Capnp.Net.Runtime.Tests\DynamicSerializerStateTests.cs" Link="DynamicSerializerStateTests.cs" /> <Compile Include="..\Capnp.Net.Runtime.Tests\DynamicSerializerStateTests.cs" Link="DynamicSerializerStateTests.cs" />
<Compile Include="..\Capnp.Net.Runtime.Tests\FramePumpTests.cs" Link="FramePumpTests.cs" /> <Compile Include="..\Capnp.Net.Runtime.Tests\FramePumpTests.cs" Link="FramePumpTests.cs" />
<Compile Include="..\Capnp.Net.Runtime.Tests\General.cs" Link="General.cs" /> <Compile Include="..\Capnp.Net.Runtime.Tests\General.cs" Link="General.cs" />
<Compile Include="..\Capnp.Net.Runtime.Tests\Issue19.cs" Link="Issue19.cs" />
<Compile Include="..\Capnp.Net.Runtime.Tests\JobUtil.cs" Link="JobUtil.cs" /> <Compile Include="..\Capnp.Net.Runtime.Tests\JobUtil.cs" Link="JobUtil.cs" />
<Compile Include="..\Capnp.Net.Runtime.Tests\MessageBuilderTests.cs" Link="MessageBuilderTests.cs" /> <Compile Include="..\Capnp.Net.Runtime.Tests\MessageBuilderTests.cs" Link="MessageBuilderTests.cs" />
<Compile Include="..\Capnp.Net.Runtime.Tests\ProvidedCapabilityMock.cs" Link="ProvidedCapabilityMock.cs" /> <Compile Include="..\Capnp.Net.Runtime.Tests\ProvidedCapabilityMock.cs" Link="ProvidedCapabilityMock.cs" />

View File

@ -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<TT> : IDisposable where TT : class
{
Task MethodA(TT param1, CancellationToken cancellationToken_ = default);
}
public class GenericAProxy<TT> : Proxy, IGenericA<TT> where TT : class
{
public async Task MethodA(TT param1, CancellationToken cancellationToken_ = default)
{
var in_ = SerializerState.CreateForRpc<CapnpGen.GenericA<TT>.Params_methodA.WRITER>();
var arg_ = new CapnpGen.GenericA<TT>.Params_methodA()
{Param1 = param1};
arg_.serialize(in_);
var d_ = await Call(10341943558714247093UL, 0, in_.Rewrap<DynamicSerializerState>(), false, cancellationToken_).WhenReturned;
var r_ = CapnpSerializable.Create<CapnpGen.GenericA<TT>.Result_methodA>(d_);
return;
}
}
public class GenericASkeleton<TT> : Skeleton<IGenericA<TT>> where TT : class
{
public GenericASkeleton()
{
SetMethodTable(MethodA);
}
public override ulong InterfaceId => 10341943558714247093UL;
async Task<AnswerOrCounterquestion> MethodA(DeserializerState d_, CancellationToken cancellationToken_)
{
var in_ = CapnpSerializable.Create<CapnpGen.GenericA<TT>.Params_methodA>(d_);
await Impl.MethodA(in_.Param1, cancellationToken_);
var s_ = SerializerState.CreateForRpc<CapnpGen.GenericA<TT>.Result_methodA.WRITER>();
return s_;
}
}
public static class GenericA<TT>
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<TT>(reader.Param1);
applyDefaults();
}
public void serialize(WRITER writer)
{
writer.Param1.SetObject(Param1);
}
void ICapnpSerializable.Serialize(SerializerState arg_)
{
serialize(arg_.Rewrap<WRITER>());
}
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<DynamicSerializerState>(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<WRITER>());
}
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<string>
{
Task<string> MethodB(long param1, CancellationToken cancellationToken_ = default);
}
public class B2Proxy : Proxy, IB2
{
public async Task<string> MethodB(long param1, CancellationToken cancellationToken_ = default)
{
var in_ = SerializerState.CreateForRpc<CapnpGen.B2.Params_methodB.WRITER>();
var arg_ = new CapnpGen.B2.Params_methodB()
{Param1 = param1};
arg_.serialize(in_);
var d_ = await Call(16414937344734980809UL, 0, in_.Rewrap<DynamicSerializerState>(), false, cancellationToken_).WhenReturned;
var r_ = CapnpSerializable.Create<CapnpGen.B2.Result_methodB>(d_);
return (r_.Res);
}
public async Task MethodA(string param1, CancellationToken cancellationToken_ = default)
{
var in_ = SerializerState.CreateForRpc<CapnpGen.GenericA<string>.Params_methodA.WRITER>();
var arg_ = new CapnpGen.GenericA<string>.Params_methodA()
{Param1 = param1};
arg_.serialize(in_);
var d_ = await Call(10341943558714247093UL, 0, in_.Rewrap<DynamicSerializerState>(), false, cancellationToken_).WhenReturned;
var r_ = CapnpSerializable.Create<CapnpGen.GenericA<string>.Result_methodA>(d_);
return;
}
}
public class B2Skeleton : Skeleton<IB2>
{
public B2Skeleton()
{
SetMethodTable(MethodB);
}
public override ulong InterfaceId => 16414937344734980809UL;
Task<AnswerOrCounterquestion> MethodB(DeserializerState d_, CancellationToken cancellationToken_)
{
var in_ = CapnpSerializable.Create<CapnpGen.B2.Params_methodB>(d_);
return Impatient.MaybeTailCall(Impl.MethodB(in_.Param1, cancellationToken_), res =>
{
var s_ = SerializerState.CreateForRpc<CapnpGen.B2.Result_methodB.WRITER>();
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<WRITER>());
}
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<WRITER>());
}
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, "");
}
}
}
}
}

View File

@ -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<CapnpGen.IB2>())
{
Assert.IsTrue(main.MethodA("42").Wait(MediumNonDbgTimeout));
var b = main.MethodB(123);
Assert.IsTrue(b.Wait(MediumNonDbgTimeout));
Assert.AreEqual("42", b.Result);
}
}
}
}
} }
} }

View File

@ -753,4 +753,27 @@ namespace Capnp.Net.Runtime.Tests.GenImpls
} }
} }
#endregion TestHandle #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<string> MethodB(long param1, CancellationToken cancellationToken_ = default)
{
return Task.FromResult(_s);
}
}
#endregion B2
} }

View File

@ -18,7 +18,7 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>Git</RepositoryType> <RepositoryType>Git</RepositoryType>
<PackageTags>capnp "Cap'n Proto" RPC serialization cerealization</PackageTags> <PackageTags>capnp "Cap'n Proto" RPC serialization cerealization</PackageTags>
<Version>1.1-local$([System.DateTime]::UtcNow.ToString(yyMMddHHmm))</Version> <Version>1.2-local$([System.DateTime]::UtcNow.ToString(yyMMddHHmm))</Version>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
</PropertyGroup> </PropertyGroup>

View File

@ -119,21 +119,20 @@ namespace Capnp.Rpc
try try
{ {
var attrs = (from iface in _.GetInterfaces() var attrs = (from iface in _.GetInterfaces()
from attr in iface.GetCustomAttributes(typeof(SkeletonAttribute), true) let generics = iface.GetGenericArguments()
select (SkeletonAttribute)attr).ToArray(); from attr in iface.GetCustomAttributes(typeof(SkeletonAttribute), false)
select (Attr: (SkeletonAttribute)attr, Generics: generics)).ToArray();
if (attrs.Length == 0) if (attrs.Length == 0)
throw new InvalidCapabilityInterfaceException("No 'Skeleton' attribute defined, don't know how to create the skeleton"); throw new InvalidCapabilityInterfaceException("No 'Skeleton' attribute defined, don't know how to create the skeleton");
Type[] genericArguments = type.GetGenericArguments();
if (attrs.Length == 1) if (attrs.Length == 1)
{ {
return CreateMonoSkeletonFactory(attrs[0], genericArguments); return CreateMonoSkeletonFactory(attrs[0].Attr, attrs[0].Generics);
} }
else 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); return new PolySkeletonFactory(monoFactories);
} }
} }
@ -174,7 +173,7 @@ namespace Capnp.Rpc
try try
{ {
var attrs = type var attrs = type
.GetCustomAttributes(typeof(ProxyAttribute), true) .GetCustomAttributes(typeof(ProxyAttribute), false)
.Cast<ProxyAttribute>() .Cast<ProxyAttribute>()
.ToArray(); .ToArray();

View File

@ -10,7 +10,10 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.3.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.3.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="Mono.Cecil" Version="0.11.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> <PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> <PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
<PackageReference Include="SpecFlow" Version="3.0.225" /> <PackageReference Include="SpecFlow" Version="3.0.225" />
@ -24,6 +27,7 @@
<None Remove="Embedded Resources\Empty.capnp" /> <None Remove="Embedded Resources\Empty.capnp" />
<None Remove="Embedded Resources\Empty1.capnp" /> <None Remove="Embedded Resources\Empty1.capnp" />
<None Remove="Embedded Resources\invalid.capnp" /> <None Remove="Embedded Resources\invalid.capnp" />
<None Remove="Embedded Resources\Issue19.capnp.bin" />
<None Remove="Embedded Resources\null.bin" /> <None Remove="Embedded Resources\null.bin" />
<None Remove="Embedded Resources\test.capnp" /> <None Remove="Embedded Resources\test.capnp" />
<None Remove="Embedded Resources\test.capnp.bin" /> <None Remove="Embedded Resources\test.capnp.bin" />
@ -37,6 +41,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Embedded Resources\Issue19.capnp.bin" />
<EmbeddedResource Include="Embedded Resources\Empty.capnp" /> <EmbeddedResource Include="Embedded Resources\Empty.capnp" />
<EmbeddedResource Include="Embedded Resources\Empty1.capnp" /> <EmbeddedResource Include="Embedded Resources\Empty1.capnp" />
<EmbeddedResource Include="Embedded Resources\invalid.capnp" /> <EmbeddedResource Include="Embedded Resources\invalid.capnp" />

View File

@ -46,3 +46,12 @@ Scenario: Multiple errors
Then the invocation must fail Then the invocation must fail
And the reason must be bad input And the reason must be bad input
And the error output must contain multiple messages And the error output must contain multiple messages
Scenario Outline: Valid generator output
Given I have a binary code generator request <bin>
When I invoke capnpc-csharp
Then the invocation must succeed and the generated code must compile
Examples:
| bin |
| Issue19.capnp.bin |

View File

@ -241,6 +241,34 @@ this.ScenarioInitialize(scenarioInfo);
#line hidden #line hidden
this.ScenarioCleanup(); 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 #pragma warning restore

View File

@ -102,6 +102,13 @@ namespace CapnpC.CSharp.Generator.Tests
Assert.IsNotNull(_result.Exception, "Expected an exception"); 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")] [Given(@"capnp\.exe is installed on my system")]
public void GivenCapnp_ExeIsInstalledOnMySystem() public void GivenCapnp_ExeIsInstalledOnMySystem()
{ {

View File

@ -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;
}
}
}
}

View File

@ -283,7 +283,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
var allMethods = var allMethods =
from c in Types.FromDefinition(type).AllImplementedClasses from c in Types.FromDefinition(type).AllImplementedClasses
from m in c.Definition.Methods from m in c.Methods
select m; select m;
foreach (var method in allMethods) foreach (var method in allMethods)

View File

@ -5,7 +5,6 @@ namespace CapnpC.CSharp.Generator.Model
abstract class AbstractType abstract class AbstractType
{ {
public TypeTag Tag { get; set; } public TypeTag Tag { get; set; }
protected List<Field> Fields { get; } = new List<Field>();
public uint? FixedBitWidth public uint? FixedBitWidth
{ {

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace CapnpC.CSharp.Generator.Model namespace CapnpC.CSharp.Generator.Model
{ {
@ -12,5 +13,21 @@ namespace CapnpC.CSharp.Generator.Model
public Type ParamsStruct { get; set; } public Type ParamsStruct { get; set; }
public Type ResultStruct { get; set; } public Type ResultStruct { get; set; }
public List<string> GenericParameters { get; } = new List<string>(); public List<string> GenericParameters { get; } = new List<string>();
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;
}
} }
} }

View File

@ -648,8 +648,9 @@ namespace CapnpC.CSharp.Generator.Model
{ {
foreach (var superClassReader in ifaceReader.Interface_Superclasses) foreach (var superClassReader in ifaceReader.Interface_Superclasses)
{ {
var superClass = ProcessTypeDef(superClassReader.Id, state, TypeTag.Interface); var superClass = Types.FromDefinition(ProcessTypeDef(superClassReader.Id, state, TypeTag.Interface));
def.Superclasses.Add(Types.FromDefinition(superClass)); ProcessBrand(superClassReader.Brand, superClass, state);
def.Superclasses.Add(superClass);
} }
return ProcessInterfaceOrStructTail(def, ifaceReader, state); return ProcessInterfaceOrStructTail(def, ifaceReader, state);

View File

@ -83,7 +83,7 @@ namespace CapnpC.CSharp.Generator.Model
} }
else else
{ {
return Types.AnyPointer; return type;
} }
} }
@ -117,7 +117,25 @@ namespace CapnpC.CSharp.Generator.Model
return result; return result;
} }
public new IReadOnlyList<Field> 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<Field> Fields => Definition.Fields.LazyListSelect(SubstituteGenerics);
public IReadOnlyList<Method> Methods => Definition.Methods.LazyListSelect(SubstituteGenerics);
public Type DeclaringType public Type DeclaringType
{ {

View File

@ -39,7 +39,7 @@ namespace CapnpC.CSharp.Generator.Model
public string Name { get; set; } public string Name { get; set; }
public SpecialName SpecialName { get; set; } public SpecialName SpecialName { get; set; }
public DiscriminationInfo UnionInfo { get; set; } public DiscriminationInfo UnionInfo { get; set; }
public new List<Field> Fields => base.Fields; public List<Field> Fields { get; } = new List<Field>();
public List<Enumerant> Enumerants { get; } = new List<Enumerant>(); public List<Enumerant> Enumerants { get; } = new List<Enumerant>();
public ICollection<IDefinition> NestedDefinitions { get; } = new List<IDefinition>(); public ICollection<IDefinition> NestedDefinitions { get; } = new List<IDefinition>();
public IEnumerable<TypeDefinition> NestedTypes { get => this.GetNestedTypes(); } public IEnumerable<TypeDefinition> NestedTypes { get => this.GetNestedTypes(); }

View File

@ -0,0 +1,9 @@
@0xe169e9301753ca94;
interface GenericA(T) {
methodA @0 (param1 :T) -> ();
}
interface B2 extends (GenericA(Text)) {
methodB @0 (param1 :Int64) -> (res :Text);
}

View File

@ -8,6 +8,14 @@
<PackageReferenceVersion Condition="'$(PackageReferenceVersion)'==''">$(Version)*</PackageReferenceVersion> <PackageReferenceVersion Condition="'$(PackageReferenceVersion)'==''">$(Version)*</PackageReferenceVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<CapnpCsharpObsoleteCodeBehindFiles Remove="capnp\bergm.capnp.cs" />
</ItemGroup>
<ItemGroup>
<None Remove="capnp\bergm.capnp.bin" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Capnp.Net.Runtime" Version="$(PackageReferenceVersion)" /> <PackageReference Include="Capnp.Net.Runtime" Version="$(PackageReferenceVersion)" />
<PackageReference Include="CapnpC.CSharp.MsBuild.Generation" Version="$(PackageReferenceVersion)" /> <PackageReference Include="CapnpC.CSharp.MsBuild.Generation" Version="$(PackageReferenceVersion)" />
@ -55,4 +63,10 @@
</CapnpFiles> </CapnpFiles>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Compile Update="issue19.capnp.cs">
<DependentUpon>Issue19.capnp</DependentUpon>
</Compile>
</ItemGroup>
</Project> </Project>

View File

@ -1,4 +1,4 @@
version: '1.1.{build}' version: '1.2.{build}'
image: Visual Studio 2019 image: Visual Studio 2019
# branches: # branches:
# only: # only:

View File

@ -13,7 +13,7 @@
<PackageProjectUrl>https://github.com/c80k/capnproto-dotnetcore</PackageProjectUrl> <PackageProjectUrl>https://github.com/c80k/capnproto-dotnetcore</PackageProjectUrl>
<RepositoryType>Git</RepositoryType> <RepositoryType>Git</RepositoryType>
<PackageTags>capnp capnpc RPC serialization cerealization</PackageTags> <PackageTags>capnp capnpc RPC serialization cerealization</PackageTags>
<Version>1.1.0</Version> <Version>1.2.0</Version>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
</PropertyGroup> </PropertyGroup>