mirror of
https://github.com/FabInfra/capnproto-dotnetcore_Runtime.git
synced 2025-03-12 14:51:41 +01:00
Issue #19
This commit is contained in:
parent
4637b4c4cf
commit
44d5f7a08c
@ -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" />
|
||||||
|
332
Capnp.Net.Runtime.Tests/Issue19.cs
Normal file
332
Capnp.Net.Runtime.Tests/Issue19.cs
Normal 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, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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" />
|
||||||
|
@ -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 |
|
||||||
|
@ -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
|
||||||
|
Binary file not shown.
@ -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()
|
||||||
{
|
{
|
||||||
|
49
CapnpC.CSharp.Generator.Tests/Util/InlineAssemblyCompiler.cs
Normal file
49
CapnpC.CSharp.Generator.Tests/Util/InlineAssemblyCompiler.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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(); }
|
||||||
|
9
MsBuildGenerationTest/Issue19.capnp
Normal file
9
MsBuildGenerationTest/Issue19.capnp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
@0xe169e9301753ca94;
|
||||||
|
|
||||||
|
interface GenericA(T) {
|
||||||
|
methodA @0 (param1 :T) -> ();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B2 extends (GenericA(Text)) {
|
||||||
|
methodB @0 (param1 :Int64) -> (res :Text);
|
||||||
|
}
|
@ -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>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: '1.1.{build}'
|
version: '1.2.{build}'
|
||||||
image: Visual Studio 2019
|
image: Visual Studio 2019
|
||||||
# branches:
|
# branches:
|
||||||
# only:
|
# only:
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user