mirror of
https://github.com/FabInfra/capnproto-dotnetcore_Runtime.git
synced 2025-03-12 06:41:50 +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\FramePumpTests.cs" Link="FramePumpTests.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\MessageBuilderTests.cs" Link="MessageBuilderTests.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
|
||||
|
||||
#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>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<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>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -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<ProxyAttribute>()
|
||||
.ToArray();
|
||||
|
||||
|
@ -10,7 +10,10 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<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="Mono.Cecil" Version="0.11.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
|
||||
<PackageReference Include="SpecFlow" Version="3.0.225" />
|
||||
@ -24,6 +27,7 @@
|
||||
<None Remove="Embedded Resources\Empty.capnp" />
|
||||
<None Remove="Embedded Resources\Empty1.capnp" />
|
||||
<None Remove="Embedded Resources\invalid.capnp" />
|
||||
<None Remove="Embedded Resources\Issue19.capnp.bin" />
|
||||
<None Remove="Embedded Resources\null.bin" />
|
||||
<None Remove="Embedded Resources\test.capnp" />
|
||||
<None Remove="Embedded Resources\test.capnp.bin" />
|
||||
@ -37,6 +41,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Embedded Resources\Issue19.capnp.bin" />
|
||||
<EmbeddedResource Include="Embedded Resources\Empty.capnp" />
|
||||
<EmbeddedResource Include="Embedded Resources\Empty1.capnp" />
|
||||
<EmbeddedResource Include="Embedded Resources\invalid.capnp" />
|
||||
|
@ -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 <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
|
||||
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
|
||||
|
Binary file not shown.
@ -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()
|
||||
{
|
||||
|
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 =
|
||||
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)
|
||||
|
@ -5,7 +5,6 @@ namespace CapnpC.CSharp.Generator.Model
|
||||
abstract class AbstractType
|
||||
{
|
||||
public TypeTag Tag { get; set; }
|
||||
protected List<Field> Fields { get; } = new List<Field>();
|
||||
|
||||
public uint? FixedBitWidth
|
||||
{
|
||||
|
@ -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<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)
|
||||
{
|
||||
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);
|
||||
|
@ -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<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
|
||||
{
|
||||
|
@ -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<Field> Fields => base.Fields;
|
||||
public List<Field> Fields { get; } = new List<Field>();
|
||||
public List<Enumerant> Enumerants { get; } = new List<Enumerant>();
|
||||
public ICollection<IDefinition> NestedDefinitions { get; } = new List<IDefinition>();
|
||||
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>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<CapnpCsharpObsoleteCodeBehindFiles Remove="capnp\bergm.capnp.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="capnp\bergm.capnp.bin" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Capnp.Net.Runtime" Version="$(PackageReferenceVersion)" />
|
||||
<PackageReference Include="CapnpC.CSharp.MsBuild.Generation" Version="$(PackageReferenceVersion)" />
|
||||
@ -55,4 +63,10 @@
|
||||
</CapnpFiles>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="issue19.capnp.cs">
|
||||
<DependentUpon>Issue19.capnp</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: '1.1.{build}'
|
||||
version: '1.2.{build}'
|
||||
image: Visual Studio 2019
|
||||
# branches:
|
||||
# only:
|
||||
|
@ -13,7 +13,7 @@
|
||||
<PackageProjectUrl>https://github.com/c80k/capnproto-dotnetcore</PackageProjectUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<PackageTags>capnp capnpc RPC serialization cerealization</PackageTags>
|
||||
<Version>1.1.0</Version>
|
||||
<Version>1.2.0</Version>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user