mirror of
https://github.com/FabInfra/capnproto-dotnetcore_Runtime.git
synced 2025-03-12 14:51:41 +01:00
refactored codegen to use generated schema
fixed issue #45 refactored codegen unit tests fixed appveyor.yml
This commit is contained in:
parent
c1e8ed6d65
commit
c3cbb123c8
@ -162,10 +162,12 @@ namespace Capnp.Net.Runtime.Tests
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void ObsoleteGetAnswer()
|
public void ObsoleteGetAnswer()
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CS0618
|
||||||
var answer = new PromisedAnswerMock();
|
var answer = new PromisedAnswerMock();
|
||||||
Assert.ThrowsException<ArgumentException>(() => Impatient.GetAnswer(answer.WhenReturned));
|
Assert.ThrowsException<ArgumentException>(() => Impatient.GetAnswer(answer.WhenReturned));
|
||||||
var t = Impatient.MakePipelineAware(answer, _ => _);
|
var t = Impatient.MakePipelineAware(answer, _ => _);
|
||||||
Assert.AreEqual(answer, Impatient.GetAnswer(t));
|
Assert.AreEqual(answer, Impatient.GetAnswer(t));
|
||||||
|
#pragma warning restore CS0618
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@ -182,8 +184,10 @@ namespace Capnp.Net.Runtime.Tests
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void ObsoletePseudoEager()
|
public void ObsoletePseudoEager()
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CS0618
|
||||||
var task = Task.FromResult<ITestInterface>(new TestInterfaceImpl2());
|
var task = Task.FromResult<ITestInterface>(new TestInterfaceImpl2());
|
||||||
Assert.IsTrue(task.PseudoEager() is Proxy proxy && proxy.WhenResolved.IsCompleted);
|
Assert.IsTrue(task.PseudoEager() is Proxy proxy && proxy.WhenResolved.IsCompleted);
|
||||||
|
#pragma warning restore CS0618
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
@ -718,7 +718,7 @@ namespace Capnp.Net.Runtime.Tests.GenImpls
|
|||||||
await task2;
|
await task2;
|
||||||
Assert.Fail("Not a tail call");
|
Assert.Fail("Not a tail call");
|
||||||
}
|
}
|
||||||
catch (TailCallNoDataException)
|
catch (NoResultsException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1198,7 +1198,9 @@ namespace Capnp.Net.Runtime.Tests
|
|||||||
var p2 = (Proxy)Proxy.Share<ITestInterface>(impl);
|
var p2 = (Proxy)Proxy.Share<ITestInterface>(impl);
|
||||||
Assert.AreEqual(0u, dss.ProvideCapability(p1));
|
Assert.AreEqual(0u, dss.ProvideCapability(p1));
|
||||||
Assert.AreEqual(0u, dss.ProvideCapability(p2.ConsumedCap));
|
Assert.AreEqual(0u, dss.ProvideCapability(p2.ConsumedCap));
|
||||||
|
#pragma warning disable CS0618 // Typ oder Element ist veraltet
|
||||||
Assert.AreEqual(0u, dss.ProvideCapability(CapabilityReflection.CreateSkeleton(impl)));
|
Assert.AreEqual(0u, dss.ProvideCapability(CapabilityReflection.CreateSkeleton(impl)));
|
||||||
|
#pragma warning restore CS0618 // Typ oder Element ist veraltet
|
||||||
Assert.IsTrue(p1.IsDisposed);
|
Assert.IsTrue(p1.IsDisposed);
|
||||||
Assert.IsFalse(p2.IsDisposed);
|
Assert.IsFalse(p2.IsDisposed);
|
||||||
p2.Dispose();
|
p2.Dispose();
|
||||||
|
@ -35,6 +35,7 @@ namespace Capnp.Net.Runtime.Tests
|
|||||||
ExpectingLogOutput = true;
|
ExpectingLogOutput = true;
|
||||||
|
|
||||||
Logging.LoggerFactory?.Dispose();
|
Logging.LoggerFactory?.Dispose();
|
||||||
|
#pragma warning disable CS0618 // Typ oder Element ist veraltet
|
||||||
Logging.LoggerFactory = new LoggerFactory().AddConsole((msg, level) =>
|
Logging.LoggerFactory = new LoggerFactory().AddConsole((msg, level) =>
|
||||||
{
|
{
|
||||||
if (!ExpectingLogOutput && level != LogLevel.Debug)
|
if (!ExpectingLogOutput && level != LogLevel.Debug)
|
||||||
@ -43,6 +44,7 @@ namespace Capnp.Net.Runtime.Tests
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
#pragma warning restore CS0618 // Typ oder Element ist veraltet
|
||||||
}
|
}
|
||||||
|
|
||||||
int MediumNonDbgTimeout => Debugger.IsAttached ? Timeout.Infinite : 2000;
|
int MediumNonDbgTimeout => Debugger.IsAttached ? Timeout.Infinite : 2000;
|
||||||
|
@ -412,7 +412,9 @@ namespace Capnp.Net.Runtime.Tests
|
|||||||
public void InitConsoleLogging()
|
public void InitConsoleLogging()
|
||||||
{
|
{
|
||||||
Logging.LoggerFactory?.Dispose();
|
Logging.LoggerFactory?.Dispose();
|
||||||
|
#pragma warning disable CS0618 // Typ oder Element ist veraltet
|
||||||
Logging.LoggerFactory = new LoggerFactory().AddConsole((msg, level) => true);
|
Logging.LoggerFactory = new LoggerFactory().AddConsole((msg, level) => true);
|
||||||
|
#pragma warning restore CS0618 // Typ oder Element ist veraltet
|
||||||
Logger = Logging.CreateLogger<TcpRpcStress>();
|
Logger = Logging.CreateLogger<TcpRpcStress>();
|
||||||
if (Thread.CurrentThread.Name == null)
|
if (Thread.CurrentThread.Name == null)
|
||||||
Thread.CurrentThread.Name = $"Test Thread {Thread.CurrentThread.ManagedThreadId}";
|
Thread.CurrentThread.Name = $"Test Thread {Thread.CurrentThread.ManagedThreadId}";
|
||||||
|
@ -55,11 +55,22 @@ namespace Capnp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static object? CreateFromAny(DeserializerState state)
|
||||||
|
{
|
||||||
|
switch (state.Kind)
|
||||||
|
{
|
||||||
|
case ObjectKind.Capability: return state.RequireCap<Rpc.BareProxy>();
|
||||||
|
case ObjectKind.Nil: return null;
|
||||||
|
default: return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static readonly ConditionalWeakTable<Type, Func<DeserializerState, object?>> _typeMap =
|
static readonly ConditionalWeakTable<Type, Func<DeserializerState, object?>> _typeMap =
|
||||||
new ConditionalWeakTable<Type, Func<DeserializerState, object?>>();
|
new ConditionalWeakTable<Type, Func<DeserializerState, object?>>();
|
||||||
|
|
||||||
static CapnpSerializable()
|
static CapnpSerializable()
|
||||||
{
|
{
|
||||||
|
_typeMap.Add(typeof(object), CreateFromAny);
|
||||||
_typeMap.Add(typeof(string), d => d.RequireList().CastText());
|
_typeMap.Add(typeof(string), d => d.RequireList().CastText());
|
||||||
_typeMap.Add(typeof(IReadOnlyList<bool>), d => d.RequireList().CastBool());
|
_typeMap.Add(typeof(IReadOnlyList<bool>), d => d.RequireList().CastBool());
|
||||||
_typeMap.Add(typeof(IReadOnlyList<sbyte>), d => d.RequireList().CastSByte());
|
_typeMap.Add(typeof(IReadOnlyList<sbyte>), d => d.RequireList().CastSByte());
|
||||||
|
@ -29,7 +29,7 @@ namespace Capnp.Rpc
|
|||||||
{
|
{
|
||||||
var result = await promise.WhenReturned;
|
var result = await promise.WhenReturned;
|
||||||
if (promise.IsTailCall)
|
if (promise.IsTailCall)
|
||||||
throw new TailCallNoDataException();
|
throw new NoResultsException();
|
||||||
|
|
||||||
return then(result);
|
return then(result);
|
||||||
}
|
}
|
||||||
|
16
Capnp.Net.Runtime/Rpc/NoResultsException.cs
Normal file
16
Capnp.Net.Runtime/Rpc/NoResultsException.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
namespace Capnp.Rpc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Thrown when a pending question did return, but was not configured to deliver the result back to the sender
|
||||||
|
/// (typcial for tail calls).
|
||||||
|
/// </summary>
|
||||||
|
public class NoResultsException: System.Exception
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance
|
||||||
|
/// </summary>
|
||||||
|
public NoResultsException(): base("Pending question did return, but was not configured to deliver the result back to the sender")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
namespace Capnp.Rpc
|
|
||||||
{
|
|
||||||
public class TailCallNoDataException: System.Exception
|
|
||||||
{
|
|
||||||
public TailCallNoDataException(): base("Because the question was asked as tail call, it won't return data")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -72,3 +72,4 @@ Examples:
|
|||||||
| 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 |
|
| rpc-csharp.capnp.bin | true | true | warnings |
|
||||||
|
| schema-csharp.capnp.bin | false | false | success |
|
@ -662,6 +662,21 @@ this.ValidGeneratorOutput("NullableEnable2.capnp.bin", "false", "true", "success
|
|||||||
{
|
{
|
||||||
#line 50
|
#line 50
|
||||||
this.ValidGeneratorOutput("rpc-csharp.capnp.bin", "true", "true", "warnings", ((string[])(null)));
|
this.ValidGeneratorOutput("rpc-csharp.capnp.bin", "true", "true", "warnings", ((string[])(null)));
|
||||||
|
#line hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
|
||||||
|
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 16")]
|
||||||
|
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
|
||||||
|
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 16")]
|
||||||
|
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "schema-csharp.capnp.bin")]
|
||||||
|
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")]
|
||||||
|
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")]
|
||||||
|
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")]
|
||||||
|
public virtual void ValidGeneratorOutput_Variant16()
|
||||||
|
{
|
||||||
|
#line 50
|
||||||
|
this.ValidGeneratorOutput("schema-csharp.capnp.bin", "false", "false", "success", ((string[])(null)));
|
||||||
#line hidden
|
#line hidden
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,13 +45,13 @@ namespace CapnpC.CSharp.Generator.Tests
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Test04MutualDependencies()
|
public void Test04MutualDependencies()
|
||||||
{
|
{
|
||||||
LoadAndGenerate("UnitTest4.capnp.bin");
|
LoadAndGenerate("UnitTest4.capnp.bin", "UnitTest4b.capnp.bin");
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Test10ImportedNamespaces()
|
public void Test10ImportedNamespaces()
|
||||||
{
|
{
|
||||||
var (model, codegen, _) = LoadAndGenerate("UnitTest10.capnp.bin");
|
var (model, codegen, _) = LoadAndGenerate("UnitTest10.capnp.bin", "UnitTest10b.capnp.bin");
|
||||||
var outerTypeDef = GetGeneratedFile("UnitTest10.capnp", model).NestedTypes.First();
|
var outerTypeDef = GetGeneratedFile("UnitTest10.capnp", model).NestedTypes.First();
|
||||||
var outerType = Model.Types.FromDefinition(outerTypeDef);
|
var outerType = Model.Types.FromDefinition(outerTypeDef);
|
||||||
var innerType = outerTypeDef.Fields[0].Type;
|
var innerType = outerTypeDef.Fields[0].Type;
|
||||||
@ -72,7 +72,7 @@ namespace CapnpC.CSharp.Generator.Tests
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void Test11ImportedConst()
|
public void Test11ImportedConst()
|
||||||
{
|
{
|
||||||
LoadAndGenerate("UnitTest11.capnp.bin");
|
LoadAndGenerate("UnitTest11.capnp.bin", "UnitTest11b.capnp.bin");
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@ -147,20 +147,54 @@ namespace CapnpC.CSharp.Generator.Tests
|
|||||||
LoadAndGenerate("schema-with-offsets.capnp.bin");
|
LoadAndGenerate("schema-with-offsets.capnp.bin");
|
||||||
}
|
}
|
||||||
|
|
||||||
static (Model.SchemaModel, CodeGen.CodeGenerator, string) LoadAndGenerate(string inputName)
|
[TestMethod]
|
||||||
|
public void Issue45()
|
||||||
{
|
{
|
||||||
var model = Load(inputName);
|
var input = CodeGeneratorSteps.LoadResource("Issue45.capnp.bin");
|
||||||
var codegen = new CodeGen.CodeGenerator(model, new CodeGen.GeneratorOptions());
|
using (input)
|
||||||
|
{
|
||||||
|
var frame = Framing.ReadSegments(input);
|
||||||
|
var ds = DeserializerState.CreateRoot(frame);
|
||||||
|
var cgr = CapnpSerializable.Create<CodeGeneratorRequest>(ds);
|
||||||
|
Assert.IsTrue(cgr.Nodes.Count > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static (Model.SchemaModel, CodeGen.CodeGenerator, string) LoadAndGenerate(params string[] inputNames)
|
||||||
|
{
|
||||||
|
Model.SchemaModel firstModel = null;
|
||||||
|
CodeGen.CodeGenerator firstCodeGen = null;
|
||||||
|
|
||||||
|
Model.SchemaModel LocalLoad(string name)
|
||||||
|
{
|
||||||
|
var model = Load(name);
|
||||||
|
firstModel = firstModel ?? model;
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeGen.CodeGenerator CreateCodeGen(Model.SchemaModel model)
|
||||||
|
{
|
||||||
|
var codegen = new CodeGen.CodeGenerator(model, new CodeGen.GeneratorOptions());
|
||||||
|
firstCodeGen = firstCodeGen ?? codegen;
|
||||||
|
return codegen;
|
||||||
|
}
|
||||||
|
|
||||||
|
var codes = (
|
||||||
|
from name in inputNames
|
||||||
|
let model = LocalLoad(name)
|
||||||
|
let codegen = CreateCodeGen(model)
|
||||||
|
from file in model.FilesToGenerate
|
||||||
|
select codegen.Transform(file)).ToArray();
|
||||||
|
|
||||||
var code = model.FilesToGenerate.Select(f => codegen.Transform(f)).ToArray();
|
|
||||||
Assert.AreEqual(
|
Assert.AreEqual(
|
||||||
Util.InlineAssemblyCompiler.CompileSummary.Success,
|
Util.InlineAssemblyCompiler.CompileSummary.Success,
|
||||||
Util.InlineAssemblyCompiler.TryCompileCapnp(
|
Util.InlineAssemblyCompiler.TryCompileCapnp(
|
||||||
Microsoft.CodeAnalysis.NullableContextOptions.Disable,
|
Microsoft.CodeAnalysis.NullableContextOptions.Disable,
|
||||||
code),
|
codes),
|
||||||
"Compilation was not successful with no warnings");
|
"Compilation was not successful with no warnings");
|
||||||
|
|
||||||
return (model, codegen, code[0]);
|
return (firstModel, firstCodeGen, codes[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Model.GenFile GetGeneratedFile(string name, Model.SchemaModel model)
|
static Model.GenFile GetGeneratedFile(string name, Model.SchemaModel model)
|
||||||
@ -199,7 +233,7 @@ namespace CapnpC.CSharp.Generator.Tests
|
|||||||
segments = Framing.ReadSegments(input);
|
segments = Framing.ReadSegments(input);
|
||||||
}
|
}
|
||||||
var dec = DeserializerState.CreateRoot(segments);
|
var dec = DeserializerState.CreateRoot(segments);
|
||||||
var reader = CodeGeneratorRequest.Reader.Create(dec);
|
var reader = CodeGeneratorRequest.READER.create(dec);
|
||||||
var model = Model.SchemaModel.Create(reader);
|
var model = Model.SchemaModel.Create(reader);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
537
CapnpC.CSharp.Generator.Tests/No Resources/schema-csharp.capnp
Normal file
537
CapnpC.CSharp.Generator.Tests/No Resources/schema-csharp.capnp
Normal file
@ -0,0 +1,537 @@
|
|||||||
|
# Copyright (c) 2020 Christian Köllner and contributors
|
||||||
|
# This is a modified version of schema.capnp, found in the original distribution
|
||||||
|
# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||||
|
# Licensed under the MIT License:
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
|
||||||
|
@0xa93fc509624c72d9;
|
||||||
|
# $$embed
|
||||||
|
# #pragma warning disable CS1591
|
||||||
|
|
||||||
|
using CSharp = import "/csharp.capnp";
|
||||||
|
$CSharp.namespace("CapnpC.CSharp.Generator.Schema");
|
||||||
|
$CSharp.nullableEnable(false);
|
||||||
|
$CSharp.emitNullableDirective(false);
|
||||||
|
$CSharp.emitDomainClassesAndInterfaces(true);
|
||||||
|
$CSharp.typeVisibility(public);
|
||||||
|
|
||||||
|
using Id = UInt64;
|
||||||
|
# The globally-unique ID of a file, type, or annotation.
|
||||||
|
|
||||||
|
struct Node {
|
||||||
|
id @0 :Id;
|
||||||
|
|
||||||
|
displayName @1 :Text;
|
||||||
|
# Name to present to humans to identify this Node. You should not attempt to parse this. Its
|
||||||
|
# format could change. It is not guaranteed to be unique.
|
||||||
|
#
|
||||||
|
# (On Zooko's triangle, this is the node's nickname.)
|
||||||
|
|
||||||
|
displayNamePrefixLength @2 :UInt32;
|
||||||
|
# If you want a shorter version of `displayName` (just naming this node, without its surrounding
|
||||||
|
# scope), chop off this many characters from the beginning of `displayName`.
|
||||||
|
|
||||||
|
scopeId @3 :Id;
|
||||||
|
# ID of the lexical parent node. Typically, the scope node will have a NestedNode pointing back
|
||||||
|
# at this node, but robust code should avoid relying on this (and, in fact, group nodes are not
|
||||||
|
# listed in the outer struct's nestedNodes, since they are listed in the fields). `scopeId` is
|
||||||
|
# zero if the node has no parent, which is normally only the case with files, but should be
|
||||||
|
# allowed for any kind of node (in order to make runtime type generation easier).
|
||||||
|
|
||||||
|
parameters @32 :List(Parameter);
|
||||||
|
# If this node is parameterized (generic), the list of parameters. Empty for non-generic types.
|
||||||
|
|
||||||
|
isGeneric @33 :Bool;
|
||||||
|
# True if this node is generic, meaning that it or one of its parent scopes has a non-empty
|
||||||
|
# `parameters`.
|
||||||
|
|
||||||
|
struct Parameter {
|
||||||
|
# Information about one of the node's parameters.
|
||||||
|
|
||||||
|
name @0 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
nestedNodes @4 :List(NestedNode);
|
||||||
|
# List of nodes nested within this node, along with the names under which they were declared.
|
||||||
|
|
||||||
|
struct NestedNode {
|
||||||
|
name @0 :Text;
|
||||||
|
# Unqualified symbol name. Unlike Node.displayName, this *can* be used programmatically.
|
||||||
|
#
|
||||||
|
# (On Zooko's triangle, this is the node's petname according to its parent scope.)
|
||||||
|
|
||||||
|
id @1 :Id;
|
||||||
|
# ID of the nested node. Typically, the target node's scopeId points back to this node, but
|
||||||
|
# robust code should avoid relying on this.
|
||||||
|
}
|
||||||
|
|
||||||
|
annotations @5 :List(Annotation);
|
||||||
|
# Annotations applied to this node.
|
||||||
|
|
||||||
|
union {
|
||||||
|
# Info specific to each kind of node.
|
||||||
|
|
||||||
|
file @6 :Void;
|
||||||
|
|
||||||
|
struct :group {
|
||||||
|
dataWordCount @7 :UInt16;
|
||||||
|
# Size of the data section, in words.
|
||||||
|
|
||||||
|
pointerCount @8 :UInt16;
|
||||||
|
# Size of the pointer section, in pointers (which are one word each).
|
||||||
|
|
||||||
|
preferredListEncoding @9 :ElementSize;
|
||||||
|
# The preferred element size to use when encoding a list of this struct. If this is anything
|
||||||
|
# other than `inlineComposite` then the struct is one word or less in size and is a candidate
|
||||||
|
# for list packing optimization.
|
||||||
|
|
||||||
|
isGroup @10 :Bool;
|
||||||
|
# If true, then this "struct" node is actually not an independent node, but merely represents
|
||||||
|
# some named union or group within a particular parent struct. This node's scopeId refers
|
||||||
|
# to the parent struct, which may itself be a union/group in yet another struct.
|
||||||
|
#
|
||||||
|
# All group nodes share the same dataWordCount and pointerCount as the top-level
|
||||||
|
# struct, and their fields live in the same ordinal and offset spaces as all other fields in
|
||||||
|
# the struct.
|
||||||
|
#
|
||||||
|
# Note that a named union is considered a special kind of group -- in fact, a named union
|
||||||
|
# is exactly equivalent to a group that contains nothing but an unnamed union.
|
||||||
|
|
||||||
|
discriminantCount @11 :UInt16;
|
||||||
|
# Number of fields in this struct which are members of an anonymous union, and thus may
|
||||||
|
# overlap. If this is non-zero, then a 16-bit discriminant is present indicating which
|
||||||
|
# of the overlapping fields is active. This can never be 1 -- if it is non-zero, it must be
|
||||||
|
# two or more.
|
||||||
|
#
|
||||||
|
# Note that the fields of an unnamed union are considered fields of the scope containing the
|
||||||
|
# union -- an unnamed union is not its own group. So, a top-level struct may contain a
|
||||||
|
# non-zero discriminant count. Named unions, on the other hand, are equivalent to groups
|
||||||
|
# containing unnamed unions. So, a named union has its own independent schema node, with
|
||||||
|
# `isGroup` = true.
|
||||||
|
|
||||||
|
discriminantOffset @12 :UInt32;
|
||||||
|
# If `discriminantCount` is non-zero, this is the offset of the union discriminant, in
|
||||||
|
# multiples of 16 bits.
|
||||||
|
|
||||||
|
fields @13 :List(Field);
|
||||||
|
# Fields defined within this scope (either the struct's top-level fields, or the fields of
|
||||||
|
# a particular group; see `isGroup`).
|
||||||
|
#
|
||||||
|
# The fields are sorted by ordinal number, but note that because groups share the same
|
||||||
|
# ordinal space, the field's index in this list is not necessarily exactly its ordinal.
|
||||||
|
# On the other hand, the field's position in this list does remain the same even as the
|
||||||
|
# protocol evolves, since it is not possible to insert or remove an earlier ordinal.
|
||||||
|
# Therefore, for most use cases, if you want to identify a field by number, it may make the
|
||||||
|
# most sense to use the field's index in this list rather than its ordinal.
|
||||||
|
}
|
||||||
|
|
||||||
|
enum :group {
|
||||||
|
enumerants@14 :List(Enumerant);
|
||||||
|
# Enumerants ordered by numeric value (ordinal).
|
||||||
|
}
|
||||||
|
|
||||||
|
interface :group {
|
||||||
|
methods @15 :List(Method);
|
||||||
|
# Methods ordered by ordinal.
|
||||||
|
|
||||||
|
superclasses @31 :List(Superclass);
|
||||||
|
# Superclasses of this interface.
|
||||||
|
}
|
||||||
|
|
||||||
|
const :group {
|
||||||
|
type @16 :Type;
|
||||||
|
value @17 :Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
annotation :group {
|
||||||
|
type @18 :Type;
|
||||||
|
|
||||||
|
targetsFile @19 :Bool;
|
||||||
|
targetsConst @20 :Bool;
|
||||||
|
targetsEnum @21 :Bool;
|
||||||
|
targetsEnumerant @22 :Bool;
|
||||||
|
targetsStruct @23 :Bool;
|
||||||
|
targetsField @24 :Bool;
|
||||||
|
targetsUnion @25 :Bool;
|
||||||
|
targetsGroup @26 :Bool;
|
||||||
|
targetsInterface @27 :Bool;
|
||||||
|
targetsMethod @28 :Bool;
|
||||||
|
targetsParam @29 :Bool;
|
||||||
|
targetsAnnotation @30 :Bool;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SourceInfo {
|
||||||
|
# Additional information about a node which is not needed at runtime, but may be useful for
|
||||||
|
# documentation or debugging purposes. This is kept in a separate struct to make sure it
|
||||||
|
# doesn't accidentally get included in contexts where it is not needed. The
|
||||||
|
# `CodeGeneratorRequest` includes this information in a separate array.
|
||||||
|
|
||||||
|
id @0 :Id;
|
||||||
|
# ID of the Node which this info describes.
|
||||||
|
|
||||||
|
docComment @1 :Text;
|
||||||
|
# The top-level doc comment for the Node.
|
||||||
|
|
||||||
|
members @2 :List(Member);
|
||||||
|
# Information about each member -- i.e. fields (for structs), enumerants (for enums), or
|
||||||
|
# methods (for interfaces).
|
||||||
|
#
|
||||||
|
# This list is the same length and order as the corresponding list in the Node, i.e.
|
||||||
|
# Node.struct.fields, Node.enum.enumerants, or Node.interface.methods.
|
||||||
|
|
||||||
|
struct Member {
|
||||||
|
docComment @0 :Text;
|
||||||
|
# Doc comment on the member.
|
||||||
|
}
|
||||||
|
|
||||||
|
# TODO(someday): Record location of the declaration in the original source code.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Field {
|
||||||
|
# Schema for a field of a struct.
|
||||||
|
|
||||||
|
name @0 :Text;
|
||||||
|
|
||||||
|
codeOrder @1 :UInt16;
|
||||||
|
# Indicates where this member appeared in the code, relative to other members.
|
||||||
|
# Code ordering may have semantic relevance -- programmers tend to place related fields
|
||||||
|
# together. So, using code ordering makes sense in human-readable formats where ordering is
|
||||||
|
# otherwise irrelevant, like JSON. The values of codeOrder are tightly-packed, so the maximum
|
||||||
|
# value is count(members) - 1. Fields that are members of a union are only ordered relative to
|
||||||
|
# the other members of that union, so the maximum value there is count(union.members).
|
||||||
|
|
||||||
|
annotations @2 :List(Annotation);
|
||||||
|
|
||||||
|
const noDiscriminant :UInt16 = 0xffff;
|
||||||
|
|
||||||
|
discriminantValue @3 :UInt16 = Field.noDiscriminant;
|
||||||
|
# If the field is in a union, this is the value which the union's discriminant should take when
|
||||||
|
# the field is active. If the field is not in a union, this is 0xffff.
|
||||||
|
|
||||||
|
union {
|
||||||
|
slot :group {
|
||||||
|
# A regular, non-group, non-fixed-list field.
|
||||||
|
|
||||||
|
offset @4 :UInt32;
|
||||||
|
# Offset, in units of the field's size, from the beginning of the section in which the field
|
||||||
|
# resides. E.g. for a UInt32 field, multiply this by 4 to get the byte offset from the
|
||||||
|
# beginning of the data section.
|
||||||
|
|
||||||
|
type @5 :Type;
|
||||||
|
defaultValue @6 :Value;
|
||||||
|
|
||||||
|
hadExplicitDefault @10 :Bool;
|
||||||
|
# Whether the default value was specified explicitly. Non-explicit default values are always
|
||||||
|
# zero or empty values. Usually, whether the default value was explicit shouldn't matter.
|
||||||
|
# The main use case for this flag is for structs representing method parameters:
|
||||||
|
# explicitly-defaulted parameters may be allowed to be omitted when calling the method.
|
||||||
|
}
|
||||||
|
|
||||||
|
group :group {
|
||||||
|
# A group.
|
||||||
|
|
||||||
|
typeId @7 :Id;
|
||||||
|
# The ID of the group's node.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ordinal :union {
|
||||||
|
implicit @8 :Void;
|
||||||
|
explicit @9 :UInt16;
|
||||||
|
# The original ordinal number given to the field. You probably should NOT use this; if you need
|
||||||
|
# a numeric identifier for a field, use its position within the field array for its scope.
|
||||||
|
# The ordinal is given here mainly just so that the original schema text can be reproduced given
|
||||||
|
# the compiled version -- i.e. so that `capnp compile -ocapnp` can do its job.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Enumerant {
|
||||||
|
# Schema for member of an enum.
|
||||||
|
|
||||||
|
name @0 :Text;
|
||||||
|
|
||||||
|
codeOrder @1 :UInt16;
|
||||||
|
# Specifies order in which the enumerants were declared in the code.
|
||||||
|
# Like Struct.Field.codeOrder.
|
||||||
|
|
||||||
|
annotations @2 :List(Annotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Superclass {
|
||||||
|
id @0 :Id;
|
||||||
|
brand @1 :Brand;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Method {
|
||||||
|
# Schema for method of an interface.
|
||||||
|
|
||||||
|
name @0 :Text;
|
||||||
|
|
||||||
|
codeOrder @1 :UInt16;
|
||||||
|
# Specifies order in which the methods were declared in the code.
|
||||||
|
# Like Struct.Field.codeOrder.
|
||||||
|
|
||||||
|
implicitParameters @7 :List(Node.Parameter);
|
||||||
|
# The parameters listed in [] (typically, type / generic parameters), whose bindings are intended
|
||||||
|
# to be inferred rather than specified explicitly, although not all languages support this.
|
||||||
|
|
||||||
|
paramStructType @2 :Id;
|
||||||
|
# ID of the parameter struct type. If a named parameter list was specified in the method
|
||||||
|
# declaration (rather than a single struct parameter type) then a corresponding struct type is
|
||||||
|
# auto-generated. Such an auto-generated type will not be listed in the interface's
|
||||||
|
# `nestedNodes` and its `scopeId` will be zero -- it is completely detached from the namespace.
|
||||||
|
# (Awkwardly, it does of course inherit generic parameters from the method's scope, which makes
|
||||||
|
# this a situation where you can't just climb the scope chain to find where a particular
|
||||||
|
# generic parameter was introduced. Making the `scopeId` zero was a mistake.)
|
||||||
|
|
||||||
|
paramBrand @5 :Brand;
|
||||||
|
# Brand of param struct type.
|
||||||
|
|
||||||
|
resultStructType @3 :Id;
|
||||||
|
# ID of the return struct type; similar to `paramStructType`.
|
||||||
|
|
||||||
|
resultBrand @6 :Brand;
|
||||||
|
# Brand of result struct type.
|
||||||
|
|
||||||
|
annotations @4 :List(Annotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Type {
|
||||||
|
# Represents a type expression.
|
||||||
|
|
||||||
|
union {
|
||||||
|
# The ordinals intentionally match those of Value.
|
||||||
|
|
||||||
|
void @0 :Void;
|
||||||
|
bool @1 :Void;
|
||||||
|
int8 @2 :Void;
|
||||||
|
int16 @3 :Void;
|
||||||
|
int32 @4 :Void;
|
||||||
|
int64 @5 :Void;
|
||||||
|
uint8 @6 :Void;
|
||||||
|
uint16 @7 :Void;
|
||||||
|
uint32 @8 :Void;
|
||||||
|
uint64 @9 :Void;
|
||||||
|
float32 @10 :Void;
|
||||||
|
float64 @11 :Void;
|
||||||
|
text @12 :Void;
|
||||||
|
data @13 :Void;
|
||||||
|
|
||||||
|
list :group {
|
||||||
|
elementType @14 :Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum :group {
|
||||||
|
typeId @15 :Id;
|
||||||
|
brand @21 :Brand;
|
||||||
|
}
|
||||||
|
struct :group {
|
||||||
|
typeId @16 :Id;
|
||||||
|
brand @22 :Brand;
|
||||||
|
}
|
||||||
|
interface :group {
|
||||||
|
typeId @17 :Id;
|
||||||
|
brand @23 :Brand;
|
||||||
|
}
|
||||||
|
|
||||||
|
anyPointer :union {
|
||||||
|
unconstrained :union {
|
||||||
|
# A regular AnyPointer.
|
||||||
|
#
|
||||||
|
# The name "unconstrained" means as opposed to constraining it to match a type parameter.
|
||||||
|
# In retrospect this name is probably a poor choice given that it may still be constrained
|
||||||
|
# to be a struct, list, or capability.
|
||||||
|
|
||||||
|
anyKind @18 :Void; # truly AnyPointer
|
||||||
|
struct @25 :Void; # AnyStruct
|
||||||
|
list @26 :Void; # AnyList
|
||||||
|
capability @27 :Void; # Capability
|
||||||
|
}
|
||||||
|
|
||||||
|
parameter :group {
|
||||||
|
# This is actually a reference to a type parameter defined within this scope.
|
||||||
|
|
||||||
|
scopeId @19 :Id;
|
||||||
|
# ID of the generic type whose parameter we're referencing. This should be a parent of the
|
||||||
|
# current scope.
|
||||||
|
|
||||||
|
parameterIndex @20 :UInt16;
|
||||||
|
# Index of the parameter within the generic type's parameter list.
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitMethodParameter :group {
|
||||||
|
# This is actually a reference to an implicit (generic) parameter of a method. The only
|
||||||
|
# legal context for this type to appear is inside Method.paramBrand or Method.resultBrand.
|
||||||
|
|
||||||
|
parameterIndex @24 :UInt16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Brand {
|
||||||
|
# Specifies bindings for parameters of generics. Since these bindings turn a generic into a
|
||||||
|
# non-generic, we call it the "brand".
|
||||||
|
|
||||||
|
scopes @0 :List(Scope);
|
||||||
|
# For each of the target type and each of its parent scopes, a parameterization may be included
|
||||||
|
# in this list. If no parameterization is included for a particular relevant scope, then either
|
||||||
|
# that scope has no parameters or all parameters should be considered to be `AnyPointer`.
|
||||||
|
|
||||||
|
struct Scope {
|
||||||
|
scopeId @0 :Id;
|
||||||
|
# ID of the scope to which these params apply.
|
||||||
|
|
||||||
|
union {
|
||||||
|
bind @1 :List(Binding);
|
||||||
|
# List of parameter bindings.
|
||||||
|
|
||||||
|
inherit @2 :Void;
|
||||||
|
# The place where this Brand appears is actually within this scope or a sub-scope,
|
||||||
|
# and the bindings for this scope should be inherited from the reference point.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Binding {
|
||||||
|
union {
|
||||||
|
unbound @0 :Void;
|
||||||
|
type @1 :Type;
|
||||||
|
|
||||||
|
# TODO(someday): Allow non-type parameters? Unsure if useful.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Value {
|
||||||
|
# Represents a value, e.g. a field default value, constant value, or annotation value.
|
||||||
|
|
||||||
|
union {
|
||||||
|
# The ordinals intentionally match those of Type.
|
||||||
|
|
||||||
|
void @0 :Void;
|
||||||
|
bool @1 :Bool;
|
||||||
|
int8 @2 :Int8;
|
||||||
|
int16 @3 :Int16;
|
||||||
|
int32 @4 :Int32;
|
||||||
|
int64 @5 :Int64;
|
||||||
|
uint8 @6 :UInt8;
|
||||||
|
uint16 @7 :UInt16;
|
||||||
|
uint32 @8 :UInt32;
|
||||||
|
uint64 @9 :UInt64;
|
||||||
|
float32 @10 :Float32;
|
||||||
|
float64 @11 :Float64;
|
||||||
|
text @12 :Text;
|
||||||
|
data @13 :Data;
|
||||||
|
|
||||||
|
list @14 :AnyPointer;
|
||||||
|
|
||||||
|
enum @15 :UInt16;
|
||||||
|
struct @16 :AnyPointer;
|
||||||
|
|
||||||
|
interface @17 :Void;
|
||||||
|
# The only interface value that can be represented statically is "null", whose methods always
|
||||||
|
# throw exceptions.
|
||||||
|
|
||||||
|
anyPointer @18 :AnyPointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Annotation {
|
||||||
|
# Describes an annotation applied to a declaration. Note AnnotationNode describes the
|
||||||
|
# annotation's declaration, while this describes a use of the annotation.
|
||||||
|
|
||||||
|
id @0 :Id;
|
||||||
|
# ID of the annotation node.
|
||||||
|
|
||||||
|
brand @2 :Brand;
|
||||||
|
# Brand of the annotation.
|
||||||
|
#
|
||||||
|
# Note that the annotation itself is not allowed to be parameterized, but its scope might be.
|
||||||
|
|
||||||
|
value @1 :Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ElementSize {
|
||||||
|
# Possible element sizes for encoded lists. These correspond exactly to the possible values of
|
||||||
|
# the 3-bit element size component of a list pointer.
|
||||||
|
|
||||||
|
empty @0; # aka "void", but that's a keyword.
|
||||||
|
bit @1;
|
||||||
|
byte @2;
|
||||||
|
twoBytes @3;
|
||||||
|
fourBytes @4;
|
||||||
|
eightBytes @5;
|
||||||
|
pointer @6;
|
||||||
|
inlineComposite @7;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CapnpVersion {
|
||||||
|
major @0 :UInt16;
|
||||||
|
minor @1 :UInt8;
|
||||||
|
micro @2 :UInt8;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CodeGeneratorRequest {
|
||||||
|
capnpVersion @2 :CapnpVersion;
|
||||||
|
# Version of the `capnp` executable. Generally, code generators should ignore this, but the code
|
||||||
|
# generators that ship with `capnp` itself will print a warning if this mismatches since that
|
||||||
|
# probably indicates something is misconfigured.
|
||||||
|
#
|
||||||
|
# The first version of 'capnp' to set this was 0.6.0. So, if it's missing, the compiler version
|
||||||
|
# is older than that.
|
||||||
|
|
||||||
|
nodes @0 :List(Node);
|
||||||
|
# All nodes parsed by the compiler, including for the files on the command line and their
|
||||||
|
# imports.
|
||||||
|
|
||||||
|
sourceInfo @3 :List(Node.SourceInfo);
|
||||||
|
# Information about the original source code for each node, where available. This array may be
|
||||||
|
# omitted or may be missing some nodes if no info is available for them.
|
||||||
|
|
||||||
|
requestedFiles @1 :List(RequestedFile);
|
||||||
|
# Files which were listed on the command line.
|
||||||
|
|
||||||
|
struct RequestedFile {
|
||||||
|
id @0 :Id;
|
||||||
|
# ID of the file.
|
||||||
|
|
||||||
|
filename @1 :Text;
|
||||||
|
# Name of the file as it appeared on the command-line (minus the src-prefix). You may use
|
||||||
|
# this to decide where to write the output.
|
||||||
|
|
||||||
|
imports @2 :List(Import);
|
||||||
|
# List of all imported paths seen in this file.
|
||||||
|
|
||||||
|
struct Import {
|
||||||
|
id @0 :Id;
|
||||||
|
# ID of the imported file.
|
||||||
|
|
||||||
|
name @1 :Text;
|
||||||
|
# Name which *this* file used to refer to the foreign file. This may be a relative name.
|
||||||
|
# This information is provided because it might be useful for code generation, e.g. to
|
||||||
|
# generate #include directives in C++. We don't put this in Node.file because this
|
||||||
|
# information is only meaningful at compile time anyway.
|
||||||
|
#
|
||||||
|
# (On Zooko's triangle, this is the import's petname according to the importing file.)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -40,7 +40,7 @@ namespace CapnpC.CSharp.Generator
|
|||||||
{
|
{
|
||||||
var segments = Framing.ReadSegments(input);
|
var segments = Framing.ReadSegments(input);
|
||||||
var dec = DeserializerState.CreateRoot(segments);
|
var dec = DeserializerState.CreateRoot(segments);
|
||||||
var reader = Schema.CodeGeneratorRequest.Reader.Create(dec);
|
var reader = Schema.CodeGeneratorRequest.READER.create(dec);
|
||||||
var model = Model.SchemaModel.Create(reader);
|
var model = Model.SchemaModel.Create(reader);
|
||||||
var codeGen = new CodeGen.CodeGenerator(model, options ?? new CodeGen.GeneratorOptions());
|
var codeGen = new CodeGen.CodeGenerator(model, options ?? new CodeGen.GeneratorOptions());
|
||||||
return new GenerationResult(codeGen.Generate());
|
return new GenerationResult(codeGen.Generate());
|
||||||
|
@ -40,7 +40,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
|
|||||||
EqualsValueClause(
|
EqualsValueClause(
|
||||||
LiteralExpression(
|
LiteralExpression(
|
||||||
SyntaxKind.NumericLiteralExpression,
|
SyntaxKind.NumericLiteralExpression,
|
||||||
Literal(Schema.Field.Reader.NoDiscriminant))));
|
Literal(SchemaModel.NoDiscriminant))));
|
||||||
|
|
||||||
whichEnum = whichEnum.AddMembers(ndecl);
|
whichEnum = whichEnum.AddMembers(ndecl);
|
||||||
|
|
||||||
|
@ -8,21 +8,23 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
{
|
{
|
||||||
class SchemaModel
|
class SchemaModel
|
||||||
{
|
{
|
||||||
readonly Schema.CodeGeneratorRequest.Reader _request;
|
public const ushort NoDiscriminant = 65535;
|
||||||
|
|
||||||
|
readonly Schema.CodeGeneratorRequest.READER _request;
|
||||||
readonly List<GenFile> _generatedFiles = new List<GenFile>();
|
readonly List<GenFile> _generatedFiles = new List<GenFile>();
|
||||||
readonly DefinitionManager _typeDefMgr = new DefinitionManager();
|
readonly DefinitionManager _typeDefMgr = new DefinitionManager();
|
||||||
|
|
||||||
readonly Dictionary<ulong, Schema.Node.Reader> _id2node = new Dictionary<ulong, Schema.Node.Reader>();
|
readonly Dictionary<ulong, Schema.Node.READER> _id2node = new Dictionary<ulong, Schema.Node.READER>();
|
||||||
readonly Dictionary<ulong, SourceInfo> _id2sourceInfo = new Dictionary<ulong, SourceInfo>();
|
readonly Dictionary<ulong, SourceInfo> _id2sourceInfo = new Dictionary<ulong, SourceInfo>();
|
||||||
|
|
||||||
public SchemaModel(Schema.CodeGeneratorRequest.Reader request)
|
public SchemaModel(Schema.CodeGeneratorRequest.READER request)
|
||||||
{
|
{
|
||||||
_request = request;
|
_request = request;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IReadOnlyList<GenFile> FilesToGenerate => _generatedFiles;
|
public IReadOnlyList<GenFile> FilesToGenerate => _generatedFiles;
|
||||||
|
|
||||||
Schema.Node.Reader? IdToNode(ulong id, bool mustExist)
|
Schema.Node.READER? IdToNode(ulong id, bool mustExist)
|
||||||
{
|
{
|
||||||
if (_id2node.TryGetValue(id, out var node))
|
if (_id2node.TryGetValue(id, out var node))
|
||||||
return node;
|
return node;
|
||||||
@ -31,9 +33,9 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Schema.Node.Reader IdToNode(ulong id)
|
Schema.Node.READER IdToNode(ulong id)
|
||||||
{
|
{
|
||||||
return (Schema.Node.Reader)IdToNode(id, true);
|
return (Schema.Node.READER)IdToNode(id, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Build()
|
void Build()
|
||||||
@ -76,13 +78,13 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
public IHasNestedDefinitions parent;
|
public IHasNestedDefinitions parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildPass1(Dictionary<ulong, Schema.CodeGeneratorRequest.RequestedFile.Reader> requestedFiles)
|
void BuildPass1(Dictionary<ulong, Schema.CodeGeneratorRequest.RequestedFile.READER> requestedFiles)
|
||||||
{
|
{
|
||||||
Pass1State state = new Pass1State()
|
Pass1State state = new Pass1State()
|
||||||
{
|
{
|
||||||
unprocessedNodes = new HashSet<ulong>(_id2node.Keys)
|
unprocessedNodes = new HashSet<ulong>(_id2node.Keys)
|
||||||
};
|
};
|
||||||
foreach (var node in _id2node.Values.Where(n => n.IsFile))
|
foreach (var node in _id2node.Values.Where(n => n.which == Schema.Node.WHICH.File))
|
||||||
{
|
{
|
||||||
GenFile file;
|
GenFile file;
|
||||||
bool isGenerated = requestedFiles.TryGetValue(node.Id, out var req);
|
bool isGenerated = requestedFiles.TryGetValue(node.Id, out var req);
|
||||||
@ -118,7 +120,7 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
IDefinition ProcessNodePass1(ulong id, string name, Pass1State state)
|
IDefinition ProcessNodePass1(ulong id, string name, Pass1State state)
|
||||||
{
|
{
|
||||||
bool mustExist = state.parent == null || (state.parent as IDefinition).IsGenerated;
|
bool mustExist = state.parent == null || (state.parent as IDefinition).IsGenerated;
|
||||||
if (!(IdToNode(id, mustExist) is Schema.Node.Reader node))
|
if (!(IdToNode(id, mustExist) is Schema.Node.READER node))
|
||||||
return null;
|
return null;
|
||||||
if (!state.unprocessedNodes.Remove(id))
|
if (!state.unprocessedNodes.Remove(id))
|
||||||
return null;
|
return null;
|
||||||
@ -175,18 +177,18 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
{
|
{
|
||||||
ProcessNodePass1(nested.Id, nested.Name, state);
|
ProcessNodePass1(nested.Id, nested.Name, state);
|
||||||
}
|
}
|
||||||
if (processFields && node.Fields != null)
|
if (processFields && node.Struct.Fields != null)
|
||||||
foreach (var field in node.Fields.Where(f => f.IsGroup))
|
foreach (var field in node.Struct.Fields.Where(f => f.which == Schema.Field.WHICH.Group))
|
||||||
{
|
{
|
||||||
var group = IdToNode(field.Group_TypeId);
|
var group = IdToNode(field.Group.TypeId);
|
||||||
if (!group.IsStruct || !group.Struct_IsGroup)
|
if (group.which != Schema.Node.WHICH.Struct || !group.Struct.IsGroup)
|
||||||
{
|
{
|
||||||
throw new InvalidSchemaException($"Expected node with id {group.StrId()} to be a struct definition");
|
throw new InvalidSchemaException($"Expected node with id {group.StrId()} to be a struct definition");
|
||||||
}
|
}
|
||||||
ProcessNodePass1(field.Group_TypeId, field.Name, state);
|
ProcessNodePass1(field.Group.TypeId, field.Name, state);
|
||||||
}
|
}
|
||||||
if (processInterfaceMethods && node.Interface_Methods != null)
|
if (processInterfaceMethods && node.Interface.Methods != null)
|
||||||
foreach (var method in node.Interface_Methods)
|
foreach (var method in node.Interface.Methods)
|
||||||
{
|
{
|
||||||
var pnode = IdToNode(method.ParamStructType);
|
var pnode = IdToNode(method.ParamStructType);
|
||||||
if (pnode.ScopeId == 0) ProcessNodePass1(pnode.Id, null, state); // Anonymous generated type
|
if (pnode.ScopeId == 0) ProcessNodePass1(pnode.Id, null, state); // Anonymous generated type
|
||||||
@ -204,7 +206,7 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
public HashSet<ulong> processedNodes;
|
public HashSet<ulong> processedNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildPass2(Dictionary<ulong, Schema.CodeGeneratorRequest.RequestedFile.Reader> requestedFiles)
|
void BuildPass2(Dictionary<ulong, Schema.CodeGeneratorRequest.RequestedFile.READER> requestedFiles)
|
||||||
{
|
{
|
||||||
var state = new Pass2State() { processedNodes = new HashSet<ulong>() };
|
var state = new Pass2State() { processedNodes = new HashSet<ulong>() };
|
||||||
foreach (var file in _typeDefMgr.Files)
|
foreach (var file in _typeDefMgr.Files)
|
||||||
@ -214,7 +216,7 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessNestedNodes(IEnumerable<Schema.Node.NestedNode.Reader> nestedNodes, Pass2State state, bool mustExist)
|
void ProcessNestedNodes(IEnumerable<Schema.Node.NestedNode.READER> nestedNodes, Pass2State state, bool mustExist)
|
||||||
{
|
{
|
||||||
foreach (var nestedNode in nestedNodes)
|
foreach (var nestedNode in nestedNodes)
|
||||||
{
|
{
|
||||||
@ -222,16 +224,16 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessBrand(Schema.Brand.Reader brandReader, Type type, Pass2State state)
|
void ProcessBrand(Schema.Brand.READER brandReader, Type type, Pass2State state)
|
||||||
{
|
{
|
||||||
foreach (var scopeReader in brandReader.Scopes)
|
foreach (var scopeReader in brandReader.Scopes)
|
||||||
{
|
{
|
||||||
var whatToBind = ProcessTypeDef(scopeReader.ScopeId, state);
|
var whatToBind = ProcessTypeDef(scopeReader.ScopeId, state);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
switch (0)
|
switch (scopeReader.which)
|
||||||
{
|
{
|
||||||
case 0 when scopeReader.IsBind:
|
case Schema.Brand.Scope.WHICH.Bind:
|
||||||
foreach (var bindingReader in scopeReader.Bind)
|
foreach (var bindingReader in scopeReader.Bind)
|
||||||
{
|
{
|
||||||
var typeParameter = new GenericParameter()
|
var typeParameter = new GenericParameter()
|
||||||
@ -240,20 +242,20 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
Index = index++
|
Index = index++
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (0)
|
switch (bindingReader.which)
|
||||||
{
|
{
|
||||||
case 0 when bindingReader.IsType:
|
case Schema.Brand.Binding.WHICH.Type:
|
||||||
type.BindGenericParameter(typeParameter, ProcessType(bindingReader.Type, state));
|
type.BindGenericParameter(typeParameter, ProcessType(bindingReader.Type, state));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when bindingReader.IsUnbound:
|
case Schema.Brand.Binding.WHICH.Unbound:
|
||||||
type.BindGenericParameter(typeParameter, Types.FromParameter(typeParameter));
|
type.BindGenericParameter(typeParameter, Types.FromParameter(typeParameter));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when scopeReader.IsInherit:
|
case Schema.Brand.Scope.WHICH.Inherit:
|
||||||
for (index = 0; index < type.DeclaringType.Definition.GenericParameters.Count; index++)
|
for (index = 0; index < type.DeclaringType.Definition.GenericParameters.Count; index++)
|
||||||
{
|
{
|
||||||
var typeParameter = new GenericParameter()
|
var typeParameter = new GenericParameter()
|
||||||
@ -269,45 +271,44 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type ProcessType(Schema.Type.Reader typeReader, Pass2State state)
|
Type ProcessType(Schema.Type.READER typeReader, Pass2State state)
|
||||||
{
|
{
|
||||||
Type result;
|
Type result;
|
||||||
|
|
||||||
switch (0)
|
switch (typeReader.which)
|
||||||
{
|
{
|
||||||
case 0 when typeReader.IsAnyPointer:
|
case Schema.Type.WHICH.AnyPointer:
|
||||||
switch (0)
|
switch (typeReader.AnyPointer.which)
|
||||||
{
|
{
|
||||||
case 0 when typeReader.AnyPointer_IsParameter:
|
case Schema.Type.anyPointer.WHICH.Parameter:
|
||||||
return Types.FromParameter(
|
return Types.FromParameter(
|
||||||
new GenericParameter()
|
new GenericParameter()
|
||||||
{
|
{
|
||||||
DeclaringEntity = ProcessTypeDef(typeReader.AnyPointer_Parameter_ScopeId, state),
|
DeclaringEntity = ProcessTypeDef(typeReader.AnyPointer.Parameter.ScopeId, state),
|
||||||
Index = typeReader.AnyPointer_Parameter_ParameterIndex
|
Index = typeReader.AnyPointer.Parameter.ParameterIndex
|
||||||
});
|
});
|
||||||
|
|
||||||
case 0 when typeReader.AnyPointer_IsImplicitMethodParameter:
|
case Schema.Type.anyPointer.WHICH.ImplicitMethodParameter:
|
||||||
return Types.FromParameter(
|
return Types.FromParameter(
|
||||||
new GenericParameter()
|
new GenericParameter()
|
||||||
{
|
{
|
||||||
DeclaringEntity = state.currentMethod ?? throw new InvalidOperationException("current method not set"),
|
DeclaringEntity = state.currentMethod ?? throw new InvalidOperationException("current method not set"),
|
||||||
Index = typeReader.AnyPointer_ImplicitMethodParameter_ParameterIndex
|
Index = typeReader.AnyPointer.ImplicitMethodParameter.ParameterIndex
|
||||||
});
|
});
|
||||||
|
|
||||||
case 0 when typeReader.AnyPointer_IsUnconstrained:
|
case Schema.Type.anyPointer.WHICH.Unconstrained:
|
||||||
|
switch (typeReader.AnyPointer.Unconstrained.which)
|
||||||
switch (0)
|
|
||||||
{
|
{
|
||||||
case 0 when typeReader.AnyPointer_Unconstrained_IsAnyKind:
|
case Schema.Type.anyPointer.unconstrained.WHICH.AnyKind:
|
||||||
return Types.AnyPointer;
|
return Types.AnyPointer;
|
||||||
|
|
||||||
case 0 when typeReader.AnyPointer_Unconstrained_IsCapability:
|
case Schema.Type.anyPointer.unconstrained.WHICH.Capability:
|
||||||
return Types.CapabilityPointer;
|
return Types.CapabilityPointer;
|
||||||
|
|
||||||
case 0 when typeReader.AnyPointer_Unconstrained_IsList:
|
case Schema.Type.anyPointer.unconstrained.WHICH.List:
|
||||||
return Types.ListPointer;
|
return Types.ListPointer;
|
||||||
|
|
||||||
case 0 when typeReader.AnyPointer_Unconstrained_IsStruct:
|
case Schema.Type.anyPointer.unconstrained.WHICH.Struct:
|
||||||
return Types.StructPointer;
|
return Types.StructPointer;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -318,62 +319,62 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0 when typeReader.IsBool:
|
case Schema.Type.WHICH.Bool:
|
||||||
return Types.Bool;
|
return Types.Bool;
|
||||||
|
|
||||||
case 0 when typeReader.IsData:
|
case Schema.Type.WHICH.Data:
|
||||||
return Types.Data;
|
return Types.Data;
|
||||||
|
|
||||||
case 0 when typeReader.IsFloat64:
|
case Schema.Type.WHICH.Float64:
|
||||||
return Types.F64;
|
return Types.F64;
|
||||||
|
|
||||||
case 0 when typeReader.IsEnum:
|
case Schema.Type.WHICH.Enum:
|
||||||
return Types.FromDefinition(ProcessTypeDef(typeReader.Enum_TypeId, state, TypeTag.Enum));
|
return Types.FromDefinition(ProcessTypeDef(typeReader.Enum.TypeId, state, TypeTag.Enum));
|
||||||
|
|
||||||
case 0 when typeReader.IsFloat32:
|
case Schema.Type.WHICH.Float32:
|
||||||
return Types.F32;
|
return Types.F32;
|
||||||
|
|
||||||
case 0 when typeReader.IsInt16:
|
case Schema.Type.WHICH.Int16:
|
||||||
return Types.S16;
|
return Types.S16;
|
||||||
|
|
||||||
case 0 when typeReader.IsInt32:
|
case Schema.Type.WHICH.Int32:
|
||||||
return Types.S32;
|
return Types.S32;
|
||||||
|
|
||||||
case 0 when typeReader.IsInt64:
|
case Schema.Type.WHICH.Int64:
|
||||||
return Types.S64;
|
return Types.S64;
|
||||||
|
|
||||||
case 0 when typeReader.IsInt8:
|
case Schema.Type.WHICH.Int8:
|
||||||
return Types.S8;
|
return Types.S8;
|
||||||
|
|
||||||
case 0 when typeReader.IsInterface:
|
case Schema.Type.WHICH.Interface:
|
||||||
result = Types.FromDefinition(ProcessTypeDef(typeReader.Interface_TypeId, state, TypeTag.Interface));
|
result = Types.FromDefinition(ProcessTypeDef(typeReader.Interface.TypeId, state, TypeTag.Interface));
|
||||||
ProcessBrand(typeReader.Interface_Brand, result, state);
|
ProcessBrand(typeReader.Interface.Brand, result, state);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
case 0 when typeReader.IsList:
|
case Schema.Type.WHICH.List:
|
||||||
return Types.List(ProcessType(typeReader.List_ElementType, state));
|
return Types.List(ProcessType(typeReader.List.ElementType, state));
|
||||||
|
|
||||||
case 0 when typeReader.IsStruct:
|
case Schema.Type.WHICH.Struct:
|
||||||
result = Types.FromDefinition(ProcessTypeDef(typeReader.Struct_TypeId, state, TypeTag.Struct));
|
result = Types.FromDefinition(ProcessTypeDef(typeReader.Struct.TypeId, state, TypeTag.Struct));
|
||||||
ProcessBrand(typeReader.Struct_Brand, result, state);
|
ProcessBrand(typeReader.Struct.Brand, result, state);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
case 0 when typeReader.IsText:
|
case Schema.Type.WHICH.Text:
|
||||||
return Types.Text;
|
return Types.Text;
|
||||||
|
|
||||||
case 0 when typeReader.IsUInt16:
|
case Schema.Type.WHICH.Uint16:
|
||||||
return Types.U16;
|
return Types.U16;
|
||||||
|
|
||||||
case 0 when typeReader.IsUInt32:
|
case Schema.Type.WHICH.Uint32:
|
||||||
return Types.U32;
|
return Types.U32;
|
||||||
|
|
||||||
case 0 when typeReader.IsUInt64:
|
case Schema.Type.WHICH.Uint64:
|
||||||
return Types.U64;
|
return Types.U64;
|
||||||
|
|
||||||
case 0 when typeReader.IsUInt8:
|
case Schema.Type.WHICH.Uint8:
|
||||||
return Types.U8;
|
return Types.U8;
|
||||||
|
|
||||||
case 0 when typeReader.IsVoid:
|
case Schema.Type.WHICH.Void:
|
||||||
return Types.Void;
|
return Types.Void;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -381,103 +382,103 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Value ProcessValue(Schema.Value.Reader valueReader)
|
Value ProcessValue(Schema.Value.READER valueReader)
|
||||||
{
|
{
|
||||||
var value = new Value();
|
var value = new Value();
|
||||||
|
|
||||||
switch (0)
|
switch (valueReader.which)
|
||||||
{
|
{
|
||||||
case 0 when valueReader.IsAnyPointer:
|
case Schema.Value.WHICH.AnyPointer:
|
||||||
value.ScalarValue = valueReader.AnyPointer;
|
value.ScalarValue = valueReader.AnyPointer;
|
||||||
value.Type = Types.AnyPointer;
|
value.Type = Types.AnyPointer;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsBool:
|
case Schema.Value.WHICH.Bool:
|
||||||
value.ScalarValue = valueReader.Bool;
|
value.ScalarValue = valueReader.Bool;
|
||||||
value.Type = Types.Bool;
|
value.Type = Types.Bool;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsData:
|
case Schema.Value.WHICH.Data:
|
||||||
value.Items.AddRange(valueReader.Data.CastByte().Select(Value.Scalar));
|
value.Items.AddRange(valueReader.Data.Select(Value.Scalar));
|
||||||
value.Type = Types.Data;
|
value.Type = Types.Data;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsEnum:
|
case Schema.Value.WHICH.Enum:
|
||||||
value.ScalarValue = valueReader.Enum;
|
value.ScalarValue = valueReader.Enum;
|
||||||
value.Type = Types.AnyEnum;
|
value.Type = Types.AnyEnum;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsFloat32:
|
case Schema.Value.WHICH.Float32:
|
||||||
value.ScalarValue = valueReader.Float32;
|
value.ScalarValue = valueReader.Float32;
|
||||||
value.Type = Types.F32;
|
value.Type = Types.F32;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsFloat64:
|
case Schema.Value.WHICH.Float64:
|
||||||
value.ScalarValue = valueReader.Float64;
|
value.ScalarValue = valueReader.Float64;
|
||||||
value.Type = Types.F64;
|
value.Type = Types.F64;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsInt16:
|
case Schema.Value.WHICH.Int16:
|
||||||
value.ScalarValue = valueReader.Int16;
|
value.ScalarValue = valueReader.Int16;
|
||||||
value.Type = Types.S16;
|
value.Type = Types.S16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsInt32:
|
case Schema.Value.WHICH.Int32:
|
||||||
value.ScalarValue = valueReader.Int32;
|
value.ScalarValue = valueReader.Int32;
|
||||||
value.Type = Types.S32;
|
value.Type = Types.S32;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsInt64:
|
case Schema.Value.WHICH.Int64:
|
||||||
value.ScalarValue = valueReader.Int64;
|
value.ScalarValue = valueReader.Int64;
|
||||||
value.Type = Types.S64;
|
value.Type = Types.S64;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsInt8:
|
case Schema.Value.WHICH.Int8:
|
||||||
value.ScalarValue = valueReader.Int8;
|
value.ScalarValue = valueReader.Int8;
|
||||||
value.Type = Types.S8;
|
value.Type = Types.S8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsInterface:
|
case Schema.Value.WHICH.Interface:
|
||||||
value.ScalarValue = null;
|
value.ScalarValue = null;
|
||||||
value.Type = Types.CapabilityPointer;
|
value.Type = Types.CapabilityPointer;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsList:
|
case Schema.Value.WHICH.List:
|
||||||
value.RawValue = valueReader.List;
|
value.RawValue = valueReader.List;
|
||||||
value.Type = Types.ListPointer;
|
value.Type = Types.ListPointer;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsStruct:
|
case Schema.Value.WHICH.Struct:
|
||||||
value.RawValue = valueReader.Struct;
|
value.RawValue = valueReader.Struct;
|
||||||
value.Type = Types.StructPointer;
|
value.Type = Types.StructPointer;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsText:
|
case Schema.Value.WHICH.Text:
|
||||||
value.ScalarValue = valueReader.Text;
|
value.ScalarValue = valueReader.Text;
|
||||||
value.Type = Types.Text;
|
value.Type = Types.Text;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsUInt16:
|
case Schema.Value.WHICH.Uint16:
|
||||||
value.ScalarValue = valueReader.UInt16;
|
value.ScalarValue = valueReader.Uint16;
|
||||||
value.Type = Types.U16;
|
value.Type = Types.U16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsUInt32:
|
case Schema.Value.WHICH.Uint32:
|
||||||
value.ScalarValue = valueReader.UInt32;
|
value.ScalarValue = valueReader.Uint32;
|
||||||
value.Type = Types.U32;
|
value.Type = Types.U32;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsUInt64:
|
case Schema.Value.WHICH.Uint64:
|
||||||
value.ScalarValue = valueReader.UInt64;
|
value.ScalarValue = valueReader.Uint64;
|
||||||
value.Type = Types.U64;
|
value.Type = Types.U64;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsUInt8:
|
case Schema.Value.WHICH.Uint8:
|
||||||
value.ScalarValue = valueReader.UInt8;
|
value.ScalarValue = valueReader.Uint8;
|
||||||
value.Type = Types.U8;
|
value.Type = Types.U8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when valueReader.IsVoid:
|
case Schema.Value.WHICH.Void:
|
||||||
value.Type = Types.Void;
|
value.Type = Types.Void;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -488,14 +489,14 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessFields(Schema.Node.Reader reader, TypeDefinition declaringType, List<Field> fields, Pass2State state)
|
void ProcessFields(Schema.Node.READER reader, TypeDefinition declaringType, List<Field> fields, Pass2State state)
|
||||||
{
|
{
|
||||||
if (reader.Fields == null)
|
if (reader.Struct.Fields == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var fieldReader in reader.Fields)
|
foreach (var fieldReader in reader.Struct.Fields)
|
||||||
{
|
{
|
||||||
var field = new Field()
|
var field = new Field()
|
||||||
{
|
{
|
||||||
@ -505,25 +506,25 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
CodeOrder = fieldReader.CodeOrder
|
CodeOrder = fieldReader.CodeOrder
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fieldReader.DiscriminantValue != Schema.Field.Reader.NoDiscriminant)
|
if (fieldReader.DiscriminantValue != NoDiscriminant)
|
||||||
{
|
{
|
||||||
field.DiscValue = fieldReader.DiscriminantValue;
|
field.DiscValue = fieldReader.DiscriminantValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (0)
|
switch (fieldReader.which)
|
||||||
{
|
{
|
||||||
case 0 when fieldReader.IsGroup:
|
case Schema.Field.WHICH.Group:
|
||||||
var def = ProcessTypeDef(fieldReader.Group_TypeId, state, TypeTag.Group);
|
var def = ProcessTypeDef(fieldReader.Group.TypeId, state, TypeTag.Group);
|
||||||
field.Type = Types.FromDefinition(def);
|
field.Type = Types.FromDefinition(def);
|
||||||
def.CsName = field.CsName; // Type definitions for unions are artificially generated.
|
def.CsName = field.CsName; // Type definitions for unions are artificially generated.
|
||||||
// Transfer the C# name of the using field.
|
// Transfer the C# name of the using field.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0 when fieldReader.IsSlot:
|
case Schema.Field.WHICH.Slot:
|
||||||
field.DefaultValue = ProcessValue(fieldReader.Slot_DefaultValue);
|
field.DefaultValue = ProcessValue(fieldReader.Slot.DefaultValue);
|
||||||
field.DefaultValueIsExplicit = fieldReader.Slot_HadExplicitDefault;
|
field.DefaultValueIsExplicit = fieldReader.Slot.HadExplicitDefault;
|
||||||
field.Offset = fieldReader.Slot_Offset;
|
field.Offset = fieldReader.Slot.Offset;
|
||||||
field.Type = ProcessType(fieldReader.Slot_Type, state);
|
field.Type = ProcessType(fieldReader.Slot.Type, state);
|
||||||
field.DefaultValue.Type = field.Type;
|
field.DefaultValue.Type = field.Type;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -537,7 +538,7 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeDefinition ProcessInterfaceOrStructTail(TypeDefinition def, Schema.Node.Reader reader, Pass2State state)
|
TypeDefinition ProcessInterfaceOrStructTail(TypeDefinition def, Schema.Node.READER reader, Pass2State state)
|
||||||
{
|
{
|
||||||
def.IsGeneric = reader.IsGeneric;
|
def.IsGeneric = reader.IsGeneric;
|
||||||
|
|
||||||
@ -553,9 +554,9 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
|
|
||||||
ProcessFields(reader, def, def.Fields, state);
|
ProcessFields(reader, def, def.Fields, state);
|
||||||
|
|
||||||
if (reader.IsInterface)
|
if (reader.which == Schema.Node.WHICH.Interface)
|
||||||
{
|
{
|
||||||
foreach (var methodReader in reader.Interface_Methods)
|
foreach (var methodReader in reader.Interface.Methods)
|
||||||
{
|
{
|
||||||
var method = new Method()
|
var method = new Method()
|
||||||
{
|
{
|
||||||
@ -608,22 +609,22 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeDefinition ProcessStruct(Schema.Node.Reader structReader, TypeDefinition def, Pass2State state)
|
TypeDefinition ProcessStruct(Schema.Node.READER structReader, TypeDefinition def, Pass2State state)
|
||||||
{
|
{
|
||||||
def.StructDataWordCount = structReader.Struct_DataWordCount;
|
def.StructDataWordCount = structReader.Struct.DataWordCount;
|
||||||
def.StructPointerCount = structReader.Struct_PointerCount;
|
def.StructPointerCount = structReader.Struct.PointerCount;
|
||||||
|
|
||||||
if (structReader.Struct_DiscriminantCount > 0)
|
if (structReader.Struct.DiscriminantCount > 0)
|
||||||
{
|
{
|
||||||
def.UnionInfo = new TypeDefinition.DiscriminationInfo(
|
def.UnionInfo = new TypeDefinition.DiscriminationInfo(
|
||||||
structReader.Struct_DiscriminantCount,
|
structReader.Struct.DiscriminantCount,
|
||||||
16u * structReader.Struct_DiscriminantOffset);
|
16u * structReader.Struct.DiscriminantOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ProcessInterfaceOrStructTail(def, structReader, state);
|
return ProcessInterfaceOrStructTail(def, structReader, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeDefinition ProcessParameterList(Schema.Node.Reader reader, Schema.Brand.Reader brandReader, List<Field> list, Pass2State state)
|
TypeDefinition ProcessParameterList(Schema.Node.READER reader, Schema.Brand.READER brandReader, List<Field> list, Pass2State state)
|
||||||
{
|
{
|
||||||
//# If a named parameter list was specified in the method
|
//# If a named parameter list was specified in the method
|
||||||
//# declaration (rather than a single struct parameter type) then a corresponding struct type is
|
//# declaration (rather than a single struct parameter type) then a corresponding struct type is
|
||||||
@ -633,7 +634,7 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
//# this a situation where you can't just climb the scope chain to find where a particular
|
//# this a situation where you can't just climb the scope chain to find where a particular
|
||||||
//# generic parameter was introduced. Making the `scopeId` zero was a mistake.)
|
//# generic parameter was introduced. Making the `scopeId` zero was a mistake.)
|
||||||
|
|
||||||
if (!reader.IsStruct)
|
if (reader.which != Schema.Node.WHICH.Struct)
|
||||||
{
|
{
|
||||||
throw new InvalidSchemaException("Expected a struct");
|
throw new InvalidSchemaException("Expected a struct");
|
||||||
}
|
}
|
||||||
@ -657,9 +658,9 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeDefinition ProcessInterface(Schema.Node.Reader ifaceReader, TypeDefinition def, Pass2State state)
|
TypeDefinition ProcessInterface(Schema.Node.READER ifaceReader, TypeDefinition def, Pass2State state)
|
||||||
{
|
{
|
||||||
foreach (var superClassReader in ifaceReader.Interface_Superclasses)
|
foreach (var superClassReader in ifaceReader.Interface.Superclasses)
|
||||||
{
|
{
|
||||||
var superClass = Types.FromDefinition(ProcessTypeDef(superClassReader.Id, state, TypeTag.Interface));
|
var superClass = Types.FromDefinition(ProcessTypeDef(superClassReader.Id, state, TypeTag.Interface));
|
||||||
ProcessBrand(superClassReader.Brand, superClass, state);
|
ProcessBrand(superClassReader.Brand, superClass, state);
|
||||||
@ -669,9 +670,9 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
return ProcessInterfaceOrStructTail(def, ifaceReader, state);
|
return ProcessInterfaceOrStructTail(def, ifaceReader, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeDefinition ProcessEnum(Schema.Node.Reader enumReader, TypeDefinition def, Pass2State state)
|
TypeDefinition ProcessEnum(Schema.Node.READER enumReader, TypeDefinition def, Pass2State state)
|
||||||
{
|
{
|
||||||
foreach (var fieldReader in enumReader.Enumerants)
|
foreach (var fieldReader in enumReader.Enum.Enumerants)
|
||||||
{
|
{
|
||||||
var field = new Enumerant()
|
var field = new Enumerant()
|
||||||
{
|
{
|
||||||
@ -681,20 +682,15 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
CodeOrder = fieldReader.CodeOrder
|
CodeOrder = fieldReader.CodeOrder
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fieldReader.Ordinal_IsExplicit)
|
|
||||||
{
|
|
||||||
field.Ordinal = fieldReader.Ordinal_Explicit;
|
|
||||||
}
|
|
||||||
|
|
||||||
def.Enumerants.Add(field);
|
def.Enumerants.Add(field);
|
||||||
}
|
}
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
Constant ProcessConst(Schema.Node.Reader constReader, Constant @const, Pass2State state)
|
Constant ProcessConst(Schema.Node.READER constReader, Constant @const, Pass2State state)
|
||||||
{
|
{
|
||||||
var value = ProcessValue(constReader.Const_Value);
|
var value = ProcessValue(constReader.Const.Value);
|
||||||
value.Type = ProcessType(constReader.Const_Type, state);
|
value.Type = ProcessType(constReader.Const.Type, state);
|
||||||
@const.Value = value;
|
@const.Value = value;
|
||||||
return @const;
|
return @const;
|
||||||
}
|
}
|
||||||
@ -712,7 +708,7 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
|
|
||||||
IDefinition ProcessNode(ulong id, Pass2State state, bool mustExist, TypeTag tag = default)
|
IDefinition ProcessNode(ulong id, Pass2State state, bool mustExist, TypeTag tag = default)
|
||||||
{
|
{
|
||||||
if (!(IdToNode(id, mustExist) is Schema.Node.Reader node)) return null;
|
if (!(IdToNode(id, mustExist) is Schema.Node.READER node)) return null;
|
||||||
var kind = node.GetKind();
|
var kind = node.GetKind();
|
||||||
if (tag == TypeTag.Unknown) tag = kind.GetTypeTag();
|
if (tag == TypeTag.Unknown) tag = kind.GetTypeTag();
|
||||||
var def = _typeDefMgr.GetExistingDef(id, tag);
|
var def = _typeDefMgr.GetExistingDef(id, tag);
|
||||||
@ -737,7 +733,7 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SchemaModel Create(Schema.CodeGeneratorRequest.Reader request)
|
public static SchemaModel Create(Schema.CodeGeneratorRequest.READER request)
|
||||||
{
|
{
|
||||||
var model = new SchemaModel(request);
|
var model = new SchemaModel(request);
|
||||||
model.Build();
|
model.Build();
|
||||||
@ -759,22 +755,24 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
|
|
||||||
public static class SchemaExtensions
|
public static class SchemaExtensions
|
||||||
{
|
{
|
||||||
public static string StrId(this Schema.Node.Reader node)
|
public static string StrId(this Schema.Node.READER node)
|
||||||
=> $"0x{node.Id:X}";
|
=> $"0x{node.Id:X}";
|
||||||
|
|
||||||
public static string StrId(this ulong nodeId)
|
public static string StrId(this ulong nodeId)
|
||||||
=> $"0x{nodeId:X}";
|
=> $"0x{nodeId:X}";
|
||||||
|
|
||||||
public static NodeKind GetKind(this Schema.Node.Reader node)
|
public static NodeKind GetKind(this Schema.Node.READER node)
|
||||||
{
|
{
|
||||||
if (node.IsStruct)
|
switch (node.which)
|
||||||
return node.Struct_IsGroup ? NodeKind.Group : NodeKind.Struct;
|
{
|
||||||
if (node.IsInterface) return NodeKind.Interface;
|
case Schema.Node.WHICH.Struct: return node.Struct.IsGroup ? NodeKind.Group : NodeKind.Struct;
|
||||||
if (node.IsEnum) return NodeKind.Enum;
|
case Schema.Node.WHICH.Interface: return NodeKind.Interface;
|
||||||
if (node.IsConst) return NodeKind.Const;
|
case Schema.Node.WHICH.Enum: return NodeKind.Enum;
|
||||||
if (node.IsAnnotation) return NodeKind.Annotation;
|
case Schema.Node.WHICH.Const: return NodeKind.Const;
|
||||||
if (node.IsFile) return NodeKind.File;
|
case Schema.Node.WHICH.Annotation: return NodeKind.Annotation;
|
||||||
return NodeKind.Unknown;
|
case Schema.Node.WHICH.File: return NodeKind.File;
|
||||||
|
default: return NodeKind.Unknown;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static TypeTag GetTypeTag(this NodeKind kind)
|
internal static TypeTag GetTypeTag(this NodeKind kind)
|
||||||
@ -789,7 +787,6 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static TypeTag GetTypeTag(this Schema.Node.Reader node)
|
internal static TypeTag GetTypeTag(this Schema.Node.READER node) => node.GetKind().GetTypeTag();
|
||||||
=> node.GetKind().GetTypeTag();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
Internal = 1
|
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)
|
||||||
{
|
{
|
||||||
@ -48,7 +48,7 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetCsName(Schema.Field.Reader node)
|
public static string GetCsName(Schema.Field.READER node)
|
||||||
{
|
{
|
||||||
foreach (var annotation in node.Annotations)
|
foreach (var annotation in node.Annotations)
|
||||||
{
|
{
|
||||||
@ -60,7 +60,7 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetCsName(Schema.Node.Reader node)
|
public static string GetCsName(Schema.Enumerant.READER node)
|
||||||
{
|
{
|
||||||
foreach (var annotation in node.Annotations)
|
foreach (var annotation in node.Annotations)
|
||||||
{
|
{
|
||||||
@ -72,7 +72,7 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetCsName(Schema.Method.Reader node)
|
public static string GetCsName(Schema.Node.READER node)
|
||||||
{
|
{
|
||||||
foreach (var annotation in node.Annotations)
|
foreach (var annotation in node.Annotations)
|
||||||
{
|
{
|
||||||
@ -84,11 +84,23 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool? GetNullableEnable(Schema.Node.Reader node)
|
public static string GetCsName(Schema.Method.READER node)
|
||||||
{
|
{
|
||||||
foreach (var annotation in node.Annotations)
|
foreach (var annotation in node.Annotations)
|
||||||
{
|
{
|
||||||
if (annotation.Id == AnnotationIds.Cs.NullableEnable && annotation.Value.IsBool)
|
if (annotation.Id == AnnotationIds.Cs.Name)
|
||||||
|
{
|
||||||
|
return annotation.Value.Text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool? GetNullableEnable(Schema.Node.READER node)
|
||||||
|
{
|
||||||
|
foreach (var annotation in node.Annotations)
|
||||||
|
{
|
||||||
|
if (annotation.Id == AnnotationIds.Cs.NullableEnable && annotation.Value.which == Schema.Value.WHICH.Bool)
|
||||||
{
|
{
|
||||||
return annotation.Value.Bool;
|
return annotation.Value.Bool;
|
||||||
}
|
}
|
||||||
@ -96,11 +108,11 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool? GetEmitNullableDirective(Schema.Node.Reader node)
|
public static bool? GetEmitNullableDirective(Schema.Node.READER node)
|
||||||
{
|
{
|
||||||
foreach (var annotation in node.Annotations)
|
foreach (var annotation in node.Annotations)
|
||||||
{
|
{
|
||||||
if (annotation.Id == AnnotationIds.Cs.EmitNullableDirective && annotation.Value.IsBool)
|
if (annotation.Id == AnnotationIds.Cs.EmitNullableDirective && annotation.Value.which == Schema.Value.WHICH.Bool)
|
||||||
{
|
{
|
||||||
return annotation.Value.Bool;
|
return annotation.Value.Bool;
|
||||||
}
|
}
|
||||||
@ -108,11 +120,11 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool? GetEmitDomainClassesAndInterfaces(Schema.Node.Reader node)
|
public static bool? GetEmitDomainClassesAndInterfaces(Schema.Node.READER node)
|
||||||
{
|
{
|
||||||
foreach (var annotation in node.Annotations)
|
foreach (var annotation in node.Annotations)
|
||||||
{
|
{
|
||||||
if (annotation.Id == AnnotationIds.Cs.EmitDomainClassesAndInterfaces && annotation.Value.IsBool)
|
if (annotation.Id == AnnotationIds.Cs.EmitDomainClassesAndInterfaces && annotation.Value.which == Schema.Value.WHICH.Bool)
|
||||||
{
|
{
|
||||||
return annotation.Value.Bool;
|
return annotation.Value.Bool;
|
||||||
}
|
}
|
||||||
@ -120,11 +132,11 @@ namespace CapnpC.CSharp.Generator.Model
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TypeVisibility? GetTypeVisibility(Schema.Node.Reader node)
|
public static TypeVisibility? GetTypeVisibility(Schema.Node.READER node)
|
||||||
{
|
{
|
||||||
foreach (var annotation in node.Annotations)
|
foreach (var annotation in node.Annotations)
|
||||||
{
|
{
|
||||||
if (annotation.Id == AnnotationIds.Cs.TypeVisibility && annotation.Value.IsEnum)
|
if (annotation.Id == AnnotationIds.Cs.TypeVisibility && annotation.Value.which == Schema.Value.WHICH.Enum)
|
||||||
{
|
{
|
||||||
return (TypeVisibility)annotation.Value.Enum;
|
return (TypeVisibility)annotation.Value.Enum;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -83,10 +83,10 @@ test_script:
|
|||||||
vstest.console /logger:Appveyor /inIsolation CapnpC.CSharp.MsBuild.Generation.Tests\bin\Release\netcoreapp3.0\CapnpC.CSharp.MsBuild.Generation.Tests.dll
|
vstest.console /logger:Appveyor /inIsolation CapnpC.CSharp.MsBuild.Generation.Tests\bin\Release\netcoreapp3.0\CapnpC.CSharp.MsBuild.Generation.Tests.dll
|
||||||
msbuild -t:restore ./MsBuildGenerationTest/MsBuildGenerationTest.csproj /p:Configuration="Debug" /p:PackageReferenceVersion="%VERSION%"
|
msbuild -t:restore ./MsBuildGenerationTest/MsBuildGenerationTest.csproj /p:Configuration="Debug" /p:PackageReferenceVersion="%VERSION%"
|
||||||
msbuild ./MsBuildGenerationTest/MsBuildGenerationTest.sln /p:Configuration="Debug" /p:PackageReferenceVersion="%VERSION%"
|
msbuild ./MsBuildGenerationTest/MsBuildGenerationTest.sln /p:Configuration="Debug" /p:PackageReferenceVersion="%VERSION%"
|
||||||
vstest.console /logger:Appveyor /inIsolation Capnp.Net.Runtime.Tests\bin\Debug\net471\Capnp.Net.Runtime.Tests.Std20.dll
|
vstest.console /logger:Appveyor /inIsolation Capnp.Net.Runtime.Tests\bin\Debug\net471\Capnp.Net.Runtime.Tests.dll
|
||||||
vstest.console /logger:Appveyor /inIsolation Capnp.Net.Runtime.Tests\bin\Release\net471\Capnp.Net.Runtime.Tests.Std20.dll
|
vstest.console /logger:Appveyor /inIsolation Capnp.Net.Runtime.Tests\bin\Release\net471\Capnp.Net.Runtime.Tests.dll
|
||||||
vstest.console /logger:Appveyor /inIsolation Capnp.Net.Runtime.Tests\bin\Debug\netcoreapp2.1\Capnp.Net.Runtime.Tests.Core21.dll
|
vstest.console /logger:Appveyor /inIsolation Capnp.Net.Runtime.Tests\bin\Debug\netcoreapp2.1\Capnp.Net.Runtime.Tests.dll
|
||||||
vstest.console /logger:Appveyor /inIsolation Capnp.Net.Runtime.Tests\bin\Release\netcoreapp2.1\Capnp.Net.Runtime.Tests.Core21.dll
|
vstest.console /logger:Appveyor /inIsolation Capnp.Net.Runtime.Tests\bin\Release\netcoreapp2.1\Capnp.Net.Runtime.Tests.dll
|
||||||
powershell -File .\scripts\measure-coverage.ps1
|
powershell -File .\scripts\measure-coverage.ps1
|
||||||
csmacnz.Coveralls --multiple -i "opencover=coverage\cov-Capnp.Net.Runtime.xml;opencover=coverage\cov-CapnpC.CSharp.Generator.xml" --repoToken %COVERALLS_REPO_TOKEN%
|
csmacnz.Coveralls --multiple -i "opencover=coverage\cov-Capnp.Net.Runtime.xml;opencover=coverage\cov-CapnpC.CSharp.Generator.xml" --repoToken %COVERALLS_REPO_TOKEN%
|
||||||
on_finish :
|
on_finish :
|
||||||
|
Loading…
x
Reference in New Issue
Block a user