support several new codegen annotations

minor fixes
improved CC
This commit is contained in:
Christian Köllner 2020-03-26 21:30:30 +01:00
parent 9dbf474334
commit 6af523b261
20 changed files with 2219 additions and 240 deletions

View File

@ -1,5 +1,7 @@
using Capnp.Rpc; using Capnp.Rpc;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
namespace Capnp.Net.Runtime.Tests namespace Capnp.Net.Runtime.Tests
{ {
@ -366,5 +368,402 @@ namespace Capnp.Net.Runtime.Tests
Assert.AreEqual("reason", r.Unimplemented.Resolve.Exception.Reason); Assert.AreEqual("reason", r.Unimplemented.Resolve.Exception.Reason);
} }
} }
void ConstructReconstructTest<TD, TW>(Func<TD> construct, Action<TD> verify)
where TD : class, ICapnpSerializable, new()
where TW: SerializerState, new()
{
var obj = construct();
var mb = MessageBuilder.Create();
var root = mb.BuildRoot<TW>();
obj.Serialize(root);
var d = (DeserializerState)root;
var obj2 = new TD();
obj2.Deserialize(d);
verify(obj2);
}
[TestMethod]
public void DcMessageAbort()
{
ConstructReconstructTest<Message, Message.WRITER>(
() => new Message()
{
Abort = new Rpc.Exception()
{
Reason = "problem"
}
},
msg =>
{
Assert.IsNotNull(msg.Abort);
Assert.IsNull(msg.Accept);
Assert.AreEqual("problem", msg.Abort.Reason);
}
);
}
[TestMethod]
public void DcMessageAccept()
{
ConstructReconstructTest<Message, Message.WRITER>(
() => new Message()
{
Accept = new Accept()
{
QuestionId = 123u,
Embargo = true
}
},
msg =>
{
Assert.IsNotNull(msg.Accept);
Assert.AreEqual(123u, msg.Accept.QuestionId);
Assert.IsTrue(msg.Accept.Embargo);
}
);
}
[TestMethod]
public void DcMessageUnimplementedJoin()
{
ConstructReconstructTest<Message, Message.WRITER>(
() => new Message()
{
Unimplemented = new Message()
{
Join = new Join()
{
QuestionId = 456u,
Target = new MessageTarget()
{
ImportedCap = 789u
}
}
}
},
msg =>
{
Assert.IsNotNull(msg.Unimplemented);
Assert.IsNotNull(msg.Unimplemented.Join);
Assert.AreEqual(456u, msg.Unimplemented.Join.QuestionId);
Assert.IsNotNull(msg.Unimplemented.Join.Target);
Assert.AreEqual(789u, msg.Unimplemented.Join.Target.ImportedCap);
}
);
}
[TestMethod]
public void DcMessageCall()
{
ConstructReconstructTest<Message, Message.WRITER>(
() => new Message()
{
Call = new Call()
{
AllowThirdPartyTailCall = true,
InterfaceId = 0x12345678abcdef,
MethodId = 0x5555,
Params = new Payload()
{
CapTable = new List<CapDescriptor>()
{
new CapDescriptor()
{
ReceiverAnswer = new PromisedAnswer()
{
QuestionId = 42u,
Transform = new List<PromisedAnswer.Op>()
{
new PromisedAnswer.Op()
{
GetPointerField = 3
}
}
},
},
new CapDescriptor()
{
ReceiverHosted = 7u
},
new CapDescriptor()
{
SenderHosted = 8u
},
new CapDescriptor()
{
SenderPromise = 9u
},
new CapDescriptor()
{
ThirdPartyHosted = new ThirdPartyCapDescriptor()
{
VineId = 10u
}
}
}
},
QuestionId = 57u,
SendResultsTo = new Call.sendResultsTo()
{
which = Call.sendResultsTo.WHICH.Caller
},
Target = new MessageTarget()
{
PromisedAnswer = new PromisedAnswer()
{
QuestionId = 12u
}
}
}
},
msg =>
{
Assert.IsNotNull(msg.Call);
Assert.IsTrue(msg.Call.AllowThirdPartyTailCall);
Assert.AreEqual(0x12345678abcdeful, msg.Call.InterfaceId);
Assert.AreEqual(0x5555u, msg.Call.MethodId);
Assert.IsNotNull(msg.Call.Params);
Assert.IsNotNull(msg.Call.Params.CapTable);
Assert.AreEqual(5, msg.Call.Params.CapTable.Count);
Assert.IsNotNull(msg.Call.Params.CapTable[0].ReceiverAnswer);
Assert.AreEqual(42u, msg.Call.Params.CapTable[0].ReceiverAnswer.QuestionId);
Assert.IsNotNull(msg.Call.Params.CapTable[0].ReceiverAnswer.Transform);
Assert.AreEqual(1, msg.Call.Params.CapTable[0].ReceiverAnswer.Transform.Count);
Assert.AreEqual((ushort)3, msg.Call.Params.CapTable[0].ReceiverAnswer.Transform[0].GetPointerField);
Assert.AreEqual(7u, msg.Call.Params.CapTable[1].ReceiverHosted);
Assert.AreEqual(8u, msg.Call.Params.CapTable[2].SenderHosted);
Assert.AreEqual(9u, msg.Call.Params.CapTable[3].SenderPromise);
Assert.IsNotNull(msg.Call.Params.CapTable[4].ThirdPartyHosted);
Assert.AreEqual(10u, msg.Call.Params.CapTable[4].ThirdPartyHosted.VineId);
Assert.AreEqual(57u, msg.Call.QuestionId);
Assert.IsNotNull(msg.Call.SendResultsTo);
Assert.AreEqual(Call.sendResultsTo.WHICH.Caller, msg.Call.SendResultsTo.which);
Assert.IsNotNull(msg.Call.Target);
Assert.IsNotNull(msg.Call.Target.PromisedAnswer);
Assert.AreEqual(12u, msg.Call.Target.PromisedAnswer.QuestionId);
}
);
}
[TestMethod]
public void DcMessageReturnResults()
{
ConstructReconstructTest<Message, Message.WRITER>(
() => new Message()
{
Return = new Return()
{
AnswerId = 123u,
ReleaseParamCaps = false,
Results = new Payload()
{
CapTable = new List<CapDescriptor>()
}
}
},
msg =>
{
Assert.IsNotNull(msg.Return);
Assert.AreEqual(123u, msg.Return.AnswerId);
Assert.IsFalse(msg.Return.ReleaseParamCaps);
Assert.IsNotNull(msg.Return.Results);
Assert.IsNotNull(msg.Return.Results.CapTable);
Assert.AreEqual(0, msg.Return.Results.CapTable.Count);
}
);
}
[TestMethod]
public void DcMessageReturnException()
{
ConstructReconstructTest<Message, Message.WRITER>(
() => new Message()
{
Return = new Return()
{
AnswerId = 123u,
ReleaseParamCaps = true,
Exception = new Rpc.Exception()
{
Reason = "bad",
TheType = Rpc.Exception.Type.overloaded
}
}
},
msg =>
{
Assert.IsNotNull(msg.Return);
Assert.AreEqual(123u, msg.Return.AnswerId);
Assert.IsTrue(msg.Return.ReleaseParamCaps);
Assert.IsNotNull(msg.Return.Exception);
Assert.AreEqual("bad", msg.Return.Exception.Reason);
Assert.AreEqual(Rpc.Exception.Type.overloaded, msg.Return.Exception.TheType);
}
);
}
[TestMethod]
public void DcMessageReturnTakeFromOtherQuestion()
{
ConstructReconstructTest<Message, Message.WRITER>(
() => new Message()
{
Return = new Return()
{
AnswerId = 123u,
ReleaseParamCaps = true,
TakeFromOtherQuestion = 321u
}
},
msg =>
{
Assert.IsNotNull(msg.Return);
Assert.AreEqual(123u, msg.Return.AnswerId);
Assert.IsTrue(msg.Return.ReleaseParamCaps);
Assert.AreEqual(321u, msg.Return.TakeFromOtherQuestion);
}
);
}
[TestMethod]
public void DcMessageFinish()
{
ConstructReconstructTest<Message, Message.WRITER>(
() => new Message()
{
Finish = new Finish()
{
QuestionId = 321u,
ReleaseResultCaps = true
}
},
msg =>
{
Assert.IsNotNull(msg.Finish);
Assert.AreEqual(321u, msg.Finish.QuestionId);
Assert.IsTrue(msg.Finish.ReleaseResultCaps);
}
);
}
[TestMethod]
public void DcMessageResolve()
{
ConstructReconstructTest<Message, Message.WRITER>(
() => new Message()
{
Resolve = new Resolve()
{
PromiseId = 555u,
Exception = new Rpc.Exception()
{
Reason = "error",
TheType = Rpc.Exception.Type.failed
}
}
},
msg =>
{
Assert.IsNotNull(msg.Resolve);
Assert.AreEqual(555u, msg.Resolve.PromiseId);
Assert.AreEqual("error", msg.Resolve.Exception.Reason);
Assert.AreEqual(Rpc.Exception.Type.failed, msg.Resolve.Exception.TheType);
}
);
}
[TestMethod]
public void DcMessageRelease()
{
ConstructReconstructTest<Message, Message.WRITER>(
() => new Message()
{
Release = new Release()
{
Id = 6000u,
ReferenceCount = 6u
}
},
msg =>
{
Assert.IsNotNull(msg.Release);
Assert.AreEqual(6000u, msg.Release.Id);
Assert.AreEqual(6u, msg.Release.ReferenceCount);
}
);
}
[TestMethod]
public void DcMessageBootstrap()
{
ConstructReconstructTest<Message, Message.WRITER>(
() => new Message()
{
Bootstrap = new Bootstrap()
{
QuestionId = 99u
}
},
msg =>
{
Assert.IsNotNull(msg.Bootstrap);
Assert.AreEqual(99u, msg.Bootstrap.QuestionId);
}
);
}
[TestMethod]
public void DcMessageProvide()
{
ConstructReconstructTest<Message, Message.WRITER>(
() => new Message()
{
Provide = new Provide()
{
Target = new MessageTarget()
{
ImportedCap = 7u
}
}
},
msg =>
{
Assert.IsNotNull(msg.Provide);
Assert.IsNotNull(msg.Provide.Target);
Assert.AreEqual(7u, msg.Provide.Target.ImportedCap);
}
);
}
[TestMethod]
public void DcMessageDisembargo()
{
ConstructReconstructTest<Message, Message.WRITER>(
() => new Message()
{
Disembargo = new Disembargo()
{
Context = new Disembargo.context()
{
ReceiverLoopback = 900u
},
Target = new MessageTarget()
}
},
msg =>
{
Assert.IsNotNull(msg.Disembargo);
Assert.IsNotNull(msg.Disembargo.Context);
Assert.AreEqual(900u, msg.Disembargo.Context.ReceiverLoopback);
Assert.IsNotNull(msg.Disembargo.Target);
Assert.IsNull(msg.Disembargo.Target.ImportedCap);
Assert.IsNull(msg.Disembargo.Target.PromisedAnswer);
Assert.AreEqual(MessageTarget.WHICH.undefined, msg.Disembargo.Target.which);
}
);
}
} }
} }

View File

@ -229,7 +229,7 @@ namespace Capnp.Rpc
} }
/// <summary> /// <summary>
/// Checkes whether a given type qualifies as cpapbility interface./> on failure. /// Checks whether a given type qualifies as cpapbility interface.
/// </summary> /// </summary>
/// <param name="interfaceType">type to check</param> /// <param name="interfaceType">type to check</param>
/// <returns>true when <paramref name="interfaceType"/> is a capability interface</returns> /// <returns>true when <paramref name="interfaceType"/> is a capability interface</returns>

View File

@ -165,7 +165,7 @@ namespace Capnp.Rpc
SetReturned(); SetReturned();
} }
_tcs.TrySetException(new RpcException(exception.Reason)); _tcs.TrySetException(new RpcException(exception.Reason ?? "unknown reason"));
} }
internal void OnException(System.Exception exception) internal void OnException(System.Exception exception)
@ -313,7 +313,7 @@ namespace Capnp.Rpc
} }
var msg = (Message.WRITER)inParams!.MsgBuilder!.Root!; var msg = (Message.WRITER)inParams!.MsgBuilder!.Root!;
Debug.Assert(msg.Call.Target.which != MessageTarget.WHICH.undefined); Debug.Assert(msg.Call!.Target.which != MessageTarget.WHICH.undefined);
var call = msg.Call; var call = msg.Call;
call.QuestionId = QuestionId; call.QuestionId = QuestionId;
call.SendResultsTo.which = IsTailCall ? call.SendResultsTo.which = IsTailCall ?

View File

@ -101,7 +101,7 @@ namespace Capnp.Rpc
protected override void GetMessageTarget(MessageTarget.WRITER wr) protected override void GetMessageTarget(MessageTarget.WRITER wr)
{ {
wr.which = MessageTarget.WHICH.PromisedAnswer; wr.which = MessageTarget.WHICH.PromisedAnswer;
wr.PromisedAnswer.QuestionId = _question.QuestionId; wr.PromisedAnswer!.QuestionId = _question.QuestionId;
_access.Serialize(wr.PromisedAnswer); _access.Serialize(wr.PromisedAnswer);
} }
@ -178,7 +178,7 @@ namespace Capnp.Rpc
var call = base.SetupMessage(args, interfaceId, methodId); var call = base.SetupMessage(args, interfaceId, methodId);
call.Target.which = MessageTarget.WHICH.PromisedAnswer; call.Target.which = MessageTarget.WHICH.PromisedAnswer;
call.Target.PromisedAnswer.QuestionId = _question.QuestionId; call.Target.PromisedAnswer!.QuestionId = _question.QuestionId;
_access.Serialize(call.Target.PromisedAnswer); _access.Serialize(call.Target.PromisedAnswer);
return call; return call;
@ -243,8 +243,8 @@ namespace Capnp.Rpc
if (endpoint == _ep) if (endpoint == _ep)
{ {
writer.which = CapDescriptor.WHICH.ReceiverAnswer; writer.which = CapDescriptor.WHICH.ReceiverAnswer;
_access.Serialize(writer.ReceiverAnswer); _access.Serialize(writer.ReceiverAnswer!);
writer.ReceiverAnswer.QuestionId = _question.QuestionId; writer.ReceiverAnswer!.QuestionId = _question.QuestionId;
} }
else if (_question.IsTailCall) else if (_question.IsTailCall)
{ {

View File

@ -29,7 +29,7 @@ namespace Capnp.Rpc
callMsg.which = Message.WHICH.Call; callMsg.which = Message.WHICH.Call;
var call = callMsg.Call; var call = callMsg.Call!;
call.AllowThirdPartyTailCall = false; call.AllowThirdPartyTailCall = false;
call.InterfaceId = interfaceId; call.InterfaceId = interfaceId;
call.MethodId = methodId; call.MethodId = methodId;

View File

@ -210,7 +210,7 @@ namespace Capnp.Rpc
var mb = MessageBuilder.Create(); var mb = MessageBuilder.Create();
var msg = mb.BuildRoot<Message.WRITER>(); var msg = mb.BuildRoot<Message.WRITER>();
msg.which = Message.WHICH.Abort; msg.which = Message.WHICH.Abort;
msg.Abort.Reason = reason; msg.Abort!.Reason = reason;
Tx(mb.Frame); Tx(mb.Frame);
} }
@ -233,18 +233,18 @@ namespace Capnp.Rpc
var mb = MessageBuilder.Create(); var mb = MessageBuilder.Create();
var msg = mb.BuildRoot<Message.WRITER>(); var msg = mb.BuildRoot<Message.WRITER>();
msg.which = Message.WHICH.Resolve; msg.which = Message.WHICH.Resolve;
var resolve = msg.Resolve; var resolve = msg.Resolve!;
try try
{ {
var resolvedCap = resolvedCapGetter(); var resolvedCap = resolvedCapGetter();
resolve.which = Resolve.WHICH.Cap; resolve.which = Resolve.WHICH.Cap;
resolvedCap.Export(this, resolve.Cap); resolvedCap.Export(this, resolve.Cap!);
} }
catch (System.Exception ex) catch (System.Exception ex)
{ {
resolve.which = Resolve.WHICH.Exception; resolve.which = Resolve.WHICH.Exception;
resolve.Exception.Reason = ex.Message; resolve.Exception!.Reason = ex.Message;
} }
resolve.PromiseId = preliminaryId; resolve.PromiseId = preliminaryId;
@ -364,7 +364,7 @@ namespace Capnp.Rpc
var ans = bootstrap.MsgBuilder!.BuildRoot<Message.WRITER>(); var ans = bootstrap.MsgBuilder!.BuildRoot<Message.WRITER>();
ans.which = Message.WHICH.Return; ans.which = Message.WHICH.Return;
var ret = ans.Return; var ret = ans.Return!;
ret.AnswerId = q; ret.AnswerId = q;
Task<AnswerOrCounterquestion> bootstrapTask; Task<AnswerOrCounterquestion> bootstrapTask;
@ -374,7 +374,7 @@ namespace Capnp.Rpc
{ {
ret.which = Return.WHICH.Results; ret.which = Return.WHICH.Results;
bootstrap.SetCapability(bootstrap.ProvideCapability(LocalCapability.Create(bootstrapCap))); bootstrap.SetCapability(bootstrap.ProvideCapability(LocalCapability.Create(bootstrapCap)));
ret.Results.Content = bootstrap; ret.Results!.Content = bootstrap;
bootstrapTask = Task.FromResult<AnswerOrCounterquestion>(bootstrap); bootstrapTask = Task.FromResult<AnswerOrCounterquestion>(bootstrap);
} }
@ -383,7 +383,7 @@ namespace Capnp.Rpc
Logger.LogWarning("Peer asked for bootstrap capability, but no bootstrap capability was set."); Logger.LogWarning("Peer asked for bootstrap capability, but no bootstrap capability was set.");
ret.which = Return.WHICH.Exception; ret.which = Return.WHICH.Exception;
ret.Exception.Reason = "No bootstrap capability present"; ret.Exception!.Reason = "No bootstrap capability present";
bootstrapTask = Task.FromException<AnswerOrCounterquestion>(new RpcException(ret.Exception.Reason)); bootstrapTask = Task.FromException<AnswerOrCounterquestion>(new RpcException(ret.Exception.Reason));
} }
@ -403,7 +403,7 @@ namespace Capnp.Rpc
} }
if (bootstrapCap != null) if (ret.Results != null)
{ {
ExportCapTableAndSend(bootstrap, ret.Results); ExportCapTableAndSend(bootstrap, ret.Results);
} }
@ -420,7 +420,7 @@ namespace Capnp.Rpc
{ {
var rmsg = mb.BuildRoot<Message.WRITER>(); var rmsg = mb.BuildRoot<Message.WRITER>();
rmsg.which = Message.WHICH.Return; rmsg.which = Message.WHICH.Return;
var ret = rmsg.Return; var ret = rmsg.Return!;
ret.AnswerId = req.QuestionId; ret.AnswerId = req.QuestionId;
return ret; return ret;
@ -488,7 +488,7 @@ namespace Capnp.Rpc
{ {
case Call.sendResultsTo.WHICH.Caller: case Call.sendResultsTo.WHICH.Caller:
ret.which = Return.WHICH.Results; ret.which = Return.WHICH.Results;
ret.Results.Content = results.Rewrap<DynamicSerializerState>(); ret.Results!.Content = results.Rewrap<DynamicSerializerState>();
ret.ReleaseParamCaps = releaseParamCaps; ret.ReleaseParamCaps = releaseParamCaps;
ExportCapTableAndSend(results, ret.Results); ExportCapTableAndSend(results, ret.Results);
pendingAnswer.CapTable = ret.Results.CapTable; pendingAnswer.CapTable = ret.Results.CapTable;
@ -530,7 +530,7 @@ namespace Capnp.Rpc
ReturnCall(ret => ReturnCall(ret =>
{ {
ret.which = Return.WHICH.Exception; ret.which = Return.WHICH.Exception;
ret.Exception.Reason = exception.Message; ret.Exception!.Reason = exception.Message;
ret.ReleaseParamCaps = releaseParamCaps; ret.ReleaseParamCaps = releaseParamCaps;
}); });
} }
@ -824,7 +824,7 @@ namespace Capnp.Rpc
break; break;
case Resolve.WHICH.Exception: case Resolve.WHICH.Exception:
resolvableCap.Break(resolve.Exception.Reason); resolvableCap.Break(resolve.Exception.Reason ?? "unknown reason");
break; break;
default: default:
@ -844,8 +844,8 @@ namespace Capnp.Rpc
mb.InitCapTable(); mb.InitCapTable();
var wr = mb.BuildRoot<Message.WRITER>(); var wr = mb.BuildRoot<Message.WRITER>();
wr.which = Message.WHICH.Disembargo; wr.which = Message.WHICH.Disembargo;
wr.Disembargo.Context.which = Disembargo.context.WHICH.ReceiverLoopback; wr.Disembargo!.Context.which = Disembargo.context.WHICH.ReceiverLoopback;
wr.Disembargo.Context.ReceiverLoopback = disembargo.Context.SenderLoopback; wr.Disembargo!.Context.ReceiverLoopback = disembargo.Context.SenderLoopback;
var reply = wr.Disembargo; var reply = wr.Disembargo;
switch (disembargo.Target.which) switch (disembargo.Target.which)
@ -871,7 +871,7 @@ namespace Capnp.Rpc
var promisedAnswer = disembargo.Target.PromisedAnswer; var promisedAnswer = disembargo.Target.PromisedAnswer;
reply.Target.which = MessageTarget.WHICH.PromisedAnswer; reply.Target.which = MessageTarget.WHICH.PromisedAnswer;
var replyPromisedAnswer = reply.Target.PromisedAnswer; var replyPromisedAnswer = reply.Target.PromisedAnswer;
replyPromisedAnswer.QuestionId = disembargo.Target.PromisedAnswer.QuestionId; replyPromisedAnswer!.QuestionId = disembargo.Target.PromisedAnswer.QuestionId;
int count = promisedAnswer.Transform.Count; int count = promisedAnswer.Transform.Count;
replyPromisedAnswer.Transform.Init(count); replyPromisedAnswer.Transform.Init(count);
@ -1162,7 +1162,7 @@ namespace Capnp.Rpc
var req = mb.BuildRoot<Message.WRITER>(); var req = mb.BuildRoot<Message.WRITER>();
req.which = Message.WHICH.Bootstrap; req.which = Message.WHICH.Bootstrap;
var pendingBootstrap = AllocateQuestion(null, null); var pendingBootstrap = AllocateQuestion(null, null);
req.Bootstrap.QuestionId = pendingBootstrap.QuestionId; req.Bootstrap!.QuestionId = pendingBootstrap.QuestionId;
Tx(mb.Frame); Tx(mb.Frame);
@ -1237,7 +1237,7 @@ namespace Capnp.Rpc
mb.InitCapTable(); mb.InitCapTable();
var reply = mb.BuildRoot<Message.WRITER>(); var reply = mb.BuildRoot<Message.WRITER>();
reply.which = Message.WHICH.Unimplemented; reply.which = Message.WHICH.Unimplemented;
Reserializing.DeepCopy(msg, reply.Unimplemented.Rewrap<DynamicSerializerState>()); Reserializing.DeepCopy(msg, reply.Unimplemented!.Rewrap<DynamicSerializerState>());
Tx(mb.Frame); Tx(mb.Frame);
} }
@ -1472,8 +1472,8 @@ namespace Capnp.Rpc
var mb = MessageBuilder.Create(); var mb = MessageBuilder.Create();
var msg = mb.BuildRoot<Message.WRITER>(); var msg = mb.BuildRoot<Message.WRITER>();
msg.which = Message.WHICH.Finish; msg.which = Message.WHICH.Finish;
msg.Finish.QuestionId = questionId; msg.Finish!.QuestionId = questionId;
msg.Finish.ReleaseResultCaps = false; msg.Finish!.ReleaseResultCaps = false;
try try
{ {
@ -1518,8 +1518,8 @@ namespace Capnp.Rpc
var mb = MessageBuilder.Create(); var mb = MessageBuilder.Create();
var msg = mb.BuildRoot<Message.WRITER>(); var msg = mb.BuildRoot<Message.WRITER>();
msg.which = Message.WHICH.Release; msg.which = Message.WHICH.Release;
msg.Release.Id = importId; msg.Release!.Id = importId;
msg.Release.ReferenceCount = (uint)count; msg.Release!.ReferenceCount = (uint)count;
try try
{ {
@ -1540,7 +1540,7 @@ namespace Capnp.Rpc
mb.InitCapTable(); mb.InitCapTable();
var msg = mb.BuildRoot<Message.WRITER>(); var msg = mb.BuildRoot<Message.WRITER>();
msg.which = Message.WHICH.Disembargo; msg.which = Message.WHICH.Disembargo;
describe(msg.Disembargo.Target); describe(msg.Disembargo!.Target);
var ctx = msg.Disembargo.Context; var ctx = msg.Disembargo.Context;
ctx.which = Disembargo.context.WHICH.SenderLoopback; ctx.which = Disembargo.context.WHICH.SenderLoopback;
ctx.SenderLoopback = id; ctx.SenderLoopback = id;

File diff suppressed because it is too large Load Diff

View File

@ -71,3 +71,4 @@ Examples:
| NullableDisable2.capnp.bin | false | true | success | | NullableDisable2.capnp.bin | false | true | success |
| NullableEnable2.capnp.bin | false | false | errors | | NullableEnable2.capnp.bin | false | false | errors |
| NullableEnable2.capnp.bin | false | true | success | | NullableEnable2.capnp.bin | false | true | success |
| rpc-csharp.capnp.bin | true | true | warnings |

View File

@ -647,6 +647,21 @@ this.ValidGeneratorOutput("NullableEnable2.capnp.bin", "false", "false", "errors
{ {
#line 50 #line 50
this.ValidGeneratorOutput("NullableEnable2.capnp.bin", "false", "true", "success", ((string[])(null))); this.ValidGeneratorOutput("NullableEnable2.capnp.bin", "false", "true", "success", ((string[])(null)));
#line hidden
}
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 15")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 15")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "rpc-csharp.capnp.bin")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "true")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "true")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "warnings")]
public virtual void ValidGeneratorOutput_Variant15()
{
#line 50
this.ValidGeneratorOutput("rpc-csharp.capnp.bin", "true", "true", "warnings", ((string[])(null)));
#line hidden #line hidden
} }
} }

View File

@ -241,14 +241,12 @@ namespace CapnpC.CSharp.Generator.Tests
} }
} }
catch (AssertFailedException) finally
{ {
string generated = _result.GeneratedFiles.Single().GeneratedContent; string generated = _result.GeneratedFiles.Single().GeneratedContent;
string path = Path.ChangeExtension(Path.GetTempFileName(), ".capnp.cs"); string path = Path.ChangeExtension(Path.GetTempFileName(), ".capnp.cs");
File.WriteAllText(path, generated); File.WriteAllText(path, generated);
Console.WriteLine($"Generated code was saved to {path}"); Console.WriteLine($"Generated code was saved to {path}");
throw;
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -62,8 +62,17 @@
IEnumerable<MemberDeclarationSyntax> TransformStruct(TypeDefinition def) IEnumerable<MemberDeclarationSyntax> TransformStruct(TypeDefinition def)
{ {
var topDecl = ClassDeclaration(_names.MakeTypeName(def).Identifier) var topDecl = ClassDeclaration(_names.MakeTypeName(def).Identifier)
.AddModifiers(Public) .AddModifiers(_names.TypeVisibilityModifier);
.AddBaseListTypes(SimpleBaseType(_names.Type<Capnp.ICapnpSerializable>(Nullability.NonNullable)));
if (_names.EmitDomainClassesAndInterfaces)
{
topDecl = topDecl.AddBaseListTypes(SimpleBaseType(_names.Type<Capnp.ICapnpSerializable>(Nullability.NonNullable)));
}
else
{
topDecl = topDecl.AddModifiers(Static);
}
if (def.GenericParameters.Count > 0) if (def.GenericParameters.Count > 0)
{ {
@ -80,9 +89,14 @@
topDecl = topDecl.AddMembers(_commonGen.MakeUnionSelectorEnum(def)); topDecl = topDecl.AddMembers(_commonGen.MakeUnionSelectorEnum(def));
} }
topDecl = topDecl.AddMembers(_domClassGen.MakeDomainClassMembers(def)); if (_names.EmitDomainClassesAndInterfaces)
topDecl = topDecl.AddMembers(_readerGen.MakeReaderStruct(def)); {
topDecl = topDecl.AddMembers(_writerGen.MakeWriterStruct(def)); topDecl = topDecl.AddMembers(_domClassGen.MakeDomainClassMembers(def));
}
topDecl = topDecl.AddMembers(
_readerGen.MakeReaderStruct(def),
_writerGen.MakeWriterStruct(def));
foreach (var nestedGroup in def.NestedGroups) foreach (var nestedGroup in def.NestedGroups)
{ {
@ -99,6 +113,9 @@
IEnumerable<MemberDeclarationSyntax> TransformInterface(TypeDefinition def) IEnumerable<MemberDeclarationSyntax> TransformInterface(TypeDefinition def)
{ {
if (!_names.EmitDomainClassesAndInterfaces)
yield break;
yield return _interfaceGen.MakeInterface(def); yield return _interfaceGen.MakeInterface(def);
yield return _interfaceGen.MakeProxy(def); yield return _interfaceGen.MakeProxy(def);
yield return _interfaceGen.MakeSkeleton(def); yield return _interfaceGen.MakeSkeleton(def);
@ -168,7 +185,7 @@
if (classDecl == null) if (classDecl == null)
{ {
classDecl = ClassDeclaration(_names.MakePipeliningSupportExtensionClassName(file).Identifier) classDecl = ClassDeclaration(_names.MakePipeliningSupportExtensionClassName(file).Identifier)
.AddModifiers(Public, Static, Partial); .AddModifiers(_names.TypeVisibilityModifier, Static, Partial);
} }
classDecl = classDecl.AddMembers(members); classDecl = classDecl.AddMembers(members);
@ -187,6 +204,8 @@
internal string Transform(GenFile file) internal string Transform(GenFile file)
{ {
_names.NullableEnable = file.NullableEnable ?? _options.NullableEnableDefault; _names.NullableEnable = file.NullableEnable ?? _options.NullableEnableDefault;
_names.EmitDomainClassesAndInterfaces = file.EmitDomainClassesAndInterfaces;
_names.TypeVisibility = file.TypeVisibility;
NameSyntax topNamespace = GenNames.NamespaceName(file.Namespace) ?? _names.TopNamespace; NameSyntax topNamespace = GenNames.NamespaceName(file.Namespace) ?? _names.TopNamespace;
@ -211,11 +230,14 @@
ns = ns.AddMembers(Transform(def).ToArray()); ns = ns.AddMembers(Transform(def).ToArray());
} }
var psc = TransformForPipeliningSupport(file); if (_names.EmitDomainClassesAndInterfaces)
if (psc != null)
{ {
ns = ns.AddMembers(psc); var psc = TransformForPipeliningSupport(file);
if (psc != null)
{
ns = ns.AddMembers(psc);
}
} }
var cu = CompilationUnit().AddUsings( var cu = CompilationUnit().AddUsings(

View File

@ -51,7 +51,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
{ {
var decl = EnumDeclaration(_names.GetCodeIdentifier(def)) var decl = EnumDeclaration(_names.GetCodeIdentifier(def))
.WithAttributeLists(MakeTypeIdAttributeLists(def.Id)) .WithAttributeLists(MakeTypeIdAttributeLists(def.Id))
.AddModifiers(Public) .AddModifiers(_names.TypeVisibilityModifier)
.AddBaseListTypes(SimpleBaseType(_names.Type<ushort>(Nullability.NonNullable))); .AddBaseListTypes(SimpleBaseType(_names.Type<ushort>(Nullability.NonNullable)));
foreach (var enumerant in def.Enumerants.OrderBy(e => e.CodeOrder)) foreach (var enumerant in def.Enumerants.OrderBy(e => e.CodeOrder))

View File

@ -1,4 +1,5 @@
using CapnpC.CSharp.Generator.Model; using CapnpC.CSharp.Generator.Model;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using System; using System;
@ -74,6 +75,8 @@ namespace CapnpC.CSharp.Generator.CodeGen
public string SkeletonClassFormat { get; } public string SkeletonClassFormat { get; }
public Name AwaitProxy { get; } public Name AwaitProxy { get; }
public bool NullableEnable { get; set; } public bool NullableEnable { get; set; }
public bool EmitDomainClassesAndInterfaces { get; set; }
public SupportedAnnotations.TypeVisibility TypeVisibility { get; set; }
public GenNames(GeneratorOptions options) public GenNames(GeneratorOptions options)
{ {
TopNamespace = new Name(options.TopNamespaceName).IdentifierName; TopNamespace = new Name(options.TopNamespaceName).IdentifierName;
@ -708,5 +711,23 @@ namespace CapnpC.CSharp.Generator.CodeGen
PostfixUnaryExpression(SyntaxKind.SuppressNullableWarningExpression, expression) : PostfixUnaryExpression(SyntaxKind.SuppressNullableWarningExpression, expression) :
expression; expression;
} }
public SyntaxToken TypeVisibilityModifier
{
get
{
switch (TypeVisibility)
{
case SupportedAnnotations.TypeVisibility.Public:
return Token(SyntaxKind.PublicKeyword);
case SupportedAnnotations.TypeVisibility.Internal:
return Token(SyntaxKind.InternalKeyword);
default:
throw new NotImplementedException();
}
}
}
} }
} }

View File

@ -13,6 +13,8 @@ namespace CapnpC.CSharp.Generator.Model
public string[] Namespace { get; set; } public string[] Namespace { get; set; }
public bool? NullableEnable { get; set; } public bool? NullableEnable { get; set; }
public bool EmitNullableDirective { get; set; } public bool EmitNullableDirective { get; set; }
public bool EmitDomainClassesAndInterfaces { get; set; }
public SupportedAnnotations.TypeVisibility TypeVisibility { get; set; }
public IEnumerable<TypeDefinition> NestedTypes { get => this.GetNestedTypes(); } public IEnumerable<TypeDefinition> NestedTypes { get => this.GetNestedTypes(); }
public ICollection<IDefinition> NestedDefinitions { get; } = new List<IDefinition>(); public ICollection<IDefinition> NestedDefinitions { get; } = new List<IDefinition>();

View File

@ -94,6 +94,8 @@ namespace CapnpC.CSharp.Generator.Model
file.Name = name; file.Name = name;
file.NullableEnable = GetNullableEnable(node); file.NullableEnable = GetNullableEnable(node);
file.EmitNullableDirective = GetEmitNullableDirective(node) ?? false; file.EmitNullableDirective = GetEmitNullableDirective(node) ?? false;
file.EmitDomainClassesAndInterfaces = GetEmitDomainClassesAndInterfaces(node) ?? true;
file.TypeVisibility = GetTypeVisibility(node) ?? TypeVisibility.Public;
return ProcessNodePass1(id, name, state) as GenFile; return ProcessNodePass1(id, name, state) as GenFile;
} }

View File

@ -19,9 +19,17 @@ namespace CapnpC.CSharp.Generator.Model
public const ulong NullableEnable = 0xeb0d831668c6eda1; public const ulong NullableEnable = 0xeb0d831668c6eda1;
public const ulong Name = 0xeb0d831668c6eda2; public const ulong Name = 0xeb0d831668c6eda2;
public const ulong EmitNullableDirective = 0xeb0d831668c6eda3; public const ulong EmitNullableDirective = 0xeb0d831668c6eda3;
public const ulong EmitDomainClassesAndInterfaces = 0xeb0d831668c6eda4;
public const ulong TypeVisibility = 0xeb0d831668c6eda6;
} }
} }
public enum TypeVisibility
{
Public = 0,
Internal = 1
}
public static string[] GetNamespaceAnnotation(Schema.Node.Reader fileNode) public static string[] GetNamespaceAnnotation(Schema.Node.Reader fileNode)
{ {
foreach (var annotation in fileNode.Annotations) foreach (var annotation in fileNode.Annotations)
@ -98,5 +106,29 @@ namespace CapnpC.CSharp.Generator.Model
} }
return null; return null;
} }
public static bool? GetEmitDomainClassesAndInterfaces(Schema.Node.Reader node)
{
foreach (var annotation in node.Annotations)
{
if (annotation.Id == AnnotationIds.Cs.EmitDomainClassesAndInterfaces && annotation.Value.IsBool)
{
return annotation.Value.Bool;
}
}
return null;
}
public static TypeVisibility? GetTypeVisibility(Schema.Node.Reader node)
{
foreach (var annotation in node.Annotations)
{
if (annotation.Id == AnnotationIds.Cs.TypeVisibility && annotation.Value.IsEnum)
{
return (TypeVisibility)annotation.Value.Enum;
}
}
return null;
}
} }
} }

View File

@ -1,6 +1,11 @@
@0xeb0d831668c6edab; @0xeb0d831668c6edab;
$namespace("Capnp.Annotations"); $namespace("Capnp.Annotations");
enum TypeVisibility @0xeb0d831668c6eda5 {
public @0;
internal @1;
}
annotation namespace @0xeb0d831668c6eda0 (file) : Text; annotation namespace @0xeb0d831668c6eda0 (file) : Text;
# C# namespace for code generation # C# namespace for code generation
@ -8,7 +13,13 @@ annotation nullableEnable @0xeb0d831668c6eda1 (file) : Bool;
# Whether to generate C# nullable reference types # Whether to generate C# nullable reference types
annotation emitNullableDirective @0xeb0d831668c6eda3 (file) : Bool; annotation emitNullableDirective @0xeb0d831668c6eda3 (file) : Bool;
# Whether to surround the generated with with #nullable enable/disable ... #nullable restore # Whether to surround the generated code with #nullable enable/disable ... #nullable restore
annotation emitDomainClassesAndInterfaces @0xeb0d831668c6eda4 (file) : Bool;
# Whether generate domain classes and interfaces (default is 'true' if annotation is missing)
annotation typeVisibility @0xeb0d831668c6eda6 (file) : TypeVisibility;
# Visibility of generated types
annotation name @0xeb0d831668c6eda2 (field, enumerant, struct, enum, interface, method, param, group, union) : Text; annotation name @0xeb0d831668c6eda2 (field, enumerant, struct, enum, interface, method, param, group, union) : Text;
# C# member name for code generation # C# member name for code generation

View File

@ -4,12 +4,10 @@ $coverageDir = "$rootDir\coverage"
$coverageReportDir = "$rootDir\coverage\report" $coverageReportDir = "$rootDir\coverage\report"
$openCover = "$env:LOCALAPPDATA\Apps\OpenCover\OpenCover.Console.exe" $openCover = "$env:LOCALAPPDATA\Apps\OpenCover\OpenCover.Console.exe"
$vsTestConsole = where.exe vstest.console $vsTestConsole = where.exe vstest.console
$coverageOutput = "$coverageDir\coverage.xml"
$runtimeTests = "$rootDir\Capnp.Net.Runtime.Tests\bin\Release\netcoreapp2.1\Capnp.Net.Runtime.Tests.dll" $runtimeTests = "$rootDir\Capnp.Net.Runtime.Tests\bin\Release\netcoreapp2.1\Capnp.Net.Runtime.Tests.dll"
$coverageOutputRuntime = "$coverageDir\cov-Capnp.Net.Runtime.xml"
$generatorTests = "$rootDir\CapnpC.CSharp.Generator.Tests\bin\Release\netcoreapp3.0\CapnpC.CSharp.Generator.Tests.dll" $generatorTests = "$rootDir\CapnpC.CSharp.Generator.Tests\bin\Release\netcoreapp3.0\CapnpC.CSharp.Generator.Tests.dll"
$coverageOutputGenerator = "$coverageDir\cov-CapnpC.CSharp.Generator.xml"
If(!(test-path $coverageDir)) If(!(test-path $coverageDir))
{ {
@ -25,14 +23,15 @@ If(!(test-path $coverageReportDir))
-targetArgs:"/inIsolation $runtimeTests /TestCaseFilter:`"TestCategory=Coverage`"" ` -targetArgs:"/inIsolation $runtimeTests /TestCaseFilter:`"TestCategory=Coverage`"" `
-filter:"+[Capnp.Net.Runtime]Capnp.*" ` -filter:"+[Capnp.Net.Runtime]Capnp.*" `
-excludebyattribute:"System.CodeDom.Compiler.GeneratedCodeAttribute" ` -excludebyattribute:"System.CodeDom.Compiler.GeneratedCodeAttribute" `
-output:"$coverageOutputRuntime" ` -output:"$coverageOutput" `
-mergebyhash -register:user -oldStyle -mergebyhash -register:user -oldStyle
& $openCover -target:"$vsTestConsole" ` & $openCover -target:"$vsTestConsole" `
-targetArgs:"/inIsolation $generatorTests" ` -targetArgs:"/inIsolation $generatorTests" `
-filter:"+[CapnpC.CSharp.Generator]CapnpC.CSharp.Generator.* -[CapnpC.CSharp.Generator]CapnpC.CSharp.Generator.Schema.*" ` -filter:"+[CapnpC.CSharp.Generator]CapnpC.CSharp.Generator.* -[CapnpC.CSharp.Generator]CapnpC.CSharp.Generator.Schema.*" `
-excludebyattribute:"System.CodeDom.Compiler.GeneratedCodeAttribute" ` -excludebyattribute:"System.CodeDom.Compiler.GeneratedCodeAttribute" `
-output:"$coverageOutputGenerator" ` -output:"$coverageOutput" `
-mergeoutput `
-mergebyhash -register:user -oldStyle -mergebyhash -register:user -oldStyle
ReportGenerator.exe -reports:"$coverageOutputRuntime;$coverageOutputGenerator" -targetdir:"$coverageReportDir" -reportTypes:"Html;Xml" ReportGenerator.exe -reports:"$coverageOutput" -targetdir:"$coverageReportDir" -reportTypes:"Html"