From 2f21dc217a3de9a3c60f9095f78829c1e03768b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6llner?= Date: Tue, 10 Sep 2019 22:48:25 +0200 Subject: [PATCH] WIP --- Capnp.Net.sln | 12 +- .../CapnpC.CSharp.Generator.Tests.csproj | 21 +- .../CapnpMessageUnitTests.cs | 107 ++ .../CodeGenerator.feature | 48 + .../CodeGenerator.feature.cs | 96 +- .../CodeGeneratorUnitTests.cs | 14 +- .../Embedded Resources/Empty.capnp | 1 + .../Embedded Resources/Empty1.capnp | 1 + .../Embedded Resources}/UnitTest1.capnp | 0 .../Embedded Resources/UnitTest1.capnp.bin | Bin .../Embedded Resources/UnitTest10.capnp.bin | Bin .../Embedded Resources/UnitTest11.capnp.bin | Bin .../Embedded Resources/UnitTest2.capnp.bin | Bin .../Embedded Resources/UnitTest20.capnp.bin | Bin .../Embedded Resources/UnitTest3.capnp.bin | Bin .../Embedded Resources/UnitTest4.capnp.bin | Bin .../Embedded Resources/invalid.capnp | 11 + .../Embedded Resources/null.bin | 0 .../schema-with-offsets.capnp.bin | Bin .../Embedded Resources/test.capnp.bin | Bin .../Embedded Resources/test.cs | 0 .../FeatureSteps/CodeGeneratorSteps.cs | 149 ++ .../No Resources/UnitTest10.capnp | 0 .../No Resources/UnitTest10b.capnp | 0 .../No Resources/UnitTest11.capnp | 0 .../No Resources/UnitTest11b.capnp | 0 .../No Resources/UnitTest2.capnp | 0 .../No Resources/UnitTest20.capnp | 0 .../No Resources/UnitTest3.capnp | 0 .../No Resources/UnitTest4.capnp | 0 .../No Resources/UnitTest4b.capnp | 0 .../No Resources/test.capnp | 0 .../capnpc-csharp.tests.csproj | 4 + .../CapnpC.CSharp.Generator.csproj | 2 +- CapnpC.CSharp.Generator/CapnpCompilation.cs | 73 +- CapnpC.CSharp.Generator/CapnpMessage.cs | 116 ++ .../CapnpProcessFailure.cs | 23 + .../CodeGen/CodeGenerator.cs | 2 +- CapnpC.CSharp.Generator/GenerationResult.cs | 10 + .../BuildEngineMock.cs | 42 + ...npC.CSharp.MsBuild.Generation.Tests.csproj | 21 + .../GenerateCapnpFileCodeBehindTaskTest.cs | 51 + .../TaskItemMock.cs | 37 + .../CsFileGeneratorResult.cs | 51 + .../CapnpCodeBehindGenerator.cs | 82 +- .../CapnpFileCodeBehindGenerator.cs | 54 +- .../Capnpc.Csharp.MsBuild.Generation.csproj | 33 +- .../Capnpc.Csharp.MsBuild.Generation.nuspec | 7 +- .../CodeBehindWriter.cs | 15 +- .../FilePathGenerator.cs | 31 - .../FileSystemHelper.cs | 2 +- .../GenerateCapnpFileCodeBehindTask.cs | 2 +- .../Helper/LogExtensions.cs | 4 +- .../ICapnpCsharpGenerator.cs | 2 +- .../TestFileGeneratorResult.cs | 42 - .../TestGenerationError.cs | 6 - .../TestGeneratorResult.cs | 11 - .../CPS/Buildsystem/Rules/CapnpFileType.xaml | 4 +- .../Capnpc.Csharp.MsBuild.Generation.props | 6 +- .../Capnpc.Csharp.MsBuild.Generation.targets | 10 +- .../Capnpc.Csharp.MsBuild.Generation.tasks | 2 +- .../Capnpc.Csharp.MsBuild.Generation.props | 2 +- README.md | 2 +- appveyor.yml | 5 +- capnpc-csharp.tests/CodeGenerator.feature | 20 - .../FeatureSteps/CodeGeneratorSteps.cs | 83 - capnpc-csharp/Generator/CodeGenerator.cs | 182 -- capnpc-csharp/Generator/CommonSnippetGen.cs | 93 - .../Generator/DomainClassSnippetGen.cs | 972 ---------- capnpc-csharp/Generator/GenNames.cs | 601 ------- capnpc-csharp/Generator/GeneratorOptions.cs | 42 - .../Generator/InterfaceSnippetGen.cs | 844 --------- capnpc-csharp/Generator/Name.cs | 35 - capnpc-csharp/Generator/ReaderSnippetGen.cs | 715 -------- .../Generator/SerializerStateWorder.cs | 12 - capnpc-csharp/Generator/SkeletonWorder.cs | 12 - capnpc-csharp/Generator/SyntaxHelpers.cs | 128 -- capnpc-csharp/Generator/WriterSnippetGen.cs | 406 ----- capnpc-csharp/Model/AbstractType.cs | 45 - capnpc-csharp/Model/Annotation.cs | 23 - capnpc-csharp/Model/Constant.cs | 23 - capnpc-csharp/Model/DefinitionManager.cs | 67 - capnpc-csharp/Model/Enumerant.cs | 14 - capnpc-csharp/Model/Field.cs | 52 - capnpc-csharp/Model/GenFile.cs | 25 - capnpc-csharp/Model/GenericParameter.cs | 26 - capnpc-csharp/Model/HasGenericParameters.cs | 18 - capnpc-csharp/Model/IDefinition.cs | 11 - capnpc-csharp/Model/IHasGenericParameters.cs | 9 - capnpc-csharp/Model/IHasNestedDefinitions.cs | 18 - capnpc-csharp/Model/IdentifierRenamer.cs | 22 - capnpc-csharp/Model/InvalidSchemaException.cs | 11 - capnpc-csharp/Model/Method.cs | 16 - capnpc-csharp/Model/SchemaModel.cs | 783 -------- capnpc-csharp/Model/SpecialName.cs | 9 - capnpc-csharp/Model/Type.cs | 201 --- capnpc-csharp/Model/TypeCategory.cs | 8 - capnpc-csharp/Model/TypeDefinition.cs | 88 - capnpc-csharp/Model/TypeTag.cs | 36 - capnpc-csharp/Model/Types.cs | 56 - capnpc-csharp/Model/Value.cs | 300 ---- capnpc-csharp/Program.cs | 51 +- capnpc-csharp/Schema/SchemaSerialization.cs | 1577 ----------------- .../Schema/schema-with-offsets.capnp | 235 --- capnpc-csharp/capnpc-csharp.csproj | 1 + 105 files changed, 1045 insertions(+), 8039 deletions(-) rename capnpc-csharp.tests/capnpc-csharp.tests.csproj => CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj (74%) create mode 100644 CapnpC.CSharp.Generator.Tests/CapnpMessageUnitTests.cs create mode 100644 CapnpC.CSharp.Generator.Tests/CodeGenerator.feature rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/CodeGenerator.feature.cs (57%) rename capnpc-csharp.tests/UnitTests.cs => CapnpC.CSharp.Generator.Tests/CodeGeneratorUnitTests.cs (92%) create mode 100644 CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty.capnp create mode 100644 CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty1.capnp rename {capnpc-csharp.tests/No Resources => CapnpC.CSharp.Generator.Tests/Embedded Resources}/UnitTest1.capnp (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/Embedded Resources/UnitTest1.capnp.bin (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/Embedded Resources/UnitTest10.capnp.bin (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/Embedded Resources/UnitTest11.capnp.bin (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/Embedded Resources/UnitTest2.capnp.bin (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/Embedded Resources/UnitTest20.capnp.bin (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/Embedded Resources/UnitTest3.capnp.bin (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/Embedded Resources/UnitTest4.capnp.bin (100%) create mode 100644 CapnpC.CSharp.Generator.Tests/Embedded Resources/invalid.capnp rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/Embedded Resources/null.bin (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/Embedded Resources/schema-with-offsets.capnp.bin (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/Embedded Resources/test.capnp.bin (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/Embedded Resources/test.cs (100%) create mode 100644 CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/No Resources/UnitTest10.capnp (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/No Resources/UnitTest10b.capnp (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/No Resources/UnitTest11.capnp (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/No Resources/UnitTest11b.capnp (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/No Resources/UnitTest2.capnp (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/No Resources/UnitTest20.capnp (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/No Resources/UnitTest3.capnp (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/No Resources/UnitTest4.capnp (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/No Resources/UnitTest4b.capnp (100%) rename {capnpc-csharp.tests => CapnpC.CSharp.Generator.Tests}/No Resources/test.capnp (100%) create mode 100644 CapnpC.CSharp.Generator.Tests/capnpc-csharp.tests.csproj create mode 100644 CapnpC.CSharp.Generator/CapnpMessage.cs create mode 100644 CapnpC.CSharp.Generator/CapnpProcessFailure.cs create mode 100644 CapnpC.CSharp.MsBuild.Generation.Tests/BuildEngineMock.cs create mode 100644 CapnpC.CSharp.MsBuild.Generation.Tests/CapnpC.CSharp.MsBuild.Generation.Tests.csproj create mode 100644 CapnpC.CSharp.MsBuild.Generation.Tests/GenerateCapnpFileCodeBehindTaskTest.cs create mode 100644 CapnpC.CSharp.MsBuild.Generation.Tests/TaskItemMock.cs create mode 100644 CapnpC.CSharp.MsBuild.Generation/CsFileGeneratorResult.cs delete mode 100644 Capnpc.Csharp.MsBuild.Generation/FilePathGenerator.cs delete mode 100644 Capnpc.Csharp.MsBuild.Generation/TestFileGeneratorResult.cs delete mode 100644 Capnpc.Csharp.MsBuild.Generation/TestGenerationError.cs delete mode 100644 Capnpc.Csharp.MsBuild.Generation/TestGeneratorResult.cs delete mode 100644 capnpc-csharp.tests/CodeGenerator.feature delete mode 100644 capnpc-csharp.tests/FeatureSteps/CodeGeneratorSteps.cs delete mode 100644 capnpc-csharp/Generator/CodeGenerator.cs delete mode 100644 capnpc-csharp/Generator/CommonSnippetGen.cs delete mode 100644 capnpc-csharp/Generator/DomainClassSnippetGen.cs delete mode 100644 capnpc-csharp/Generator/GenNames.cs delete mode 100644 capnpc-csharp/Generator/GeneratorOptions.cs delete mode 100644 capnpc-csharp/Generator/InterfaceSnippetGen.cs delete mode 100644 capnpc-csharp/Generator/Name.cs delete mode 100644 capnpc-csharp/Generator/ReaderSnippetGen.cs delete mode 100644 capnpc-csharp/Generator/SerializerStateWorder.cs delete mode 100644 capnpc-csharp/Generator/SkeletonWorder.cs delete mode 100644 capnpc-csharp/Generator/SyntaxHelpers.cs delete mode 100644 capnpc-csharp/Generator/WriterSnippetGen.cs delete mode 100644 capnpc-csharp/Model/AbstractType.cs delete mode 100644 capnpc-csharp/Model/Annotation.cs delete mode 100644 capnpc-csharp/Model/Constant.cs delete mode 100644 capnpc-csharp/Model/DefinitionManager.cs delete mode 100644 capnpc-csharp/Model/Enumerant.cs delete mode 100644 capnpc-csharp/Model/Field.cs delete mode 100644 capnpc-csharp/Model/GenFile.cs delete mode 100644 capnpc-csharp/Model/GenericParameter.cs delete mode 100644 capnpc-csharp/Model/HasGenericParameters.cs delete mode 100644 capnpc-csharp/Model/IDefinition.cs delete mode 100644 capnpc-csharp/Model/IHasGenericParameters.cs delete mode 100644 capnpc-csharp/Model/IHasNestedDefinitions.cs delete mode 100644 capnpc-csharp/Model/IdentifierRenamer.cs delete mode 100644 capnpc-csharp/Model/InvalidSchemaException.cs delete mode 100644 capnpc-csharp/Model/Method.cs delete mode 100644 capnpc-csharp/Model/SchemaModel.cs delete mode 100644 capnpc-csharp/Model/SpecialName.cs delete mode 100644 capnpc-csharp/Model/Type.cs delete mode 100644 capnpc-csharp/Model/TypeCategory.cs delete mode 100644 capnpc-csharp/Model/TypeDefinition.cs delete mode 100644 capnpc-csharp/Model/TypeTag.cs delete mode 100644 capnpc-csharp/Model/Types.cs delete mode 100644 capnpc-csharp/Model/Value.cs delete mode 100644 capnpc-csharp/Schema/SchemaSerialization.cs delete mode 100644 capnpc-csharp/Schema/schema-with-offsets.capnp diff --git a/Capnp.Net.sln b/Capnp.Net.sln index 15732e6..38c77ca 100644 --- a/Capnp.Net.sln +++ b/Capnp.Net.sln @@ -11,11 +11,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnp.Net.Runtime.Tests.Std EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnp.Net.Runtime.Tests.Core21", "Capnp.Net.Runtime.Tests.Core21\Capnp.Net.Runtime.Tests.Core21.csproj", "{58E8FFC8-D207-4B0F-842A-58ED9D3D9EEF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "capnpc-csharp.tests", "capnpc-csharp.tests\capnpc-csharp.tests.csproj", "{B77AC567-E232-4072-85C3-8689566BF3D4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CapnpC.CSharp.Generator.Tests", "CapnpC.CSharp.Generator.Tests\CapnpC.CSharp.Generator.Tests.csproj", "{B77AC567-E232-4072-85C3-8689566BF3D4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnpc.Csharp.MsBuild.Generation", "Capnpc.Csharp.MsBuild.Generation\Capnpc.Csharp.MsBuild.Generation.csproj", "{1EFC1F20-C7BB-4F44-8BF9-DBB123AACCF4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CapnpC.CSharp.MsBuild.Generation", "CapnpC.CSharp.MsBuild.Generation\CapnpC.CSharp.MsBuild.Generation.csproj", "{1EFC1F20-C7BB-4F44-8BF9-DBB123AACCF4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CapnpC.CSharp.Generator", "CapnpC.CSharp.Generator\CapnpC.CSharp.Generator.csproj", "{C3A3BB49-356E-4762-A190-76D877BE18F7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CapnpC.CSharp.Generator", "CapnpC.CSharp.Generator\CapnpC.CSharp.Generator.csproj", "{C3A3BB49-356E-4762-A190-76D877BE18F7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CapnpC.CSharp.MsBuild.Generation.Tests", "CapnpC.CSharp.MsBuild.Generation.Tests\CapnpC.CSharp.MsBuild.Generation.Tests.csproj", "{EF05AD68-DE31-448E-B88D-4144F928ED5D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -51,6 +53,10 @@ Global {C3A3BB49-356E-4762-A190-76D877BE18F7}.Debug|Any CPU.Build.0 = Debug|Any CPU {C3A3BB49-356E-4762-A190-76D877BE18F7}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3A3BB49-356E-4762-A190-76D877BE18F7}.Release|Any CPU.Build.0 = Release|Any CPU + {EF05AD68-DE31-448E-B88D-4144F928ED5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF05AD68-DE31-448E-B88D-4144F928ED5D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF05AD68-DE31-448E-B88D-4144F928ED5D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF05AD68-DE31-448E-B88D-4144F928ED5D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/capnpc-csharp.tests/capnpc-csharp.tests.csproj b/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj similarity index 74% rename from capnpc-csharp.tests/capnpc-csharp.tests.csproj rename to CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj index ce9a24e..5228560 100644 --- a/capnpc-csharp.tests/capnpc-csharp.tests.csproj +++ b/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj @@ -2,7 +2,7 @@ netcoreapp2.2 - capnpc_csharp.Tests + CapnpC.CSharp.Generator.Tests false @@ -16,17 +16,18 @@ - - - - + + + - + + + @@ -34,9 +35,13 @@ + + + + @@ -47,6 +52,10 @@ + + + + SpecFlowSingleFileGenerator diff --git a/CapnpC.CSharp.Generator.Tests/CapnpMessageUnitTests.cs b/CapnpC.CSharp.Generator.Tests/CapnpMessageUnitTests.cs new file mode 100644 index 0000000..ce21560 --- /dev/null +++ b/CapnpC.CSharp.Generator.Tests/CapnpMessageUnitTests.cs @@ -0,0 +1,107 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; + +namespace CapnpC.CSharp.Generator.Tests +{ + [TestClass] + public class CapnpMessageUnitTests + { + [TestMethod] + public void ParseError() + { + var msg = new CapnpMessage(@"f:\code\invalid.capnp:5:1: error: Parse error."); + Assert.AreEqual(@"f:\code\invalid.capnp:5:1: error: Parse error.", msg.FullMessage); + Assert.IsTrue(msg.IsParseSuccess); + Assert.AreEqual(@"f:\code\invalid.capnp", msg.FileName); + Assert.AreEqual(5, msg.Line); + Assert.AreEqual(1, msg.Column); + Assert.AreEqual(0, msg.EndColumn); + Assert.AreEqual("error", msg.Category); + Assert.AreEqual("Parse error.", msg.MessageText); + } + + [TestMethod] + public void ColumnSpan() + { + var msg = new CapnpMessage(@"f:\code\invalid.capnp:10:7-8: error: Duplicate ordinal number."); + Assert.IsTrue(msg.IsParseSuccess); + Assert.AreEqual(@"f:\code\invalid.capnp", msg.FileName); + Assert.AreEqual(10, msg.Line); + Assert.AreEqual(7, msg.Column); + Assert.AreEqual(8, msg.EndColumn); + Assert.AreEqual("error", msg.Category); + Assert.AreEqual("Duplicate ordinal number.", msg.MessageText); + } + + [TestMethod] + public void NoSuchFile() + { + var msg = new CapnpMessage(@"C:\ProgramData\chocolatey\lib\capnproto\tools\capnproto-tools-win32-0.7.0\capnp.exe compile: doesnotexist.capnp: no such file"); + Assert.IsFalse(msg.IsParseSuccess); + Assert.AreEqual(@"C:\ProgramData\chocolatey\lib\capnproto\tools\capnproto-tools-win32-0.7.0\capnp.exe compile: doesnotexist.capnp: no such file", msg.FullMessage); + } + + [TestMethod] + public void NoId() + { + var msg = new CapnpMessage(@"empty.capnp:1:1: error: File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;"); + Assert.IsTrue(msg.IsParseSuccess); + Assert.AreEqual("empty.capnp", msg.FileName); + Assert.AreEqual(1, msg.Line); + Assert.AreEqual(1, msg.Column); + Assert.AreEqual("error", msg.Category); + Assert.AreEqual("File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;", msg.MessageText); + } + + [TestMethod] + public void AnnoyingNTFSAlternateDataStream1() + { + var msg = new CapnpMessage(@"3:2:1:1: error: File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;"); + Assert.IsTrue(msg.IsParseSuccess); + Assert.AreEqual("3:2", msg.FileName); + Assert.AreEqual(1, msg.Line); + Assert.AreEqual(1, msg.Column); + Assert.AreEqual("error", msg.Category); + Assert.AreEqual("File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;", msg.MessageText); + } + + [TestMethod] + public void AnnoyingNTFSAlternateDataStream2() + { + var msg = new CapnpMessage(@"c:\3:2:1:1: error: File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;"); + Assert.IsTrue(msg.IsParseSuccess); + Assert.AreEqual(@"c:\3:2", msg.FileName); + Assert.AreEqual(1, msg.Line); + Assert.AreEqual(1, msg.Column); + Assert.AreEqual("error", msg.Category); + Assert.AreEqual("File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;", msg.MessageText); + } + + [TestMethod] + public void AnnoyingNTFSAlternateDataStream3() + { + var msg = new CapnpMessage(@"\\?\c:\3:2:1:1: error: File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;"); + Assert.IsTrue(msg.IsParseSuccess); + Assert.AreEqual(@"\\?\c:\3:2", msg.FileName); + Assert.AreEqual(1, msg.Line); + Assert.AreEqual(1, msg.Column); + Assert.AreEqual("error", msg.Category); + Assert.AreEqual("File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;", msg.MessageText); + } + + [TestMethod] + public void AnnoyingNTFSAlternateDataStream4() + { + var msg = new CapnpMessage(@"1:2-3:10:7-8: error: Duplicate ordinal number."); + Assert.IsTrue(msg.IsParseSuccess); + Assert.AreEqual(@"1:2-3", msg.FileName); + Assert.AreEqual(10, msg.Line); + Assert.AreEqual(7, msg.Column); + Assert.AreEqual(8, msg.EndColumn); + Assert.AreEqual("error", msg.Category); + Assert.AreEqual("Duplicate ordinal number.", msg.MessageText); + } + } +} diff --git a/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature new file mode 100644 index 0000000..239fd3d --- /dev/null +++ b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature @@ -0,0 +1,48 @@ +Feature: CodeGenerator + In order to ensure that the generator backend produces valid output + As a contributor + I want to get notified when there is any deviation from reference output + +Scenario: Comparing backend output with reference + Given I have a binary code generator request "test.capnp.bin" + And my reference output is "test.cs" + When I invoke capnpc-csharp + Then the generated output must match the reference + +Scenario Outline: Invalid binary code generator requests + Given I have a binary code generator request + When I invoke capnpc-csharp + Then the invocation must fail + +Examples: + | bin | + | null.bin | + | test.cs | + +Scenario: Combining frontend and backend + Given capnp.exe is installed on my system + And I have a schema "UnitTest1.capnp" + When I try to generate code from that schema + Then code generation must succeed + +Scenario: Missing frontend + Given capnp.exe is not installed on my system + And I have a schema "UnitTest1.capnp" + When I try to generate code from that schema + Then the invocation must fail + +Scenario: Schema without ID + Given capnp.exe is installed on my system + And I have a schema "Empty1.capnp" + When I try to generate code from that schema + Then the invocation must fail + And the reason must be bad input + And the error output must contain "File does not declare an ID" + +Scenario: Multiple errors + Given capnp.exe is installed on my system + And I have a schema "invalid.capnp" + When I try to generate code from that schema + Then the invocation must fail + And the reason must be bad input + And the error output must contain multiple messages diff --git a/capnpc-csharp.tests/CodeGenerator.feature.cs b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs similarity index 57% rename from capnpc-csharp.tests/CodeGenerator.feature.cs rename to CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs index 74bf043..c01b9e3 100644 --- a/capnpc-csharp.tests/CodeGenerator.feature.cs +++ b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs @@ -10,7 +10,7 @@ // ------------------------------------------------------------------------------ #region Designer generated code #pragma warning disable -namespace capnpc_csharp.Tests +namespace CapnpC.CSharp.Generator.Tests { using TechTalk.SpecFlow; @@ -63,7 +63,7 @@ namespace capnpc_csharp.Tests if (((testRunner.FeatureContext != null) && (testRunner.FeatureContext.FeatureInfo.Title != "CodeGenerator"))) { - global::capnpc_csharp.Tests.CodeGeneratorFeature.FeatureSetup(null); + global::CapnpC.CSharp.Generator.Tests.CodeGeneratorFeature.FeatureSetup(null); } } @@ -149,6 +149,98 @@ this.InvalidBinaryCodeGeneratorRequests("null.bin", ((string[])(null))); this.InvalidBinaryCodeGeneratorRequests("test.cs", ((string[])(null))); #line hidden } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Combining frontend and backend")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] + public virtual void CombiningFrontendAndBackend() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Combining frontend and backend", null, ((string[])(null))); +#line 22 +this.ScenarioInitialize(scenarioInfo); + this.ScenarioStart(); +#line 23 + testRunner.Given("capnp.exe is installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line 24 + testRunner.And("I have a schema \"UnitTest1.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line 25 + testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line 26 + testRunner.Then("code generation must succeed", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + this.ScenarioCleanup(); + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Missing frontend")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] + public virtual void MissingFrontend() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Missing frontend", null, ((string[])(null))); +#line 28 +this.ScenarioInitialize(scenarioInfo); + this.ScenarioStart(); +#line 29 + testRunner.Given("capnp.exe is not installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line 30 + testRunner.And("I have a schema \"UnitTest1.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line 31 + testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line 32 + testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + this.ScenarioCleanup(); + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Schema without ID")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] + public virtual void SchemaWithoutID() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Schema without ID", null, ((string[])(null))); +#line 34 +this.ScenarioInitialize(scenarioInfo); + this.ScenarioStart(); +#line 35 + testRunner.Given("capnp.exe is installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line 36 + testRunner.And("I have a schema \"Empty1.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line 37 + testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line 38 + testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line 39 + testRunner.And("the reason must be bad input", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line 40 + testRunner.And("the error output must contain \"File does not declare an ID\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden + this.ScenarioCleanup(); + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Multiple errors")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] + public virtual void MultipleErrors() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Multiple errors", null, ((string[])(null))); +#line 42 +this.ScenarioInitialize(scenarioInfo); + this.ScenarioStart(); +#line 43 + testRunner.Given("capnp.exe is installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line 44 + testRunner.And("I have a schema \"invalid.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line 45 + testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line 46 + testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line 47 + testRunner.And("the reason must be bad input", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line 48 + testRunner.And("the error output must contain multiple messages", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden + this.ScenarioCleanup(); + } } } #pragma warning restore diff --git a/capnpc-csharp.tests/UnitTests.cs b/CapnpC.CSharp.Generator.Tests/CodeGeneratorUnitTests.cs similarity index 92% rename from capnpc-csharp.tests/UnitTests.cs rename to CapnpC.CSharp.Generator.Tests/CodeGeneratorUnitTests.cs index e2b80d5..bfec1b7 100644 --- a/capnpc-csharp.tests/UnitTests.cs +++ b/CapnpC.CSharp.Generator.Tests/CodeGeneratorUnitTests.cs @@ -1,13 +1,13 @@ using Capnp; -using Model = CapnpC.Model; -using Generator = CapnpC.Generator; -using CodeGeneratorRequest = CapnpC.Schema.CodeGeneratorRequest; +using Model = CapnpC.CSharp.Generator.Model; +using CodeGen = CapnpC.CSharp.Generator.CodeGen; +using CodeGeneratorRequest = CapnpC.CSharp.Generator.Schema.CodeGeneratorRequest; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; using System.Linq; -namespace capnpc_csharp.Tests +namespace CapnpC.CSharp.Generator.Tests { [TestClass] public class CodeGeneratorUnitTests @@ -98,13 +98,13 @@ namespace capnpc_csharp.Tests struct Run { public Model.SchemaModel Model; - public Generator.CodeGenerator CodeGen; + public CodeGen.CodeGenerator CodeGen; public Model.GenFile FirstFile; public string Code; } - static Generator.CodeGenerator NewGeneratorFor(Model.SchemaModel model) - => new Generator.CodeGenerator(model, new Generator.GeneratorOptions()); + static CodeGen.CodeGenerator NewGeneratorFor(Model.SchemaModel model) + => new CodeGen.CodeGenerator(model, new CodeGen.GeneratorOptions()); Run LoadAndGenerate(string inputName, int? testNum = null) { diff --git a/CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty.capnp b/CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty.capnp new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty.capnp @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty1.capnp b/CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty1.capnp new file mode 100644 index 0000000..e02abfc --- /dev/null +++ b/CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty1.capnp @@ -0,0 +1 @@ + diff --git a/capnpc-csharp.tests/No Resources/UnitTest1.capnp b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest1.capnp similarity index 100% rename from capnpc-csharp.tests/No Resources/UnitTest1.capnp rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest1.capnp diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest1.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest1.capnp.bin similarity index 100% rename from capnpc-csharp.tests/Embedded Resources/UnitTest1.capnp.bin rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest1.capnp.bin diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest10.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest10.capnp.bin similarity index 100% rename from capnpc-csharp.tests/Embedded Resources/UnitTest10.capnp.bin rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest10.capnp.bin diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest11.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest11.capnp.bin similarity index 100% rename from capnpc-csharp.tests/Embedded Resources/UnitTest11.capnp.bin rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest11.capnp.bin diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest2.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest2.capnp.bin similarity index 100% rename from capnpc-csharp.tests/Embedded Resources/UnitTest2.capnp.bin rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest2.capnp.bin diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest20.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest20.capnp.bin similarity index 100% rename from capnpc-csharp.tests/Embedded Resources/UnitTest20.capnp.bin rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest20.capnp.bin diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest3.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest3.capnp.bin similarity index 100% rename from capnpc-csharp.tests/Embedded Resources/UnitTest3.capnp.bin rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest3.capnp.bin diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest4.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest4.capnp.bin similarity index 100% rename from capnpc-csharp.tests/Embedded Resources/UnitTest4.capnp.bin rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest4.capnp.bin diff --git a/CapnpC.CSharp.Generator.Tests/Embedded Resources/invalid.capnp b/CapnpC.CSharp.Generator.Tests/Embedded Resources/invalid.capnp new file mode 100644 index 0000000..b56b978 --- /dev/null +++ b/CapnpC.CSharp.Generator.Tests/Embedded Resources/invalid.capnp @@ -0,0 +1,11 @@ +@0xa5ac546b7bf6fbbc + +enum Enumerant { + byte @0; + bit @1; +} + +struct Foo { + foo @0: UInt8; + bar @0: UInt8; +} diff --git a/capnpc-csharp.tests/Embedded Resources/null.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/null.bin similarity index 100% rename from capnpc-csharp.tests/Embedded Resources/null.bin rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/null.bin diff --git a/capnpc-csharp.tests/Embedded Resources/schema-with-offsets.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/schema-with-offsets.capnp.bin similarity index 100% rename from capnpc-csharp.tests/Embedded Resources/schema-with-offsets.capnp.bin rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/schema-with-offsets.capnp.bin diff --git a/capnpc-csharp.tests/Embedded Resources/test.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/test.capnp.bin similarity index 100% rename from capnpc-csharp.tests/Embedded Resources/test.capnp.bin rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/test.capnp.bin diff --git a/capnpc-csharp.tests/Embedded Resources/test.cs b/CapnpC.CSharp.Generator.Tests/Embedded Resources/test.cs similarity index 100% rename from capnpc-csharp.tests/Embedded Resources/test.cs rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/test.cs diff --git a/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs b/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs new file mode 100644 index 0000000..83fc17a --- /dev/null +++ b/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs @@ -0,0 +1,149 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using TechTalk.SpecFlow; + +namespace CapnpC.CSharp.Generator.Tests +{ + [Binding] + public class CodeGeneratorSteps + { + Stream _inputStream; + string _inputSchemaFileName; + string _inputSchema; + string _referenceOutputContent; + + GenerationResult _result; + + public static Stream LoadResource(string name) + { + var assembly = Assembly.GetExecutingAssembly(); + string[] names = assembly.GetManifestResourceNames(); + string urn = Array.Find(names, n => n.EndsWith(name, StringComparison.OrdinalIgnoreCase)); + Assert.IsNotNull(urn, $"Test specification error: {name} does not exist"); + return assembly.GetManifestResourceStream(urn); + } + + internal static bool IsCapnpExeInstalled() + { + using (var process = Process.Start("where", "capnp.exe")) + { + if (process == null) + Assert.Fail("Unable to start 'where'"); + + process.WaitForExit(); + + return process.ExitCode == 0; + } + } + + [Given(@"I have a binary code generator request ""(.*)""")] + [Given(@"I have a binary code generator request (.*)")] + public void GivenIHaveABinaryCodeGeneratorRequest(string binaryRequestFileName) + { + _inputStream = LoadResource(binaryRequestFileName); + } + + [Given(@"my reference output is ""(.*)""")] + public void GivenMyReferenceOutputIs(string expectedOutputFileName) + { + using (var stream = LoadResource(expectedOutputFileName)) + using (var reader = new StreamReader(stream)) + { + _referenceOutputContent = reader.ReadToEnd(); + } + } + + [When(@"I invoke capnpc-csharp")] + public void WhenIInvokeCapnpc_Csharp() + { + using (_inputStream) + { + _result = CapnpCompilation.GenerateFromStream(_inputStream); + } + } + + [Then(@"the generated output must match the reference")] + public void ThenTheGeneratedOutputMustMatchTheReference() + { + Assert.IsTrue(_result.IsSuccess, $"Tool invocation failed: {_result.Exception?.Message}"); + Assert.AreEqual(_referenceOutputContent, _result.GeneratedFiles.Single().GeneratedContent); + } + + [Then(@"the invocation must fail")] + public void ThenTheInvocationMustFail() + { + Assert.IsFalse(_result.IsSuccess, "Tool invocation was supposed to fail, but it didn't"); + Assert.IsNotNull(_result.Exception, "Expected an exception"); + } + + [Given(@"capnp\.exe is installed on my system")] + public void GivenCapnp_ExeIsInstalledOnMySystem() + { + if (!IsCapnpExeInstalled()) + { + Assert.Inconclusive("capnp.exe not found. Precondition of this test is not met."); + } + } + + [Given(@"I have a schema ""(.*)""")] + public void GivenIHaveASchema(string capnpFileName) + { + _inputSchemaFileName = capnpFileName; + + using (var stream = LoadResource(capnpFileName)) + using (var reader = new StreamReader(stream)) + { + _inputSchema = reader.ReadToEnd(); + } + } + + [When(@"I try to generate code from that schema")] + public void WhenIWantToGenerateCodeFromThatSchema() + { + string path = Path.Combine(Path.GetTempPath(), _inputSchemaFileName); + File.WriteAllText(path, _inputSchema); + _result = CapnpCompilation.InvokeCapnpAndGenerate(new string[] { path }); + } + + [Then(@"code generation must succeed")] + public void ThenCodeGenerationMustSucceed() + { + Assert.IsNotNull(_result, "expected generation result"); + Assert.IsTrue(_result.IsSuccess, $"Tool invocation failed: {_result.Exception?.Message}"); + Assert.IsTrue(_result.GeneratedFiles.Count == 1, "Expected exactly one file"); + Assert.IsTrue(_result.GeneratedFiles[0].IsSuccess, $"Code generation failed: {_result.GeneratedFiles[0].Exception?.Message}"); + Assert.IsFalse(string.IsNullOrEmpty(_result.GeneratedFiles[0].GeneratedContent), "Expected non-empty generated content"); + } + + [Given(@"capnp\.exe is not installed on my system")] + public void GivenCapnp_ExeIsNotInstalledOnMySystem() + { + if (IsCapnpExeInstalled()) + { + Assert.Inconclusive("capnp.exe found. Precondition of this test is not met."); + } + } + + [Then(@"the reason must be bad input")] + public void ThenTheReasonMustBeBadInput() + { + Assert.IsTrue(_result.ErrorCategory == CapnpProcessFailure.BadInput); + } + + [Then(@"the error output must contain ""(.*)""")] + public void ThenTheErrorOutputMustContain(string p0) + { + Assert.IsTrue(_result.Messages.Any(m => m.FullMessage.Contains(p0))); + } + + [Then(@"the error output must contain multiple messages")] + public void ThenTheErrorOutputMustContainMultipleMessages() + { + Assert.IsTrue(_result.Messages.Count >= 2); + } + } +} diff --git a/capnpc-csharp.tests/No Resources/UnitTest10.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest10.capnp similarity index 100% rename from capnpc-csharp.tests/No Resources/UnitTest10.capnp rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest10.capnp diff --git a/capnpc-csharp.tests/No Resources/UnitTest10b.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest10b.capnp similarity index 100% rename from capnpc-csharp.tests/No Resources/UnitTest10b.capnp rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest10b.capnp diff --git a/capnpc-csharp.tests/No Resources/UnitTest11.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest11.capnp similarity index 100% rename from capnpc-csharp.tests/No Resources/UnitTest11.capnp rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest11.capnp diff --git a/capnpc-csharp.tests/No Resources/UnitTest11b.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest11b.capnp similarity index 100% rename from capnpc-csharp.tests/No Resources/UnitTest11b.capnp rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest11b.capnp diff --git a/capnpc-csharp.tests/No Resources/UnitTest2.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest2.capnp similarity index 100% rename from capnpc-csharp.tests/No Resources/UnitTest2.capnp rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest2.capnp diff --git a/capnpc-csharp.tests/No Resources/UnitTest20.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest20.capnp similarity index 100% rename from capnpc-csharp.tests/No Resources/UnitTest20.capnp rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest20.capnp diff --git a/capnpc-csharp.tests/No Resources/UnitTest3.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest3.capnp similarity index 100% rename from capnpc-csharp.tests/No Resources/UnitTest3.capnp rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest3.capnp diff --git a/capnpc-csharp.tests/No Resources/UnitTest4.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest4.capnp similarity index 100% rename from capnpc-csharp.tests/No Resources/UnitTest4.capnp rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest4.capnp diff --git a/capnpc-csharp.tests/No Resources/UnitTest4b.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest4b.capnp similarity index 100% rename from capnpc-csharp.tests/No Resources/UnitTest4b.capnp rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest4b.capnp diff --git a/capnpc-csharp.tests/No Resources/test.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/test.capnp similarity index 100% rename from capnpc-csharp.tests/No Resources/test.capnp rename to CapnpC.CSharp.Generator.Tests/No Resources/test.capnp diff --git a/CapnpC.CSharp.Generator.Tests/capnpc-csharp.tests.csproj b/CapnpC.CSharp.Generator.Tests/capnpc-csharp.tests.csproj new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/CapnpC.CSharp.Generator.Tests/capnpc-csharp.tests.csproj @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/CapnpC.CSharp.Generator/CapnpC.CSharp.Generator.csproj b/CapnpC.CSharp.Generator/CapnpC.CSharp.Generator.csproj index 53233fd..377d454 100644 --- a/CapnpC.CSharp.Generator/CapnpC.CSharp.Generator.csproj +++ b/CapnpC.CSharp.Generator/CapnpC.CSharp.Generator.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + netstandard2.0;netcoreapp2.1 diff --git a/CapnpC.CSharp.Generator/CapnpCompilation.cs b/CapnpC.CSharp.Generator/CapnpCompilation.cs index 9f1a0a4..ec4c342 100644 --- a/CapnpC.CSharp.Generator/CapnpCompilation.cs +++ b/CapnpC.CSharp.Generator/CapnpCompilation.cs @@ -1,7 +1,12 @@ using Capnp; using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Runtime.CompilerServices; +using System.Text.RegularExpressions; + +[assembly: InternalsVisibleTo("CapnpC.CSharp.Generator.Tests")] namespace CapnpC.CSharp.Generator { @@ -23,13 +28,7 @@ namespace CapnpC.CSharp.Generator try { - WireFrame segments; - - using (input) - { - segments = Framing.ReadSegments(input); - } - + var segments = Framing.ReadSegments(input); var dec = DeserializerState.CreateRoot(segments); var reader = Schema.CodeGeneratorRequest.Reader.Create(dec); var model = Model.SchemaModel.Create(reader); @@ -42,8 +41,66 @@ namespace CapnpC.CSharp.Generator } } - public static GenerationResult InvokeCapnpcAndGenerate() + /// + /// Invokes "capnp.exe -o-" with given additional arguments and redirects the output to the C# generator backend. + /// + /// additional command line arguments + /// generation result + /// is null + public static GenerationResult InvokeCapnpAndGenerate(IEnumerable arguments) { + if (arguments == null) + throw new ArgumentNullException(nameof(arguments)); + + using (var compiler = new Process()) + { + var argList = new List(); + argList.Add("compile"); + argList.Add($"-o-"); + argList.AddRange(arguments); + + compiler.StartInfo.FileName = "capnp.exe"; + compiler.StartInfo.Arguments = string.Join(" ", argList); + compiler.StartInfo.UseShellExecute = false; + compiler.StartInfo.RedirectStandardOutput = true; + compiler.StartInfo.RedirectStandardError = true; + + try + { + compiler.Start(); + } + catch (Exception exception) + { + return new GenerationResult(exception) + { + ErrorCategory = CapnpProcessFailure.NotFound + }; + } + + var result = GenerateFromStream(compiler.StandardOutput.BaseStream); + + var messageList = new List(); + + while (!compiler.StandardError.EndOfStream) + { + messageList.Add(new CapnpMessage(compiler.StandardError.ReadLine())); + } + + result.Messages = messageList; + + if (!result.IsSuccess) + { + compiler.WaitForExit(); + int exitCode = compiler.ExitCode; + + if (exitCode == 0) + result.ErrorCategory = CapnpProcessFailure.BadOutput; + else + result.ErrorCategory = CapnpProcessFailure.BadInput; + } + + return result; + } } } } diff --git a/CapnpC.CSharp.Generator/CapnpMessage.cs b/CapnpC.CSharp.Generator/CapnpMessage.cs new file mode 100644 index 0000000..0cc60b8 --- /dev/null +++ b/CapnpC.CSharp.Generator/CapnpMessage.cs @@ -0,0 +1,116 @@ +using System.Runtime.CompilerServices; +using System.Text.RegularExpressions; + +[assembly: InternalsVisibleTo("CapnpC.CSharp.Generator.Tests")] + +namespace CapnpC.CSharp.Generator +{ + /// + /// Represents a capnp.exe output message + /// + public class CapnpMessage + { + // capnp outputs look like this: + // empty.capnp:1:1: error: File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d; + // f:\code\invalid.capnp:9:7-8: error: Ordinal @0 originally used here. + // Parsing them is harder than it seems because the colon may be part of the file name (as in the example above). + // And it becomes even worse! NTFS has a rarely used feature called "alternate data streams", identified by a colon: + // f:\code\somefile:stream.capnp:9:7-8: error: Ordinal @0 originally used here. + // What about a name which looks like a line number? (Hint: the 10 denotes the alternate data stream) + // f:\code\somefile:10:9:7-8: error: Ordinal @0 originally used here. + // Watching for the *last* colon as message separator does not work either, either. See first example. + // Strategy: Watch out for the *last* occurence of pattern :[line]:[column] + + static readonly Regex LineColumnRegex = new Regex(@":(?\d+):(?\d+)(-(?\d+))?:", RegexOptions.Compiled | RegexOptions.RightToLeft); + + /// + /// Constructs an instance from given message + /// + /// output message (one line) + public CapnpMessage(string fullMessage) + { + FullMessage = fullMessage; + + var match = LineColumnRegex.Match(fullMessage); + + if (match.Success) + { + IsParseSuccess = true; + FileName = fullMessage.Substring(0, match.Index); + var lineMatch = match.Groups["Line"]; + if (lineMatch.Success) + { + int.TryParse(lineMatch.Value, out int value); + Line = value; + } + var columnMatch = match.Groups["Column"]; + if (columnMatch.Success) + { + int.TryParse(columnMatch.Value, out int value); + Column = value; + } + var endColumnMatch = match.Groups["EndColumn"]; + if (endColumnMatch.Success) + { + int.TryParse(endColumnMatch.Value, out int value); + EndColumn = value; + } + + int restIndex = match.Index + match.Length; + int bodyIndex = fullMessage.IndexOf(':', restIndex); + + if (bodyIndex >= 0) + { + Category = fullMessage.Substring(restIndex, bodyIndex - restIndex).Trim(); + MessageText = fullMessage.Substring(bodyIndex + 1).Trim(); + } + else + { + // Never observed "in the wild", just in case... + Category = string.Empty; + MessageText = fullMessage.Substring(restIndex).Trim(); + } + } + } + + /// + /// The original message + /// + public string FullMessage { get; } + + /// + /// Whether the message could be decompsed into [filename]:[line]:[column]: [category]: [text] + /// + public bool IsParseSuccess { get; } + + /// + /// Parsed file name (null iff not IsParseSuccess) + /// + public string FileName { get; } + + /// + /// Parsed line (0 if not IsParseSuccess) + /// + public int Line { get; } + + /// + /// Parsed column (0 if not IsParseSuccess) + /// + public int Column { get; } + + /// + /// Parsed end column (0 if there is none) + /// + public int EndColumn { get; } + + /// + /// Parsed category (e.g. "error", null iff not IsParseSuccess) + /// + public string Category { get; } + + /// + /// Parsed message body text (0 if not IsParseSuccess) + /// + public string MessageText { get; } + } +} diff --git a/CapnpC.CSharp.Generator/CapnpProcessFailure.cs b/CapnpC.CSharp.Generator/CapnpProcessFailure.cs new file mode 100644 index 0000000..1d51c0f --- /dev/null +++ b/CapnpC.CSharp.Generator/CapnpProcessFailure.cs @@ -0,0 +1,23 @@ +namespace CapnpC.CSharp.Generator +{ + /// + /// Why did invocation of capnpc.exe fail? + /// + public enum CapnpProcessFailure + { + /// + /// Because capnpc.exe was not found. It is probably not installed. + /// + NotFound, + + /// + /// Because it exited with an error. Probably invalid .capnp file input. + /// + BadInput, + + /// + /// Because it produced an apparently bad code generation request. + /// + BadOutput + } +} diff --git a/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs b/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs index c983ccc..d873108 100644 --- a/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs +++ b/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs @@ -11,7 +11,7 @@ using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; using static SyntaxHelpers; - class CodeGenerator + internal class CodeGenerator { readonly SchemaModel _model; readonly GenNames _names; diff --git a/CapnpC.CSharp.Generator/GenerationResult.cs b/CapnpC.CSharp.Generator/GenerationResult.cs index 3f40fc5..672759a 100644 --- a/CapnpC.CSharp.Generator/GenerationResult.cs +++ b/CapnpC.CSharp.Generator/GenerationResult.cs @@ -40,5 +40,15 @@ namespace CapnpC.CSharp.Generator /// true iff generation was successful /// public bool IsSuccess => GeneratedFiles != null; + + /// + /// Messages read from standard error. Valid for both failure and success (capnp might spit out some warnings). + /// + public IReadOnlyList Messages { get; internal set; } + + /// + /// Error classification (if any error) + /// + public CapnpProcessFailure ErrorCategory { get; internal set; } } } diff --git a/CapnpC.CSharp.MsBuild.Generation.Tests/BuildEngineMock.cs b/CapnpC.CSharp.MsBuild.Generation.Tests/BuildEngineMock.cs new file mode 100644 index 0000000..f5afe60 --- /dev/null +++ b/CapnpC.CSharp.MsBuild.Generation.Tests/BuildEngineMock.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections; +using Microsoft.Build.Framework; + +namespace CapnpC.CSharp.MsBuild.Generation.Tests +{ + class BuildEngineMock : IBuildEngine + { + public bool ContinueOnError => true; + + public int LineNumberOfTaskNode => 0; + + public int ColumnNumberOfTaskNode => 0; + + public string ProjectFileOfTaskNode => null; + + public bool BuildProjectFile(string projectFileName, string[] targetNames, IDictionary globalProperties, IDictionary targetOutputs) + { + return true; + } + + public void LogCustomEvent(CustomBuildEventArgs e) + { + Console.WriteLine(e.Message); + } + + public void LogErrorEvent(BuildErrorEventArgs e) + { + Console.WriteLine(e.Message); + } + + public void LogMessageEvent(BuildMessageEventArgs e) + { + Console.WriteLine(e.Message); + } + + public void LogWarningEvent(BuildWarningEventArgs e) + { + Console.WriteLine(e.Message); + } + } +} diff --git a/CapnpC.CSharp.MsBuild.Generation.Tests/CapnpC.CSharp.MsBuild.Generation.Tests.csproj b/CapnpC.CSharp.MsBuild.Generation.Tests/CapnpC.CSharp.MsBuild.Generation.Tests.csproj new file mode 100644 index 0000000..fe274f1 --- /dev/null +++ b/CapnpC.CSharp.MsBuild.Generation.Tests/CapnpC.CSharp.MsBuild.Generation.Tests.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + + + + + + + diff --git a/CapnpC.CSharp.MsBuild.Generation.Tests/GenerateCapnpFileCodeBehindTaskTest.cs b/CapnpC.CSharp.MsBuild.Generation.Tests/GenerateCapnpFileCodeBehindTaskTest.cs new file mode 100644 index 0000000..b6a7c6b --- /dev/null +++ b/CapnpC.CSharp.MsBuild.Generation.Tests/GenerateCapnpFileCodeBehindTaskTest.cs @@ -0,0 +1,51 @@ +using CapnpC.CSharp.Generator.Tests; +using Microsoft.Build.Framework; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.IO; + +namespace CapnpC.CSharp.MsBuild.Generation.Tests +{ + [TestClass] + public class GenerateCapnpFileCodeBehindTaskTest + { + string LoadResourceContent(string name) + { + using (var stream = CodeGeneratorSteps.LoadResource("UnitTest1.capnp")) + using (var reader = new StreamReader(stream)) + { + return reader.ReadToEnd(); + } + } + + [TestMethod] + public void ExecutionWithoutParameters() + { + var task = new GenerateCapnpFileCodeBehindTask(); + task.BuildEngine = new BuildEngineMock(); + task.Execute(); + // Should not crash. Should Execute() return true or false if there is no input? + } + + [TestMethod] + public void SimpleGeneration() + { + string capnpFile = "UnitTask1.capnp"; + string content = LoadResourceContent(capnpFile); + string tmpPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(tmpPath); + string capnpPath = Path.Combine(tmpPath, capnpFile); + File.WriteAllText(capnpPath, content); + + var task = new GenerateCapnpFileCodeBehindTask(); + task.BuildEngine = new BuildEngineMock(); + task.ProjectPath = Path.Combine(tmpPath, "doesnotneedtoexist.csproj"); + task.CapnpFiles = new ITaskItem[1] { new TaskItemMock() { ItemSpec = capnpPath } }; + Assert.IsTrue(task.Execute()); + Assert.IsNotNull(task.GeneratedFiles); + Assert.AreEqual(1, task.GeneratedFiles.Length); + string csPath = Path.Combine(tmpPath, task.GeneratedFiles[0].ItemSpec); + Assert.AreEqual(capnpPath + ".cs", csPath); + Assert.IsTrue(File.Exists(csPath)); + } + } +} diff --git a/CapnpC.CSharp.MsBuild.Generation.Tests/TaskItemMock.cs b/CapnpC.CSharp.MsBuild.Generation.Tests/TaskItemMock.cs new file mode 100644 index 0000000..6cf0f5a --- /dev/null +++ b/CapnpC.CSharp.MsBuild.Generation.Tests/TaskItemMock.cs @@ -0,0 +1,37 @@ +using System.Collections; +using Microsoft.Build.Framework; + +namespace CapnpC.CSharp.MsBuild.Generation.Tests +{ + + class TaskItemMock : ITaskItem + { + public string ItemSpec { get; set; } + + public ICollection MetadataNames => null; + + public int MetadataCount => 0; + + public IDictionary CloneCustomMetadata() + { + return null; + } + + public void CopyMetadataTo(ITaskItem destinationItem) + { + } + + public string GetMetadata(string metadataName) + { + return null; + } + + public void RemoveMetadata(string metadataName) + { + } + + public void SetMetadata(string metadataName, string metadataValue) + { + } + } +} diff --git a/CapnpC.CSharp.MsBuild.Generation/CsFileGeneratorResult.cs b/CapnpC.CSharp.MsBuild.Generation/CsFileGeneratorResult.cs new file mode 100644 index 0000000..75961ac --- /dev/null +++ b/CapnpC.CSharp.MsBuild.Generation/CsFileGeneratorResult.cs @@ -0,0 +1,51 @@ +using CapnpC.CSharp.Generator; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace CapnpC.CSharp.MsBuild.Generation +{ + public class CsFileGeneratorResult + { + public CsFileGeneratorResult(FileGenerationResult generatorResult, string fileName, IReadOnlyList messages) + { + if (generatorResult == null) + { + throw new ArgumentNullException(nameof(generatorResult)); + } + + Filename = fileName ?? throw new ArgumentNullException(nameof(fileName)); + + Error = generatorResult.Exception?.Message; + GeneratedCode = generatorResult.GeneratedContent; + Messages = messages; + } + + public CsFileGeneratorResult(string error) + { + Error = error; + } + + public CsFileGeneratorResult(string error, IReadOnlyList messages) + { + Error = error; + Messages = messages; + } + + /// + /// The error, if any. + /// + public string Error { get; } + + /// + /// The generated code. + /// + public string GeneratedCode { get; } + + public IReadOnlyList Messages { get; } + + public bool Success => Error == null; + + public string Filename { get; } + } +} \ No newline at end of file diff --git a/Capnpc.Csharp.MsBuild.Generation/CapnpCodeBehindGenerator.cs b/Capnpc.Csharp.MsBuild.Generation/CapnpCodeBehindGenerator.cs index 97ab0ba..71c0592 100644 --- a/Capnpc.Csharp.MsBuild.Generation/CapnpCodeBehindGenerator.cs +++ b/Capnpc.Csharp.MsBuild.Generation/CapnpCodeBehindGenerator.cs @@ -1,41 +1,85 @@ -using System; +using CapnpC.CSharp.Generator; +using System; using System.Collections.Generic; using System.IO; -namespace Capnpc.Csharp.MsBuild.Generation +namespace CapnpC.CSharp.MsBuild.Generation { public class CapnpCodeBehindGenerator : IDisposable { - //private SpecFlowProject _specFlowProject; - //private ITestGenerator _testGenerator; public void InitializeProject(string projectPath) { - //_specFlowProject = MsBuildProjectReader.LoadSpecFlowProjectFromMsBuild(Path.GetFullPath(projectPath), rootNamespace); - - //var projectSettings = _specFlowProject.ProjectSettings; - - //var testGeneratorFactory = new TestGeneratorFactory(); - - //_testGenerator = testGeneratorFactory.CreateGenerator(projectSettings, generatorPlugins); } - public TestFileGeneratorResult GenerateCodeBehindFile(string capnpFile) + public CsFileGeneratorResult GenerateCodeBehindFile(string capnpFile) { - //var featureFileInput = new FeatureFileInput(featureFile); - //var generatedFeatureFileName = Path.GetFileName(_testGenerator.GetTestFullPath(featureFileInput)); + // Works around a weird capnp.exe behavior: When the input file is empty, it will spit out an exception dump + // instead of a parse error. But the parse error is nice because it contains a generated ID. We want the parse error! + // Workaround: Generate a temporary file that contains a single line break (such that it is not empty...) + try + { + if (File.Exists(capnpFile) && new FileInfo(capnpFile).Length == 0) + { + string tempFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".capnp"); - //var testGeneratorResult = _testGenerator.GenerateTestFile(featureFileInput, new GenerationSettings()); + File.WriteAllText(tempFile, Environment.NewLine); + try + { + return GenerateCodeBehindFile(tempFile); + } + finally + { + File.Delete(tempFile); + } + } + } + catch + { + } - return new TestFileGeneratorResult( - new TestGeneratorResult() { GeneratedTestCode = "//dummy" }, - capnpFile + ".cs"); + var result = CapnpCompilation.InvokeCapnpAndGenerate(new string[] { capnpFile }); + + if (result.IsSuccess) + { + if (result.GeneratedFiles.Count == 1) + { + return new CsFileGeneratorResult( + result.GeneratedFiles[0], + capnpFile + ".cs", + result.Messages); + } + else + { + return new CsFileGeneratorResult( + "Code generation produced more than one file. This is not supported.", + result.Messages); + } + } + else + { + switch (result.ErrorCategory) + { + case CapnpProcessFailure.NotFound: + return new CsFileGeneratorResult("Unable to find capnp.exe - please install capnproto on your system first."); + + case CapnpProcessFailure.BadInput: + return new CsFileGeneratorResult("Invalid schema", result.Messages); + + case CapnpProcessFailure.BadOutput: + return new CsFileGeneratorResult( + "Internal error: capnp.exe produced a binary code generation request which was not understood by the backend", + result.Messages); + + default: + throw new NotSupportedException("Invalid error category"); + } + } } public void Dispose() { - //_testGenerator?.Dispose(); } } } \ No newline at end of file diff --git a/Capnpc.Csharp.MsBuild.Generation/CapnpFileCodeBehindGenerator.cs b/Capnpc.Csharp.MsBuild.Generation/CapnpFileCodeBehindGenerator.cs index 6802c12..188830b 100644 --- a/Capnpc.Csharp.MsBuild.Generation/CapnpFileCodeBehindGenerator.cs +++ b/Capnpc.Csharp.MsBuild.Generation/CapnpFileCodeBehindGenerator.cs @@ -5,16 +5,13 @@ using System.Text; using System.Threading.Tasks; using Microsoft.Build.Utilities; -namespace Capnpc.Csharp.MsBuild.Generation +namespace CapnpC.CSharp.MsBuild.Generation { public class CapnpFileCodeBehindGenerator : ICapnpcCsharpGenerator { - private readonly FilePathGenerator _filePathGenerator; - public CapnpFileCodeBehindGenerator(TaskLoggingHelper log) { Log = log ?? throw new ArgumentNullException(nameof(log)); - _filePathGenerator = new FilePathGenerator(); } public TaskLoggingHelper Log { get; } @@ -39,33 +36,44 @@ namespace Capnpc.Csharp.MsBuild.Generation foreach (var capnpFile in capnpFiles) { - var capnpFileItemSpec = capnpFile; - var generatorResult = capnpCodeBehindGenerator.GenerateCodeBehindFile(capnpFileItemSpec); + var generatorResult = capnpCodeBehindGenerator.GenerateCodeBehindFile(capnpFile); if (!generatorResult.Success) { - foreach (var error in generatorResult.Errors) + if (!string.IsNullOrEmpty(generatorResult.Error)) { - //Log.LogError( - // null, - // null, - // null, - // featureFile, - // error.Line, - // error.LinePosition, - // 0, - // 0, - // error.Message); + Log.LogError("{0}", generatorResult.Error); } + + if (generatorResult.Messages != null) + { + foreach (var message in generatorResult.Messages) + { + if (message.IsParseSuccess) + { + Log.LogError( + subcategory: null, + errorCode: null, + helpKeyword: null, + file: capnpFile, + lineNumber: message.Line, + columnNumber: message.Column, + endLineNumber: message.Line, + endColumnNumber: message.EndColumn == 0 ? message.Column : message.EndColumn, + "{0}", + message.MessageText); + } + else + { + Log.LogError("{0}", message.FullMessage); + } + } + } + continue; } - var targetFilePath = _filePathGenerator.GenerateFilePath( - projectFolder, - capnpFile, - generatorResult.Filename); - - var resultedFile = codeBehindWriter.WriteCodeBehindFile(targetFilePath, capnpFile, generatorResult); + var resultedFile = codeBehindWriter.WriteCodeBehindFile(generatorResult.Filename, generatorResult); yield return FileSystemHelper.GetRelativePath(resultedFile, projectFolder); } diff --git a/Capnpc.Csharp.MsBuild.Generation/Capnpc.Csharp.MsBuild.Generation.csproj b/Capnpc.Csharp.MsBuild.Generation/Capnpc.Csharp.MsBuild.Generation.csproj index 67c482c..bbb9e95 100644 --- a/Capnpc.Csharp.MsBuild.Generation/Capnpc.Csharp.MsBuild.Generation.csproj +++ b/Capnpc.Csharp.MsBuild.Generation/Capnpc.Csharp.MsBuild.Generation.csproj @@ -2,9 +2,6 @@ net471;netcoreapp2.1 false - $(MSBuildThisFileDirectory)Capnpc.Csharp.MsBuild.Generation.nuspec - true - true true @@ -12,6 +9,13 @@ true true $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + 1.0.0.0 + 1.0.0.0 + 1.0.0 + + $(MSBuildThisFileDirectory)CapnpC.CSharp.MsBuild.Generation.nuspec + version=$(Version) + true @@ -54,6 +58,12 @@ + + + true + + + Microsoft.Build @@ -68,11 +78,28 @@ + + Always + + + Always + + + Always + + + Always + + + Always + MSBuild:Compile + Always MSBuild:Compile + Always diff --git a/Capnpc.Csharp.MsBuild.Generation/Capnpc.Csharp.MsBuild.Generation.nuspec b/Capnpc.Csharp.MsBuild.Generation/Capnpc.Csharp.MsBuild.Generation.nuspec index 887d527..d5073c9 100644 --- a/Capnpc.Csharp.MsBuild.Generation/Capnpc.Csharp.MsBuild.Generation.nuspec +++ b/Capnpc.Csharp.MsBuild.Generation/Capnpc.Csharp.MsBuild.Generation.nuspec @@ -1,9 +1,9 @@ - Capnpc.Csharp.MsBuild.Generation - 1.0.0 - Capnpc.Csharp.MsBuild.Generation + CapnpC.CSharp.MsBuild.Generation + $version$ + CapnpC.CSharp.MsBuild.Generation Christian Köllner and contributors Christian Köllner Package to enable the .capnp -> .cs file generation during build time @@ -15,6 +15,7 @@ capnproto csharp msbuild Christian Köllner and contributors + diff --git a/Capnpc.Csharp.MsBuild.Generation/CodeBehindWriter.cs b/Capnpc.Csharp.MsBuild.Generation/CodeBehindWriter.cs index f581de3..3ff276b 100644 --- a/Capnpc.Csharp.MsBuild.Generation/CodeBehindWriter.cs +++ b/Capnpc.Csharp.MsBuild.Generation/CodeBehindWriter.cs @@ -2,7 +2,7 @@ using System.IO; using Microsoft.Build.Utilities; -namespace Capnpc.Csharp.MsBuild.Generation +namespace CapnpC.CSharp.MsBuild.Generation { public class CodeBehindWriter { @@ -13,14 +13,8 @@ namespace Capnpc.Csharp.MsBuild.Generation public TaskLoggingHelper Log { get; } - public string WriteCodeBehindFile(string outputPath, string capnpFile, TestFileGeneratorResult testFileGeneratorResult) + public string WriteCodeBehindFile(string outputPath, CsFileGeneratorResult testFileGeneratorResult) { - //if (string.IsNullOrEmpty(testFileGeneratorResult.Filename)) - //{ - // Log?.LogWithNameTag(Log.LogError, $"{featureFile} has no generated filename"); - // return null; - //} - string directoryPath = Path.GetDirectoryName(outputPath) ?? throw new InvalidOperationException(); Log?.LogWithNameTag(Log.LogMessage, directoryPath); @@ -35,11 +29,6 @@ namespace Capnpc.Csharp.MsBuild.Generation } else { - if (!Directory.Exists(directoryPath)) - { - Directory.CreateDirectory(directoryPath); - } - File.WriteAllText(outputPath, testFileGeneratorResult.GeneratedCode); } diff --git a/Capnpc.Csharp.MsBuild.Generation/FilePathGenerator.cs b/Capnpc.Csharp.MsBuild.Generation/FilePathGenerator.cs deleted file mode 100644 index 4ac982d..0000000 --- a/Capnpc.Csharp.MsBuild.Generation/FilePathGenerator.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.IO; - -namespace Capnpc.Csharp.MsBuild.Generation -{ - public class FilePathGenerator - { - public string GenerateFilePath(string projectFolder, string capnpFileName, string generatedCodeBehindFileName) - { - if (projectFolder is null) - { - throw new ArgumentNullException(nameof(projectFolder)); - } - - if (capnpFileName is null) - { - throw new ArgumentNullException(nameof(capnpFileName)); - } - - if (generatedCodeBehindFileName is null) - { - throw new ArgumentNullException(nameof(generatedCodeBehindFileName)); - } - - string featureFileFullPath = Path.GetFullPath(Path.Combine(projectFolder, capnpFileName)); - string featureFileDirPath = Path.GetDirectoryName(featureFileFullPath); - - return Path.Combine(featureFileDirPath, generatedCodeBehindFileName); - } - } -} diff --git a/Capnpc.Csharp.MsBuild.Generation/FileSystemHelper.cs b/Capnpc.Csharp.MsBuild.Generation/FileSystemHelper.cs index d27428f..d538531 100644 --- a/Capnpc.Csharp.MsBuild.Generation/FileSystemHelper.cs +++ b/Capnpc.Csharp.MsBuild.Generation/FileSystemHelper.cs @@ -4,7 +4,7 @@ using System.Diagnostics; using System.IO; using System.Text; -namespace Capnpc.Csharp.MsBuild.Generation +namespace CapnpC.CSharp.MsBuild.Generation { public static class FileSystemHelper { diff --git a/Capnpc.Csharp.MsBuild.Generation/GenerateCapnpFileCodeBehindTask.cs b/Capnpc.Csharp.MsBuild.Generation/GenerateCapnpFileCodeBehindTask.cs index b4b9269..d29cf8d 100644 --- a/Capnpc.Csharp.MsBuild.Generation/GenerateCapnpFileCodeBehindTask.cs +++ b/Capnpc.Csharp.MsBuild.Generation/GenerateCapnpFileCodeBehindTask.cs @@ -7,7 +7,7 @@ using System.Resources; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; -namespace Capnpc.Csharp.MsBuild.Generation +namespace CapnpC.CSharp.MsBuild.Generation { public class GenerateCapnpFileCodeBehindTask : Task { diff --git a/Capnpc.Csharp.MsBuild.Generation/Helper/LogExtensions.cs b/Capnpc.Csharp.MsBuild.Generation/Helper/LogExtensions.cs index 1343a80..3203bea 100644 --- a/Capnpc.Csharp.MsBuild.Generation/Helper/LogExtensions.cs +++ b/Capnpc.Csharp.MsBuild.Generation/Helper/LogExtensions.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; using Microsoft.Build.Utilities; -namespace Capnpc.Csharp.MsBuild.Generation +namespace CapnpC.CSharp.MsBuild.Generation { public static class LogExtensions { @@ -15,7 +15,7 @@ namespace Capnpc.Csharp.MsBuild.Generation string message, params object[] messageArgs) { - string fullMessage = $"[SpecFlow] {message}"; + string fullMessage = $"[Cap'n Proto] {message}"; loggingMethod?.Invoke(fullMessage, messageArgs); } } diff --git a/Capnpc.Csharp.MsBuild.Generation/ICapnpCsharpGenerator.cs b/Capnpc.Csharp.MsBuild.Generation/ICapnpCsharpGenerator.cs index d55ed1e..de828fd 100644 --- a/Capnpc.Csharp.MsBuild.Generation/ICapnpCsharpGenerator.cs +++ b/Capnpc.Csharp.MsBuild.Generation/ICapnpCsharpGenerator.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Capnpc.Csharp.MsBuild.Generation +namespace CapnpC.CSharp.MsBuild.Generation { public interface ICapnpcCsharpGenerator { diff --git a/Capnpc.Csharp.MsBuild.Generation/TestFileGeneratorResult.cs b/Capnpc.Csharp.MsBuild.Generation/TestFileGeneratorResult.cs deleted file mode 100644 index 36ab361..0000000 --- a/Capnpc.Csharp.MsBuild.Generation/TestFileGeneratorResult.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Capnpc.Csharp.MsBuild.Generation -{ - public class TestFileGeneratorResult - { - public TestFileGeneratorResult(TestGeneratorResult generatorResult, string fileName) - { - if (generatorResult == null) - { - throw new ArgumentNullException(nameof(generatorResult)); - } - - Filename = fileName ?? throw new ArgumentNullException(nameof(fileName)); - - Errors = generatorResult.Errors; - IsUpToDate = generatorResult.IsUpToDate; - GeneratedCode = generatorResult.GeneratedTestCode; - } - - /// - /// The errors, if any. - /// - public IEnumerable Errors { get; } - - /// - /// The generated file was up-to-date. - /// - public bool IsUpToDate { get; } - - /// - /// The generated code. - /// - public string GeneratedCode { get; } - - public bool Success => Errors == null || !Errors.Any(); - - public string Filename { get; } - } -} \ No newline at end of file diff --git a/Capnpc.Csharp.MsBuild.Generation/TestGenerationError.cs b/Capnpc.Csharp.MsBuild.Generation/TestGenerationError.cs deleted file mode 100644 index 1bf834c..0000000 --- a/Capnpc.Csharp.MsBuild.Generation/TestGenerationError.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Capnpc.Csharp.MsBuild.Generation -{ - public class TestGenerationError - { - } -} \ No newline at end of file diff --git a/Capnpc.Csharp.MsBuild.Generation/TestGeneratorResult.cs b/Capnpc.Csharp.MsBuild.Generation/TestGeneratorResult.cs deleted file mode 100644 index 35b34e3..0000000 --- a/Capnpc.Csharp.MsBuild.Generation/TestGeneratorResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; - -namespace Capnpc.Csharp.MsBuild.Generation -{ - public class TestGeneratorResult - { - public IEnumerable Errors { get; internal set; } - public bool IsUpToDate { get; internal set; } - public string GeneratedTestCode { get; internal set; } - } -} \ No newline at end of file diff --git a/Capnpc.Csharp.MsBuild.Generation/build/CPS/Buildsystem/Rules/CapnpFileType.xaml b/Capnpc.Csharp.MsBuild.Generation/build/CPS/Buildsystem/Rules/CapnpFileType.xaml index ec90cbe..72e5c94 100644 --- a/Capnpc.Csharp.MsBuild.Generation/build/CPS/Buildsystem/Rules/CapnpFileType.xaml +++ b/Capnpc.Csharp.MsBuild.Generation/build/CPS/Buildsystem/Rules/CapnpFileType.xaml @@ -29,7 +29,7 @@ - + \ No newline at end of file diff --git a/Capnpc.Csharp.MsBuild.Generation/build/Capnpc.Csharp.MsBuild.Generation.props b/Capnpc.Csharp.MsBuild.Generation/build/Capnpc.Csharp.MsBuild.Generation.props index fe7e57a..bc41f4e 100644 --- a/Capnpc.Csharp.MsBuild.Generation/build/Capnpc.Csharp.MsBuild.Generation.props +++ b/Capnpc.Csharp.MsBuild.Generation/build/Capnpc.Csharp.MsBuild.Generation.props @@ -54,7 +54,7 @@ - after deletion of a feature file - after pulling latest changes from version control with above changes --> - + - + @@ -128,6 +128,6 @@ - after deletion of a capnp file - after pulling latest changes from version control with above changes --> - + \ No newline at end of file diff --git a/Capnpc.Csharp.MsBuild.Generation/build/Capnpc.Csharp.MsBuild.Generation.tasks b/Capnpc.Csharp.MsBuild.Generation/build/Capnpc.Csharp.MsBuild.Generation.tasks index b20fdae..9859d7b 100644 --- a/Capnpc.Csharp.MsBuild.Generation/build/Capnpc.Csharp.MsBuild.Generation.tasks +++ b/Capnpc.Csharp.MsBuild.Generation/build/Capnpc.Csharp.MsBuild.Generation.tasks @@ -1,3 +1,3 @@  - + \ No newline at end of file diff --git a/Capnpc.Csharp.MsBuild.Generation/buildMultiTargeting/Capnpc.Csharp.MsBuild.Generation.props b/Capnpc.Csharp.MsBuild.Generation/buildMultiTargeting/Capnpc.Csharp.MsBuild.Generation.props index f3c49ea..62930dd 100644 --- a/Capnpc.Csharp.MsBuild.Generation/buildMultiTargeting/Capnpc.Csharp.MsBuild.Generation.props +++ b/Capnpc.Csharp.MsBuild.Generation/buildMultiTargeting/Capnpc.Csharp.MsBuild.Generation.props @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/README.md b/README.md index db6030c..829271a 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Solution/project structure is as follows: * Capnp.Net.Runtime is the runtime implementation, a .NET assembly. * capnpc-csharp is the generator backend for C# language. * Capnp.Net.Runtime.Tests is an MS Unit Testing assembly, containing - you guessed it - the test suite. - * capnpc-csharp.tests contains the generator backend test suite. + * CapnpC.CSharp.Generator.Tests contains the generator backend test suite. - CapnpCompatTest.sln compiles to a native x86 executable which depends on the original Cap'n Proto C++ implementation. It is (partially) required by the test suite for interoperability testing. ## Features diff --git a/appveyor.yml b/appveyor.yml index b08ea80..00636e7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -29,7 +29,7 @@ before_build: - cmd: dotnet restore ./Capnp.Net.Runtime.Tests/Capnp.Net.Runtime.Tests.Std20.csproj --verbosity m - cmd: dotnet restore ./Capnp.Net.Runtime.Tests.Core21/Capnp.Net.Runtime.Tests.Core21.csproj --verbosity m - cmd: dotnet restore ./capnpc-csharp/capnpc-csharp.csproj --verbosity m - - cmd: dotnet restore ./capnpc-csharp.tests/capnpc-csharp.tests.csproj --verbosity m + - cmd: dotnet restore ./CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj --verbosity m build_script: - cmd: msbuild ./Capnp.Net.sln /p:Configuration="Debug" - cmd: msbuild ./Capnp.Net.sln /p:Configuration="Release" @@ -50,11 +50,12 @@ artifacts: type: NuGetPackage clone_depth: 1 test_script: - - cmd: vstest.console /logger:Appveyor /inIsolation capnpc-csharp.tests\bin\Release\netcoreapp2.2\capnpc-csharp.tests.dll + - cmd: vstest.console /logger:Appveyor /inIsolation CapnpC.CSharp.Generator.Tests\bin\Release\netcoreapp2.2\CapnpC.CSharp.Generator.Tests.dll - cmd: cd %APPVEYOR_BUILD_FOLDER%\chocolatey\install - cmd: choco install capnpc-csharp --source=".;https://chocolatey.org/api/v2" --force -y - cmd: cd %APPVEYOR_BUILD_FOLDER%\install-test - cmd: compile-test + - cmd: vstest.console /logger:Appveyor /inIsolation CapnpC.CSharp.Generator.Tests\bin\Release\netcoreapp2.2\CapnpC.CSharp.Generator.Tests.dll - cmd: choco uninstall capnpc-csharp -y - cmd: notinstalled-test - cmd: cd %APPVEYOR_BUILD_FOLDER%\chocolatey\install diff --git a/capnpc-csharp.tests/CodeGenerator.feature b/capnpc-csharp.tests/CodeGenerator.feature deleted file mode 100644 index 89768b9..0000000 --- a/capnpc-csharp.tests/CodeGenerator.feature +++ /dev/null @@ -1,20 +0,0 @@ -Feature: CodeGenerator - In order to ensure that the generator backend produces valid output - As a contributor - I want to get notified when there is any deviation from reference output - -Scenario: Comparing backend output with reference - Given I have a binary code generator request "test.capnp.bin" - And my reference output is "test.cs" - When I invoke capnpc-csharp - Then the generated output must match the reference - -Scenario Outline: Invalid binary code generator requests - Given I have a binary code generator request - When I invoke capnpc-csharp - Then the invocation must fail - -Examples: - | bin | - | null.bin | - | test.cs | \ No newline at end of file diff --git a/capnpc-csharp.tests/FeatureSteps/CodeGeneratorSteps.cs b/capnpc-csharp.tests/FeatureSteps/CodeGeneratorSteps.cs deleted file mode 100644 index 4d3a893..0000000 --- a/capnpc-csharp.tests/FeatureSteps/CodeGeneratorSteps.cs +++ /dev/null @@ -1,83 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.IO; -using System.Reflection; -using TechTalk.SpecFlow; - -namespace capnpc_csharp.Tests -{ - [Binding] - public class CodeGeneratorSteps - { - Stream _inputStream; - string _referenceOutputContent; - string _exceptedOutputFileName; - string _actualGeneratedContent; - bool _success; - Exception _generateException; - - internal static Stream LoadResource(string name) - { - var assembly = Assembly.GetExecutingAssembly(); - string[] names = assembly.GetManifestResourceNames(); - string urn = Array.Find(names, n => n.EndsWith(name, StringComparison.OrdinalIgnoreCase)); - Assert.IsNotNull(urn, $"Test specification error: {name} does not exist"); - return assembly.GetManifestResourceStream(urn); - } - - [Given(@"I have a binary code generator request ""(.*)""")] - [Given(@"I have a binary code generator request (.*)")] - public void GivenIHaveABinaryCodeGeneratorRequest(string binaryRequestFileName) - { - _inputStream = LoadResource(binaryRequestFileName); - } - - [Given(@"my reference output is ""(.*)""")] - public void GivenMyReferenceOutputIs(string expectedOutputFileName) - { - _exceptedOutputFileName = expectedOutputFileName; - using (var stream = LoadResource(expectedOutputFileName)) - using (var reader = new StreamReader(stream)) - { - _referenceOutputContent = reader.ReadToEnd(); - } - } - - [When(@"I invoke capnpc-csharp")] - public void WhenIInvokeCapnpc_Csharp() - { - try - { - using (_inputStream) - { - string tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - Directory.CreateDirectory(tempDir); - Environment.CurrentDirectory = tempDir; - - CapnpC.Program.GenerateFromStream(_inputStream); - - string outPath = Path.Combine(tempDir, _exceptedOutputFileName); - _actualGeneratedContent = File.ReadAllText(outPath); - _success = true; - } - } - catch (Exception exception) - { - _generateException = exception; - } - } - - [Then(@"the generated output must match the reference")] - public void ThenTheGeneratedOutputMustMatchTheReference() - { - Assert.IsTrue(_success, $"Code generation failed: {_generateException?.Message}"); - Assert.AreEqual(_referenceOutputContent, _actualGeneratedContent); - } - - [Then(@"the invocation must fail")] - public void ThenTheInvocationMustFail() - { - Assert.IsFalse(_success, "Code generation was supposed to fail, but it didn't"); - } - } -} diff --git a/capnpc-csharp/Generator/CodeGenerator.cs b/capnpc-csharp/Generator/CodeGenerator.cs deleted file mode 100644 index e401b3a..0000000 --- a/capnpc-csharp/Generator/CodeGenerator.cs +++ /dev/null @@ -1,182 +0,0 @@ -namespace CapnpC.Generator -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Text; - using CapnpC.Model; - using Microsoft.CodeAnalysis; - using Microsoft.CodeAnalysis.CSharp; - using Microsoft.CodeAnalysis.CSharp.Syntax; - using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - using static SyntaxHelpers; - - class CodeGenerator - { - readonly SchemaModel _model; - readonly GenNames _names; - readonly CommonSnippetGen _commonGen; - readonly DomainClassSnippetGen _domClassGen; - readonly ReaderSnippetGen _readerGen; - readonly WriterSnippetGen _writerGen; - readonly InterfaceSnippetGen _interfaceGen; - - public CodeGenerator(SchemaModel model, GeneratorOptions options) - { - _model = model; - _names = new GenNames(options); - _commonGen = new CommonSnippetGen(_names); - _domClassGen = new DomainClassSnippetGen(_names); - _readerGen = new ReaderSnippetGen(_names); - _writerGen = new WriterSnippetGen(_names); - _interfaceGen = new InterfaceSnippetGen(_names); - } - - internal GenNames GetNames() => _names; - - IEnumerable TransformEnum(TypeDefinition def) - { - yield return _commonGen.MakeEnum(def); - } - - IEnumerable MakeTypeParameters(TypeDefinition def) - { - foreach (string name in def.GenericParameters) - { - yield return TypeParameter(_names.GetGenericTypeParameter(name).Identifier); - } - } - - IEnumerable MakeTypeParameterConstraints(TypeDefinition def) - { - foreach (string name in def.GenericParameters) - { - yield return TypeParameterConstraintClause( - _names.GetGenericTypeParameter(name).IdentifierName) - .AddConstraints(ClassOrStructConstraint(SyntaxKind.ClassConstraint)); - } - } - - IEnumerable TransformStruct(TypeDefinition def) - { - var topDecl = ClassDeclaration(_names.MakeTypeName(def).Identifier) - .AddModifiers(Public) - .AddBaseListTypes(SimpleBaseType(Type())); - - if (def.GenericParameters.Count > 0) - { - topDecl = topDecl - .AddTypeParameterListParameters(MakeTypeParameters(def).ToArray()) - .AddConstraintClauses(MakeTypeParameterConstraints(def).ToArray()); - } - - if (def.UnionInfo != null) - { - topDecl = topDecl.AddMembers(_commonGen.MakeUnionSelectorEnum(def)); - } - - topDecl = topDecl.AddMembers(_domClassGen.MakeDomainClassMembers(def)); - topDecl = topDecl.AddMembers(_readerGen.MakeReaderStruct(def)); - topDecl = topDecl.AddMembers(_writerGen.MakeWriterStruct(def)); - - foreach (var nestedGroup in def.NestedGroups) - { - topDecl = topDecl.AddMembers(Transform(nestedGroup).ToArray()); - } - - foreach (var nestedDef in def.NestedTypes) - { - topDecl = topDecl.AddMembers(Transform(nestedDef).ToArray()); - } - - yield return topDecl; - } - - IEnumerable TransformInterface(TypeDefinition def) - { - yield return _interfaceGen.MakeInterface(def); - yield return _interfaceGen.MakeProxy(def); - yield return _interfaceGen.MakeSkeleton(def); - - if (_interfaceGen.RequiresPipeliningSupport(def)) - { - yield return _interfaceGen.MakePipeliningSupport(def); - } - - if (def.NestedTypes.Any()) - { - var ns = ClassDeclaration( - _names.MakeTypeName(def, NameUsage.Namespace).ToString()) - .AddModifiers(Public, Static); - - if (def.GenericParameters.Count > 0) - { - ns = ns - .AddTypeParameterListParameters(MakeTypeParameters(def).ToArray()) - .AddConstraintClauses(MakeTypeParameterConstraints(def).ToArray()); - } - - foreach (var nestedDef in def.NestedTypes) - { - ns = ns.AddMembers(Transform(nestedDef).ToArray()); - } - - yield return ns; - } - } - - IEnumerable Transform(TypeDefinition def) - { - switch (def.Tag) - { - case TypeTag.Enum: - return TransformEnum(def); - - case TypeTag.Group: - case TypeTag.Struct: - return TransformStruct(def); - - case TypeTag.Interface: - return TransformInterface(def); - - default: - throw new NotSupportedException($"Cannot declare type of kind {def.Tag} here"); - } - } - - internal string Transform(GenFile file) - { - NameSyntax topNamespace = GenNames.NamespaceName(file.Namespace) ?? _names.TopNamespace; - - var ns = NamespaceDeclaration(topNamespace); - - foreach (var def in file.NestedTypes) - { - ns = ns.AddMembers(Transform(def).ToArray()); - } - - var cu = CompilationUnit().AddUsings( - UsingDirective(ParseName("Capnp")), - UsingDirective(ParseName("Capnp.Rpc")), - UsingDirective(ParseName("System")), - UsingDirective(ParseName("System.Collections.Generic")), - UsingDirective(ParseName("System.Threading")), - UsingDirective(ParseName("System.Threading.Tasks"))); - - cu = cu.AddMembers(ns); - - return cu.NormalizeWhitespace().ToFullString(); - } - - public void Generate() - { - foreach (var file in _model.FilesToGenerate) - { - string content = Transform(file); - string path = Path.ChangeExtension(file.Name, ".cs"); - File.WriteAllText(path, content); - } - } - } -} diff --git a/capnpc-csharp/Generator/CommonSnippetGen.cs b/capnpc-csharp/Generator/CommonSnippetGen.cs deleted file mode 100644 index 2e1797d..0000000 --- a/capnpc-csharp/Generator/CommonSnippetGen.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using CapnpC.Model; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static CapnpC.Generator.SyntaxHelpers; - -namespace CapnpC.Generator -{ - class CommonSnippetGen - { - readonly GenNames _names; - - public CommonSnippetGen(GenNames names) - { - _names = names; - } - - public EnumDeclarationSyntax MakeUnionSelectorEnum(TypeDefinition def) - { - var whichEnum = EnumDeclaration(_names.UnionDiscriminatorEnum.ToString()) - .AddModifiers(Public) - .AddBaseListTypes(SimpleBaseType(Type())); - - var discFields = def.Fields.Where(f => f.DiscValue.HasValue); - - foreach (var discField in discFields) - { - whichEnum = whichEnum.AddMembers( - EnumMemberDeclaration(_names.GetCodeIdentifier(discField).Identifier) - .WithEqualsValue( - EqualsValueClause(LiteralExpression( - SyntaxKind.NumericLiteralExpression, - Literal(discField.DiscValue.Value))))); - } - - var ndecl = EnumMemberDeclaration(_names.UnionDiscriminatorUndefined.ToString()).WithEqualsValue( - EqualsValueClause( - LiteralExpression( - SyntaxKind.NumericLiteralExpression, - Literal(Schema.Field.Reader.NoDiscriminant)))); - - whichEnum = whichEnum.AddMembers(ndecl); - - return whichEnum; - } - - public EnumDeclarationSyntax MakeEnum(TypeDefinition def) - { - var decl = EnumDeclaration(def.Name) - .AddModifiers(Public) - .AddBaseListTypes(SimpleBaseType(Type())); - - foreach (var enumerant in def.Enumerants.OrderBy(e => e.CodeOrder)) - { - var mdecl = EnumMemberDeclaration(enumerant.Literal); - - if (enumerant.Ordinal.HasValue) - { - mdecl = mdecl.WithEqualsValue( - EqualsValueClause( - LiteralExpression( - SyntaxKind.NumericLiteralExpression, - Literal(enumerant.Ordinal.Value)))); - } - - decl = decl.AddMembers(mdecl); - } - - return decl; - } - - public static IEnumerable MakeCommaSeparatedList(IEnumerable expressions) - { - bool first = true; - - foreach (var expr in expressions) - { - if (first) - first = false; - else - yield return Token(SyntaxKind.CommaToken); - - yield return expr; - } - } - - } -} diff --git a/capnpc-csharp/Generator/DomainClassSnippetGen.cs b/capnpc-csharp/Generator/DomainClassSnippetGen.cs deleted file mode 100644 index 5b27495..0000000 --- a/capnpc-csharp/Generator/DomainClassSnippetGen.cs +++ /dev/null @@ -1,972 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using CapnpC.Model; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static CapnpC.Generator.SyntaxHelpers; - -namespace CapnpC.Generator -{ - class DomainClassSnippetGen - { - readonly GenNames _names; - - public DomainClassSnippetGen(GenNames names) - { - _names = names; - } - - MemberDeclarationSyntax MakeUnionField(Field field) - { - var type = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.DomainClassNullable); - - switch (field.Type.Tag) - { - case TypeTag.Void: - return null; - - default: - return PropertyDeclaration(type, - _names.GetCodeIdentifier(field).Identifier) - .AddModifiers(Public).AddAccessorListAccessors( - AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) - .WithExpressionBody( - ArrowExpressionClause( - ConditionalExpression( - BinaryExpression( - SyntaxKind.EqualsExpression, - _names.UnionDiscriminatorField.IdentifierName, - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.UnionDiscriminatorEnum.IdentifierName, - _names.GetCodeIdentifier(field).IdentifierName)), - CastExpression(type, - _names.UnionContentField.IdentifierName), - LiteralExpression( - SyntaxKind.NullLiteralExpression)))) - .WithSemicolonToken( - Token(SyntaxKind.SemicolonToken)), - AccessorDeclaration( - SyntaxKind.SetAccessorDeclaration) - .WithBody( - Block( - ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - _names.UnionDiscriminatorField.IdentifierName, - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.UnionDiscriminatorEnum.IdentifierName, - _names.GetCodeIdentifier(field).IdentifierName))), - ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - _names.UnionContentField.IdentifierName, - IdentifierName("value")))))); - } - } - - MemberDeclarationSyntax MakeStructField(Field field) - { - if (field.Type.Tag == TypeTag.Void) - { - return null; - } - - var prop = PropertyDeclaration(_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.DomainClass), - _names.GetCodeIdentifier(field).Identifier) - .AddModifiers(Public).AddAccessorListAccessors( - AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), - AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))); - - if (field.DefaultValueIsExplicit && field.Type.IsValueType) - { - prop = prop.WithInitializer( - EqualsValueClause(MakeDefaultValue(field))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); - } - - return prop; - } - - MemberDeclarationSyntax MakeUnionDiscriminatorField() - { - return FieldDeclaration( - VariableDeclaration(_names.UnionDiscriminatorEnum.IdentifierName) - .AddVariables( - VariableDeclarator(_names.UnionDiscriminatorField.Identifier) - .WithInitializer( - EqualsValueClause( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.UnionDiscriminatorEnum.IdentifierName, - _names.UnionDiscriminatorUndefined.IdentifierName))))) - .AddModifiers(Private); - } - - MemberDeclarationSyntax MakeUnionContentField() - { - return FieldDeclaration( - VariableDeclaration(SyntaxHelpers.Type()) - .WithVariables( - SingletonSeparatedList( - VariableDeclarator(_names.UnionContentField.Identifier)))) - .AddModifiers(Private); - } - - IEnumerable MakeInitializerAssignments(Value structValue, TypeDefinition scope) - { - foreach (var fieldValue in structValue.Fields) - { - var valueExpr = MakeValue(fieldValue.Item2, scope); - if (valueExpr == null) - continue; - - yield return AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - _names.GetCodeIdentifier(fieldValue.Item1).IdentifierName, - valueExpr); - } - } - - ExpressionSyntax MakeValue(Value value, TypeDefinition scope) - { - switch (value.Type.Tag) - { - case TypeTag.AnyEnum: - return LiteralExpression( - SyntaxKind.NumericLiteralExpression, Literal((ushort)value.ScalarValue)); - - case TypeTag.Bool: - - if ((bool)value.ScalarValue) - return LiteralExpression(SyntaxKind.TrueLiteralExpression); - else - return LiteralExpression(SyntaxKind.FalseLiteralExpression); - - case TypeTag.Data: - return ArrayCreationExpression(ArrayType( - PredefinedType(Token(SyntaxKind.ByteKeyword))) - .WithRankSpecifiers( - SingletonList( - ArrayRankSpecifier( - SingletonSeparatedList( - OmittedArraySizeExpression()))))) - .WithInitializer( - InitializerExpression( - SyntaxKind.ArrayInitializerExpression) - .AddExpressions(value.Items.Select(v => MakeValue(v, scope)).ToArray())); - - case TypeTag.Enum: - return MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _names.MakeTypeSyntax(value.Type, scope, TypeUsage.NotRelevant), - IdentifierName(value.GetEnumerant().Literal)); - - case TypeTag.F32: - switch ((float)value.ScalarValue) - { - case float.NaN: - return MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("float"), - IdentifierName(nameof(float.NaN))); - - case float.NegativeInfinity: - return MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("float"), - IdentifierName(nameof(float.NegativeInfinity))); - - case float.PositiveInfinity: - return MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("float"), - IdentifierName(nameof(float.PositiveInfinity))); - - default: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal((float)value.ScalarValue)); - } - - case TypeTag.F64: - switch ((double)value.ScalarValue) - { - case double.NaN: - return MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("double"), - IdentifierName(nameof(double.NaN))); - - case double.NegativeInfinity: - return MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("double"), - IdentifierName(nameof(double.NegativeInfinity))); - - case double.PositiveInfinity: - return MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("double"), - IdentifierName(nameof(double.PositiveInfinity))); - - default: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal((double)value.ScalarValue)); - } - - case TypeTag.S8: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal((sbyte)value.ScalarValue)); - - case TypeTag.S16: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal((short)value.ScalarValue)); - - case TypeTag.S32: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal((int)value.ScalarValue)); - - case TypeTag.S64: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal((long)value.ScalarValue)); - - case TypeTag.U8: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal((byte)value.ScalarValue)); - - case TypeTag.U16: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal((ushort)value.ScalarValue)); - - case TypeTag.U32: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal((uint)value.ScalarValue)); - - case TypeTag.U64: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal((ulong)value.ScalarValue)); - - case TypeTag.Text: - value.Decode(); - return value.ScalarValue == null ? - LiteralExpression(SyntaxKind.NullLiteralExpression) : - LiteralExpression(SyntaxKind.StringLiteralExpression, - Literal((string)value.ScalarValue)); - - case TypeTag.Group: - case TypeTag.Struct: - value.Decode(); - - return ObjectCreationExpression( - _names.MakeTypeSyntax(value.Type, scope, TypeUsage.DomainClass)) - .WithArgumentList(ArgumentList()) - .WithInitializer( - InitializerExpression( - SyntaxKind.ObjectInitializerExpression) - .AddExpressions(MakeInitializerAssignments(value, scope).ToArray())); - - case TypeTag.ListPointer: - // TBD - return LiteralExpression(SyntaxKind.NullLiteralExpression); - - case TypeTag.List when value.Type.ElementType.Tag == TypeTag.Void: - value.Decode(); - - return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal((int)value.VoidListCount)); - - case TypeTag.List: - value.Decode(); - - return ArrayCreationExpression(ArrayType( - _names.MakeTypeSyntax(value.Type.ElementType, scope, TypeUsage.DomainClass)) - .WithRankSpecifiers( - SingletonList( - ArrayRankSpecifier( - SingletonSeparatedList( - OmittedArraySizeExpression()))))) - .WithInitializer( - InitializerExpression( - SyntaxKind.ArrayInitializerExpression) - .AddExpressions(value.Items.Select(v => MakeValue(v, scope)).ToArray())); - - case TypeTag.AnyPointer: - case TypeTag.CapabilityPointer: - // TBD - return null; - - case TypeTag.Interface: - return null; - - default: - throw new NotImplementedException(); - } - } - - ExpressionSyntax MakeDefaultValue(Field field) - { - if (field.DefaultValueIsExplicit) - { - return MakeValue(field.DefaultValue, field.DeclaringType); - } - else - { - switch (field.Type.Tag) - { - case TypeTag.AnyEnum: - case TypeTag.S16: - case TypeTag.S32: - case TypeTag.S64: - case TypeTag.S8: - case TypeTag.U16: - case TypeTag.U32: - case TypeTag.U64: - case TypeTag.U8: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)); - - case TypeTag.AnyPointer: - case TypeTag.CapabilityPointer: - case TypeTag.Data: - case TypeTag.Group: - case TypeTag.Interface: - case TypeTag.List: - case TypeTag.ListPointer: - case TypeTag.Struct: - case TypeTag.StructPointer: - case TypeTag.Text: - return LiteralExpression(SyntaxKind.NullLiteralExpression); - - case TypeTag.Bool: - return LiteralExpression(SyntaxKind.FalseLiteralExpression); - - case TypeTag.Enum: - return MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.NotRelevant), - _names.UnionDiscriminatorUndefined.IdentifierName); - - case TypeTag.F32: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0.0f)); - - case TypeTag.F64: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0.0)); - - default: - throw new NotImplementedException(); - } - } - } - - IEnumerable MakeUnionDiscriminatorSetter(TypeDefinition def) - { - var unionFields = def.Fields.Where(f => f.DiscValue.HasValue); - - foreach (var unionField in unionFields) - { - var section = SwitchSection() - .WithLabels( - SingletonList( - CaseSwitchLabel(MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.UnionDiscriminatorEnum.IdentifierName, - _names.GetCodeIdentifier(unionField).IdentifierName)))); - - if (unionField.Type.Tag != TypeTag.Void) - { - section = section.AddStatements( - ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - _names.UnionContentField.IdentifierName, - MakeDefaultValue(unionField)))); - } - - section = section.AddStatements(BreakStatement()); - - yield return section; - } - } - - MemberDeclarationSyntax MakeUnionDiscriminatorProperty(TypeDefinition def) - { - return PropertyDeclaration(_names.UnionDiscriminatorEnum.IdentifierName, - _names.UnionDiscriminatorProp.Identifier) - .AddModifiers(Public).AddAccessorListAccessors( - AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) - .WithExpressionBody( - ArrowExpressionClause(_names.UnionDiscriminatorField.IdentifierName)) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), - AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) - .WithBody( - Block( - IfStatement( - BinaryExpression( - SyntaxKind.EqualsExpression, - IdentifierName("value"), - _names.UnionDiscriminatorField.IdentifierName), - ReturnStatement()), - ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - _names.UnionDiscriminatorField.IdentifierName, - IdentifierName("value"))), - SwitchStatement(IdentifierName("value")) - .WithOpenParenToken( - Token(SyntaxKind.OpenParenToken)) - .WithCloseParenToken( - Token(SyntaxKind.CloseParenToken)) - .AddSections(MakeUnionDiscriminatorSetter(def).ToArray())))); - } - - MemberDeclarationSyntax MakeField(Field field) - { - if (field.DiscValue.HasValue) - return MakeUnionField(field); - else - return MakeStructField(field); - } - - ExpressionSyntax MakeListSerializeParticle(Model.Type type, ExpressionSyntax writer, ExpressionSyntax domain) - { - string s = $"_s{type.GetRank().Item1}"; - string v = $"_v{type.GetRank().Item1}"; - - switch (type.ElementType?.Tag) - { - case TypeTag.List: - case TypeTag.ListPointer: - case TypeTag.Struct: - case TypeTag.Group: - case TypeTag.StructPointer: - case TypeTag.Data: - - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - writer, - IdentifierName(nameof(Capnp.ListOfPrimitivesSerializer.Init)))) - .AddArgumentListArguments( - Argument(domain), - Argument( - ParenthesizedLambdaExpression( - MakeComplexSerializeParticle( - type.ElementType, - IdentifierName(s), - IdentifierName(v))) - .AddParameterListParameters( - Parameter(Identifier(s)), - Parameter(Identifier(v))))); - - default: - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - writer, - IdentifierName(nameof(Capnp.ListOfPrimitivesSerializer.Init)))) - .AddArgumentListArguments(Argument(domain)); - } - } - - ExpressionSyntax MakeComplexSerializeParticle(Model.Type type, ExpressionSyntax writer, ExpressionSyntax domain) - { - switch (type.Tag) - { - case TypeTag.Data: - case TypeTag.List: - return MakeListSerializeParticle(type, writer, domain); - - case TypeTag.Struct: - case TypeTag.Group: - return ConditionalAccessExpression(domain, - InvocationExpression(MemberBindingExpression(_names.SerializeMethod.IdentifierName)) - .AddArgumentListArguments(Argument(writer))); - - default: - throw new NotImplementedException(); - } - } - - StatementSyntax MakeSerializeMethodFieldAssignment(Field field) - { - var writerProp = MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.WriterParameter.IdentifierName, - _names.GetCodeIdentifier(field).IdentifierName); - - switch (field.Type.Tag) - { - case TypeTag.Bool: - case TypeTag.Enum: - case TypeTag.F32: - case TypeTag.F64: - case TypeTag.S16: - case TypeTag.S32: - case TypeTag.S64: - case TypeTag.S8: - case TypeTag.U16: - case TypeTag.U32: - case TypeTag.U64: - case TypeTag.U8: - case TypeTag.AnyEnum: - case TypeTag.List when field.Type.Tag == TypeTag.Void: - if (field.DiscValue.HasValue) - { - return ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - writerProp, - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.GetCodeIdentifier(field).IdentifierName, - IdentifierName(nameof(Nullable.Value))))); - } - else - { - return ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - writerProp, - _names.GetCodeIdentifier(field).IdentifierName)); - } - - case TypeTag.AnyPointer: - case TypeTag.ListPointer: - case TypeTag.StructPointer: - return ExpressionStatement( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.WriterParameter.IdentifierName, - _names.GetCodeIdentifier(field).IdentifierName), - IdentifierName(nameof(Capnp.DynamicSerializerState.SetObject)))) - .AddArgumentListArguments( - Argument(_names.GetCodeIdentifier(field).IdentifierName))); - - case TypeTag.CapabilityPointer: - case TypeTag.Interface: - return ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - writerProp, - _names.GetCodeIdentifier(field).IdentifierName)); - - case TypeTag.Text: - return ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - writerProp, - _names.GetCodeIdentifier(field).IdentifierName)); - - case TypeTag.Data: - case TypeTag.List: - case TypeTag.Struct: - case TypeTag.Group: - return ExpressionStatement( - MakeComplexSerializeParticle( - field.Type, - writerProp, - _names.GetCodeIdentifier(field).IdentifierName)); - - case TypeTag.Void: - return null; - - default: - throw new NotImplementedException(); - } - } - - StatementSyntax MakeApplyDefaultsMethodFieldAssignment(Field field) - { - var lhs = _names.GetCodeIdentifier(field).IdentifierName; - var rhs = MakeDefaultValue(field); - - if (rhs == null) - { - return null; - } - - return ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - lhs, - BinaryExpression(SyntaxKind.CoalesceExpression, - lhs, rhs))); - } - - ExpressionSyntax MakeInnerStructListConversion(ExpressionSyntax context, TypeSyntax elementType) - { - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - context, - IdentifierName(nameof(Capnp.ReadOnlyListExtensions.ToReadOnlyList)))) - .AddArgumentListArguments(Argument( - SimpleLambdaExpression(Parameter(Identifier("_")), - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(nameof(Capnp.CapnpSerializable)), - GenericName(nameof(Capnp.CapnpSerializable.Create)) - .AddTypeArgumentListArguments(elementType))) - .AddArgumentListArguments(Argument(IdentifierName("_")))))); - } - - ExpressionSyntax MakeStructListConversion(ExpressionSyntax context, TypeSyntax elementType, int rank) - { - if (rank == 1) - { - return MakeInnerStructListConversion(context, elementType); - } - - string lambdaVarName = $"_{rank}"; - - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - context, - IdentifierName(nameof(Capnp.ReadOnlyListExtensions.ToReadOnlyList)))) - .AddArgumentListArguments(Argument( - SimpleLambdaExpression( - Parameter(Identifier(lambdaVarName)), - MakeStructListConversion(IdentifierName(lambdaVarName), elementType, rank - 1)))); - } - - ExpressionSyntax MakeAnyListConversion(ExpressionSyntax context) - { - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - context, - IdentifierName(nameof(Capnp.ReadOnlyListExtensions.ToReadOnlyList)))) - .AddArgumentListArguments(Argument( - SimpleLambdaExpression( - Parameter(Identifier("_")), - CastExpression(Type(), IdentifierName("_"))))); - } - - ExpressionSyntax MakeDeserializeMethodRightHandSide(Field field) - { - switch (field.Type.Tag) - { - case TypeTag.Struct: - case TypeTag.Group: - case TypeTag.StructPointer: - case TypeTag.AnyPointer: - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(nameof(Capnp.CapnpSerializable)), - GenericName(nameof(Capnp.CapnpSerializable.Create)) - .AddTypeArgumentListArguments( - _names.MakeTypeSyntax( - field.Type, - field.DeclaringType, - TypeUsage.DomainClass)))) - .AddArgumentListArguments(Argument(MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ReaderParameter.IdentifierName, - _names.GetCodeIdentifier(field).IdentifierName))); - - case TypeTag.Void: - return null; - - case TypeTag.List: - (var rank, var elementType) = field.Type.GetRank(); - if (elementType.Tag != TypeTag.Struct) - break; - - return MakeStructListConversion( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ReaderParameter.IdentifierName, - _names.GetCodeIdentifier(field).IdentifierName), - _names.MakeTypeSyntax(elementType, field.DeclaringType, TypeUsage.DomainClass), - rank); - - case TypeTag.ListPointer: - return MakeAnyListConversion( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ReaderParameter.IdentifierName, - _names.GetCodeIdentifier(field).IdentifierName)); - } - - return MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ReaderParameter.IdentifierName, - _names.GetCodeIdentifier(field).IdentifierName); - } - - IEnumerable MakeSerializeMethodSwitchSections(TypeDefinition def) - { - var unionFields = def.Fields.Where(f => f.DiscValue.HasValue); - - foreach (var unionField in unionFields) - { - var section = SwitchSection() - .AddLabels( - CaseSwitchLabel(MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.UnionDiscriminatorEnum.IdentifierName, - _names.GetCodeIdentifier(unionField).IdentifierName))); - - if (unionField.Type.Tag != TypeTag.Void) - { - ExpressionSyntax right = _names.GetCodeIdentifier(unionField).IdentifierName; - - var syntax = _names.MakeTypeSyntax(unionField.Type, unionField.DeclaringType, TypeUsage.DomainClassNullable); - - if (syntax is NullableTypeSyntax) - { - right = MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - right, - IdentifierName(nameof(Nullable.Value))); - } - - section = section.AddStatements(MakeSerializeMethodFieldAssignment(unionField)); - } - - section = section.AddStatements(BreakStatement()); - - yield return section; - } - } - - IEnumerable MakeDeserializeMethodSwitchSections(TypeDefinition def) - { - var unionFields = def.Fields.Where(f => f.DiscValue.HasValue); - - foreach (var unionField in unionFields) - { - var section = SwitchSection() - .AddLabels( - CaseSwitchLabel(MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.UnionDiscriminatorEnum.IdentifierName, - _names.GetCodeIdentifier(unionField).IdentifierName))); - - switch (unionField.Type.Tag) - { - case TypeTag.Void: - section = section.AddStatements( - ExpressionStatement(AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - _names.UnionDiscriminatorProp.IdentifierName, - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ReaderParameter.IdentifierName, - _names.UnionDiscriminatorProp.IdentifierName)))); - break; - - default: - section = section.AddStatements( - ExpressionStatement(AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - _names.GetCodeIdentifier(unionField).IdentifierName, - MakeDeserializeMethodRightHandSide(unionField)))); - break; - - } - - section = section.AddStatements(BreakStatement()); - - yield return section; - } - } - - IEnumerable MakeSerializeStatements(TypeDefinition def) - { - if (def.UnionInfo != null) - { - yield return ExpressionStatement(AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.WriterParameter.IdentifierName, - _names.UnionDiscriminatorProp.IdentifierName), - _names.UnionDiscriminatorProp.IdentifierName)); - - yield return SwitchStatement(_names.UnionDiscriminatorProp.IdentifierName) - .WithOpenParenToken(Token(SyntaxKind.OpenParenToken)) - .WithCloseParenToken(Token(SyntaxKind.CloseParenToken)) - .AddSections(MakeSerializeMethodSwitchSections(def).ToArray()); - } - - var nondiscFields = def.Fields.Where(f => !f.DiscValue.HasValue && f.Type.Tag != TypeTag.Void); - - foreach (var field in nondiscFields) - { - var asmt = MakeSerializeMethodFieldAssignment(field); - - if (asmt != null) - { - yield return asmt; - } - } - } - - IEnumerable MakeApplyDefaultsStatements(TypeDefinition def) - { - var relevantFields = def.Fields.Where( - f => !f.DiscValue.HasValue && - f.Type.Tag != TypeTag.Void && - f.DefaultValueIsExplicit && - !f.Type.IsValueType); - - foreach (var field in relevantFields) - { - var asmt = MakeApplyDefaultsMethodFieldAssignment(field); - - if (asmt != null) - { - yield return asmt; - } - } - } - - MemberDeclarationSyntax MakeSerializeMethod(TypeDefinition def) - { - return MethodDeclaration(PredefinedType( - Token(SyntaxKind.VoidKeyword)), - _names.SerializeMethod.Identifier) - .AddModifiers(Public) - .AddParameterListParameters( - Parameter(_names.WriterParameter.Identifier) - .WithType(_names.WriterStruct.IdentifierName)) - .AddBodyStatements(MakeSerializeStatements(def).ToArray()); - } - - MemberDeclarationSyntax MakeSerializeInterfaceMethod() - { - return MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), - Identifier(nameof(Capnp.ICapnpSerializable.Serialize))) - .WithExplicitInterfaceSpecifier( - ExplicitInterfaceSpecifier(IdentifierName(nameof(Capnp.ICapnpSerializable)))) - .AddParameterListParameters( - Parameter(_names.AnonymousParameter.Identifier) - .WithType(Type())) - .AddBodyStatements( - ExpressionStatement( - InvocationExpression(_names.SerializeMethod.IdentifierName) - .AddArgumentListArguments( - Argument( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.AnonymousParameter.IdentifierName, - GenericName(Identifier(nameof(Capnp.SerializerState.Rewrap))) - .AddTypeArgumentListArguments(_names.WriterStruct.IdentifierName))))))); - } - - MemberDeclarationSyntax MakeApplyDefaultsMethod(TypeDefinition def) - { - return MethodDeclaration(PredefinedType( - Token(SyntaxKind.VoidKeyword)), - _names.ApplyDefaultsMethod.Identifier) - .AddModifiers(Public) - .AddBodyStatements(MakeApplyDefaultsStatements(def).ToArray()); - } - - IEnumerable MakeDeserializeStatements(TypeDefinition def) - { - var relevantFields = def.Fields.Where( - f => !f.DiscValue.HasValue && - f.Type.Tag != TypeTag.Void); - - foreach (var field in relevantFields) - { - var rhs = MakeDeserializeMethodRightHandSide(field); - - if (rhs != null) - { - yield return ExpressionStatement(AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - _names.GetCodeIdentifier(field).IdentifierName, - rhs)); - } - } - } - - MemberDeclarationSyntax MakeDeserializeMethod(TypeDefinition def) - { - var stmts = new List(); - - stmts.Add(LocalDeclarationStatement( - VariableDeclaration(IdentifierName("var")) - .AddVariables( - VariableDeclarator(_names.ReaderParameter.Identifier) - .WithInitializer( - EqualsValueClause( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ReaderStruct.IdentifierName, - _names.ReaderCreateMethod.IdentifierName)) - .AddArgumentListArguments( - Argument(_names.AnonymousParameter.IdentifierName))))))); - - - if (def.UnionInfo != null) - { - stmts.Add(SwitchStatement( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ReaderParameter.IdentifierName, - _names.UnionDiscriminatorProp.IdentifierName)) - .WithOpenParenToken(Token(SyntaxKind.OpenParenToken)) - .WithCloseParenToken(Token(SyntaxKind.CloseParenToken)) - .AddSections(MakeDeserializeMethodSwitchSections(def).ToArray())); - } - - stmts.AddRange(MakeDeserializeStatements(def)); - stmts.Add(ExpressionStatement(InvocationExpression( - _names.ApplyDefaultsMethod.IdentifierName))); - - return MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), - Identifier(nameof(Capnp.ICapnpSerializable.Deserialize))) - .WithExplicitInterfaceSpecifier( - ExplicitInterfaceSpecifier(IdentifierName(nameof(Capnp.ICapnpSerializable)))) - .AddParameterListParameters( - Parameter(_names.AnonymousParameter.Identifier) - .WithType(Type())) - .AddBodyStatements(stmts.ToArray()); - } - - IEnumerable EnumerateDomainClassMembers(TypeDefinition def) - { - yield return MakeDeserializeMethod(def); - - if (def.UnionInfo != null) - { - yield return MakeUnionDiscriminatorField(); - yield return MakeUnionContentField(); - yield return MakeUnionDiscriminatorProperty(def); - } - - yield return MakeSerializeMethod(def); - yield return MakeSerializeInterfaceMethod(); - yield return MakeApplyDefaultsMethod(def); - - foreach (var field in def.Fields) - { - var decl = MakeField(field); - - if (decl != null) - yield return decl; - } - } - - public MemberDeclarationSyntax[] MakeDomainClassMembers(TypeDefinition def) - { - return EnumerateDomainClassMembers(def).ToArray(); - } - } -} diff --git a/capnpc-csharp/Generator/GenNames.cs b/capnpc-csharp/Generator/GenNames.cs deleted file mode 100644 index f842413..0000000 --- a/capnpc-csharp/Generator/GenNames.cs +++ /dev/null @@ -1,601 +0,0 @@ -using CapnpC.Model; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace CapnpC.Generator -{ - enum NameUsage - { - Default, - Interface, - Proxy, - Skeleton, - Namespace - } - - enum TypeUsage - { - NotRelevant, - DomainClass, - DomainClassNullable, - Reader, - Writer - } - - class GenNames - { - readonly Dictionary _fieldNameMap = new Dictionary(); - - public NameSyntax TopNamespace { get; set; } - public Name ReaderStruct { get; } - public Name ReaderParameter { get; } - public Name WriterParameter { get; } - public Name WriterStruct { get; } - public Name ReaderCreateMethod { get; } - public Name ReaderContextField { get; } - public Name ContextParameter { get; } - public Name GroupReaderContextArg { get; } - public Name GroupWriterContextArg { get; } - public Name UnionDiscriminatorEnum { get; } - public Name UnionDiscriminatorProp { get; } - public Name UnionDiscriminatorUndefined { get; } - public Name UnionDiscriminatorField { get; } - public Name UnionContentField { get; } - public Name AnonymousParameter { get; } - public Name CancellationTokenParameter { get; } - public Name ParamsLocal { get; } - public Name DeserializerLocal { get; } - public Name SerializerLocal { get; } - public Name ResultLocal { get; } - public Name SerializeMethod { get; } - public Name ApplyDefaultsMethod { get; } - public Name InstLocalName { get; } - public string ParamsStructFormat { get; } - public string ResultStructFormat { get; } - public string PropertyNamedLikeTypeRenameFormat { get; } - public string GenericTypeParameterFormat { get; } - public Name PipeliningExtensionsClassName { get; } - public string MemberAccessPathNameFormat { get; } - public Name TaskParameter { get; } - public Name EagerMethod { get; } - - public GenNames(GeneratorOptions options) - { - TopNamespace = new Name(options.TopNamespaceName).IdentifierName; - ReaderStruct = new Name(options.ReaderStructName); - WriterStruct = new Name(options.WriterStructName); - ReaderParameter = new Name(options.ReaderParameterName); - WriterParameter = new Name(options.WriterParameterName); - ReaderCreateMethod = new Name(options.ReaderCreateMethodName); - ReaderContextField = new Name(options.ReaderContextFieldName); - ContextParameter = new Name(options.ContextParameterName); - GroupReaderContextArg = new Name(options.GroupReaderContextArgName); - GroupWriterContextArg = new Name(options.GroupWriterContextArgName); - UnionDiscriminatorEnum = new Name(options.UnionDisciminatorEnumName); - UnionDiscriminatorProp = new Name(options.UnionDiscriminatorPropName); - UnionDiscriminatorUndefined = new Name(options.UnionDisciminatorUndefinedName); - UnionDiscriminatorField = new Name(options.UnionDiscriminatorFieldName); - UnionContentField = new Name(options.UnionContentFieldName); - SerializeMethod = new Name(options.SerializeMethodName); - ApplyDefaultsMethod = new Name(options.ApplyDefaultsMethodName); - AnonymousParameter = new Name(options.AnonymousParameterName); - CancellationTokenParameter = new Name(options.CancellationTokenParameterName); - ParamsLocal = new Name(options.ParamsLocalName); - DeserializerLocal = new Name(options.DeserializerLocalName); - SerializerLocal = new Name(options.SerializerLocalName); - ResultLocal = new Name(options.ResultLocalName); - InstLocalName = new Name(options.InstLocalName); - ParamsStructFormat = options.ParamsStructFormat; - ResultStructFormat = options.ResultStructFormat; - PropertyNamedLikeTypeRenameFormat = options.PropertyNamedLikeTypeRenameFormat; - GenericTypeParameterFormat = options.GenericTypeParameterFormat; - PipeliningExtensionsClassName = new Name(options.PipeliningExtensionsClassName); - MemberAccessPathNameFormat = options.MemberAccessPathNameFormat; - TaskParameter = new Name(options.TaskParameterName); - EagerMethod = new Name(options.EagerMethodName); - } - - public Name MakeTypeName(TypeDefinition def, NameUsage usage = NameUsage.Default) - { - if (def.Tag == TypeTag.Group) - { - return new Name(SyntaxHelpers.MakeAllLower(def.Name)); - } - else - { - string name; - - switch (usage) - { - case NameUsage.Default: - if (def.Tag == TypeTag.Interface) - goto case NameUsage.Interface; - - switch (def.SpecialName) - { - case SpecialName.NothingSpecial: - name = def.Name; - break; - - case SpecialName.MethodParamsStruct: - name = MakeParamsStructName(def.UsingMethod); - break; - - case SpecialName.MethodResultStruct: - name = MakeResultStructName(def.UsingMethod); - break; - - default: - throw new NotImplementedException(); - } - break; - - case NameUsage.Namespace: - name = def.Name; - break; - - case NameUsage.Interface: - name = "I" + def.Name; - break; - - case NameUsage.Proxy: - name = def.Name + "Proxy"; - break; - - case NameUsage.Skeleton: - name = def.Name + "Skeleton"; - break; - - default: - throw new NotImplementedException(); - } - - return new Name(name); - } - } - - public SimpleNameSyntax MakeGenericTypeName(TypeDefinition def, NameUsage usage = NameUsage.Default) - { - var name = MakeTypeName(def, usage); - - if (def.GenericParameters.Count > 0) - { - return GenericName(name.Identifier) - .AddTypeArgumentListArguments(def - .GenericParameters - .Select(p => GetGenericTypeParameter(p).IdentifierName).ToArray()); - } - else - { - return name.IdentifierName; - } - } - - TypeSyntax ResolveGenericParameter(GenericParameter p, Model.Type boundType, TypeDefinition def) - { - var type = boundType.ResolveGenericParameter(p); - return MakeTypeSyntax(type, def, TypeUsage.DomainClass); - } - - public SimpleNameSyntax MakeGenericTypeName(TypeDefinition def, Model.Type boundType, NameUsage usage = NameUsage.Default) - { - var name = MakeTypeName(def, usage); - - if (def.GenericParameters.Count > 0) - { - return GenericName(name.Identifier) - .AddTypeArgumentListArguments(def - .GetLocalTypeParameters() - .Select(p => ResolveGenericParameter(p, boundType, def)).ToArray()); - } - else - { - return name.IdentifierName; - } - } - - public SimpleNameSyntax MakeGenericTypeNameForAttribute(TypeDefinition def, NameUsage usage) - { - var name = MakeTypeName(def, usage); - - if (def.GenericParameters.Count > 0) - { - return GenericName(name.Identifier).AddTypeArgumentListArguments(); - } - else - { - return name.IdentifierName; - } - } - - public static NameSyntax NamespaceName(string[] @namespace) - { - NameSyntax ident = null; - if (@namespace != null) - { - ident = IdentifierName(SyntaxHelpers.MakeCamel(@namespace[0])); - foreach (string name in @namespace.Skip(1)) - { - var temp = IdentifierName(SyntaxHelpers.MakeCamel(name)); - ident = QualifiedName(ident, temp); - } - } - return ident; - } - - NameSyntax GetNamespaceFor(TypeDefinition def) => NamespaceName(def?.File?.Namespace); - - internal NameSyntax GetQName(Model.Type type, TypeDefinition scope) - { - // FIXME: With the help of the 'scope' parameter we will be able to generate abbreviated - // qualified names. Unfortunately the commented approach is too naive. It will fail if - // there are multiple objects with identical name up the hierarchy. We will need a more - // sophisticated algorithm. - - var scopeSet = new HashSet(); - //while (scope != null) - //{ - // scopeSet.Add(scope); - // scope = scope.DeclaringElement as TypeDefinition; - //} - - if (type.Definition != null) - { - var stack = new Stack(); - - var def = type.Definition; - stack.Push(MakeGenericTypeName(def, type, NameUsage.Default)); - - while (def.DeclaringElement is TypeDefinition pdef && !scopeSet.Contains(pdef)) - { - stack.Push(MakeGenericTypeName(pdef, type, NameUsage.Namespace)); - def = pdef; - } - - var qtype = - GetNamespaceFor(type.Definition) - ?? GetNamespaceFor(scope) - ?? TopNamespace; - - foreach (var name in stack) - { - qtype = QualifiedName(qtype, name); - } - - return qtype; - } - else - { - return GetGenericTypeParameter(type.Parameter.Name).IdentifierName; - } - } - - public TypeSyntax MakeListSerializerSyntax(Model.Type elementType, TypeDefinition scope) - { - switch (elementType.Tag) - { - case TypeTag.AnyPointer: - case TypeTag.StructPointer: - case TypeTag.ListPointer: - return SyntaxHelpers.Type>(); - - case TypeTag.CapabilityPointer: - return SyntaxHelpers.Type>(); - - case TypeTag.Data: - return SyntaxHelpers.Type>>(); - - case TypeTag.Enum: - return GenericName("ListOfPrimitivesSerializer") - .AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer)); - - case TypeTag.Group: - case TypeTag.Struct: - return GenericName("ListOfStructsSerializer") - .AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer)); - - case TypeTag.Interface: - return GenericName("ListOfCapsSerializer") - .AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer)); - - case TypeTag.List: - return GenericName("ListOfPointersSerializer") - .AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer)); - - case TypeTag.Text: - return SyntaxHelpers.Type(); - - case TypeTag.Void: - return SyntaxHelpers.Type(); - - case TypeTag.Bool: - return SyntaxHelpers.Type(); - - case TypeTag.F32: - return SyntaxHelpers.Type>(); - - case TypeTag.F64: - return SyntaxHelpers.Type>(); - - case TypeTag.S8: - return SyntaxHelpers.Type>(); - - case TypeTag.U8: - return SyntaxHelpers.Type>(); - - case TypeTag.S16: - return SyntaxHelpers.Type>(); - - case TypeTag.U16: - case TypeTag.AnyEnum: - return SyntaxHelpers.Type>(); - - case TypeTag.S32: - return SyntaxHelpers.Type>(); - - case TypeTag.U32: - return SyntaxHelpers.Type>(); - - case TypeTag.S64: - return SyntaxHelpers.Type>(); - - case TypeTag.U64: - return SyntaxHelpers.Type>(); - - default: - throw new NotImplementedException("Unexpected type tag, don't know how to deal with this"); - } - } - - TypeSyntax MaybeNullableValueType(TypeSyntax typeSyntax, TypeUsage usage) - { - switch (usage) - { - case TypeUsage.DomainClassNullable: - return NullableType(typeSyntax); - - default: - return typeSyntax; - } - } - - public TypeSyntax MakeTypeSyntax(Model.Type type, TypeDefinition scope, TypeUsage usage) - { - switch (type.Tag) - { - case TypeTag.AnyEnum: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); - - case TypeTag.CapabilityPointer: - if (type.Parameter != null) - { - return GetQName(type, scope); - } - else - { - return SyntaxHelpers.Type(); - } - - case TypeTag.AnyPointer: - case TypeTag.StructPointer: - switch (usage) - { - case TypeUsage.Reader: - return SyntaxHelpers.Type(); - - case TypeUsage.Writer: - return SyntaxHelpers.Type(); - - case TypeUsage.DomainClass: - case TypeUsage.DomainClassNullable: - if (type.Parameter != null) - { - return GetQName(type, scope); - } - else - { - return SyntaxHelpers.Type(); - } - - default: - throw new NotImplementedException(); - } - - case TypeTag.Bool: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); - - case TypeTag.Data: - switch (usage) - { - case TypeUsage.Reader: - case TypeUsage.DomainClass: - case TypeUsage.DomainClassNullable: - return SyntaxHelpers.Type>(); - - case TypeUsage.Writer: - return SyntaxHelpers.Type>(); - - default: - throw new NotImplementedException(); - } - - case TypeTag.Enum: - return MaybeNullableValueType(GetQName(type, scope), usage); - - case TypeTag.Interface: - return GetQName(type, scope); - - case TypeTag.Struct: - case TypeTag.Group: - switch (usage) - { - case TypeUsage.Writer: - return QualifiedName(GetQName(type, scope), WriterStruct.IdentifierName); - - case TypeUsage.Reader: - return QualifiedName(GetQName(type, scope), ReaderStruct.IdentifierName); - - case TypeUsage.DomainClass: - case TypeUsage.DomainClassNullable: - return GetQName(type, scope); - - default: - throw new NotImplementedException(); - } - - case TypeTag.F32: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); - - case TypeTag.F64: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); - - case TypeTag.List when type.ElementType.Tag == TypeTag.Void && usage != TypeUsage.Writer: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); - - case TypeTag.List: - switch (usage) - { - case TypeUsage.Writer: - return MakeListSerializerSyntax(type.ElementType, scope); - - case TypeUsage.Reader: - return GenericName(Identifier("IReadOnlyList")) - .AddTypeArgumentListArguments(MakeTypeSyntax(type.ElementType, scope, TypeUsage.Reader)); - - case TypeUsage.DomainClass: - case TypeUsage.DomainClassNullable: - return GenericName(Identifier("IReadOnlyList")) - .AddTypeArgumentListArguments(MakeTypeSyntax(type.ElementType, scope, TypeUsage.DomainClass)); - - default: - throw new NotImplementedException(); - } - - case TypeTag.ListPointer: - switch (usage) - { - case TypeUsage.Writer: - return SyntaxHelpers.Type(); - - case TypeUsage.Reader: - return SyntaxHelpers.Type>(); - - case TypeUsage.DomainClass: - case TypeUsage.DomainClassNullable: - return SyntaxHelpers.Type>(); - - default: - throw new NotImplementedException(); - } - - case TypeTag.S16: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); - - case TypeTag.S32: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); - - case TypeTag.S64: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); - - case TypeTag.S8: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); - - case TypeTag.Text: - return SyntaxHelpers.Type(); - - case TypeTag.U16: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); - - case TypeTag.U32: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); - - case TypeTag.U64: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); - - case TypeTag.U8: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); - - case TypeTag.Void: - return PredefinedType(Token(SyntaxKind.VoidKeyword)); - - default: - throw new NotImplementedException("Unexpected type tag, don't know how to deal with this"); - } - } - - public string MakeParamsStructName(Method method) - { - return string.Format(ParamsStructFormat, method.Name); - } - - public string MakeResultStructName(Method method) - { - return string.Format(ResultStructFormat, method.Name); - } - - public Name GetCodeIdentifier(Method method) - { - return new Name(SyntaxHelpers.MakeCamel(method.Name)); - } - - public Name GetCodeIdentifier(Field field) - { - if (_fieldNameMap.TryGetValue(field, out var name)) - { - return name; - } - - var def = field.DeclaringType; - - if (def == null) - { - // Method parameters are internally represented with the same class "Field". - // They do not have a declaring type. Anyway, they don't suffer from the field-name-equals-nested-type-name problem. - return new Name(SyntaxHelpers.MakeCamel(field.Name)); - } - - var typeNames = new HashSet(def.NestedTypes.Select(t => MakeTypeName(t))); - typeNames.Add(MakeTypeName(def)); - - foreach (var member in def.Fields) - { - var memberName = new Name(SyntaxHelpers.MakeCamel(member.Name)); - - while (typeNames.Contains(memberName)) - { - memberName = new Name(string.Format(PropertyNamedLikeTypeRenameFormat, memberName.ToString())); - } - - _fieldNameMap.Add(member, memberName); - } - - return _fieldNameMap[field]; - } - - public Name GetGenericTypeParameter(string name) - { - return new Name(string.Format(GenericTypeParameterFormat, name)); - } - - public Name MakePipeliningSupportExtensionMethodName(IReadOnlyList path) - { - if (path.Count == 1 && path[0].Offset == 0) - return EagerMethod; - else - return new Name(string.Join("_", path.Select(f => GetCodeIdentifier(f).ToString()))); - } - - public Name MakeMemberAccessPathFieldName(Method method, IReadOnlyList path) - { - return new Name(string.Format(MemberAccessPathNameFormat, - method.Name, - MakePipeliningSupportExtensionMethodName(path))); - } - } -} diff --git a/capnpc-csharp/Generator/GeneratorOptions.cs b/capnpc-csharp/Generator/GeneratorOptions.cs deleted file mode 100644 index 76faf93..0000000 --- a/capnpc-csharp/Generator/GeneratorOptions.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace CapnpC.Generator -{ - class GeneratorOptions - { - public string TopNamespaceName { get; set; } = "CapnpGen"; - public string ReaderStructName { get; set; } = "READER"; - public string WriterStructName { get; set; } = "WRITER"; - public string ReaderParameterName { get; set; } = "reader"; - public string WriterParameterName { get; set; } = "writer"; - public string ReaderCreateMethodName { get; set; } = "create"; - public string ReaderContextFieldName { get; set; } = "ctx"; - public string ContextParameterName { get; set; } = "ctx"; - public string GroupReaderContextArgName { get; set; } = "ctx"; - public string GroupWriterContextArgName { get; set; } = "ctx"; - public string UnionDisciminatorEnumName { get; set; } = "WHICH"; - public string UnionDiscriminatorPropName { get; set; } = "which"; - public string UnionDiscriminatorFieldName { get; set; } = "_which"; - public string UnionDisciminatorUndefinedName { get; set; } = "undefined"; - public string UnionContentFieldName { get; set; } = "_content"; - public string SerializeMethodName { get; set; } = "serialize"; - public string ApplyDefaultsMethodName { get; set; } = "applyDefaults"; - public string AnonymousParameterName { get; set; } = "arg_"; - public string CancellationTokenParameterName { get; set; } = "cancellationToken_"; - public string ParamsLocalName { get; set; } = "in_"; - public string DeserializerLocalName { get; set; } = "d_"; - public string SerializerLocalName { get; set; } = "s_"; - public string ResultLocalName { get; set; } = "r_"; - public string ParamsStructFormat { get; set; } = "Params_{0}"; - public string ResultStructFormat { get; set; } = "Result_{0}"; - public string PropertyNamedLikeTypeRenameFormat { get; set; } = "The{0}"; - public string InstLocalName { get; set; } = "inst"; - public string GenericTypeParameterFormat { get; set; } = "T{0}"; - public string PipeliningExtensionsClassName { get; set; } = "PipeliningSupportExtensions"; - public string MemberAccessPathNameFormat { get; set; } = "Path_{0}_{1}"; - public string TaskParameterName { get; set; } = "task"; - public string EagerMethodName { get; set; } = "Eager"; - } -} diff --git a/capnpc-csharp/Generator/InterfaceSnippetGen.cs b/capnpc-csharp/Generator/InterfaceSnippetGen.cs deleted file mode 100644 index f0adfaa..0000000 --- a/capnpc-csharp/Generator/InterfaceSnippetGen.cs +++ /dev/null @@ -1,844 +0,0 @@ -using CapnpC.Model; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static CapnpC.Generator.SyntaxHelpers; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Threading.Tasks; -using System.Threading; -using Microsoft.CodeAnalysis.CSharp; - -namespace CapnpC.Generator -{ - class InterfaceSnippetGen - { - readonly GenNames _names; - - public InterfaceSnippetGen(GenNames names) - { - _names = names; - } - - TypeSyntax TransformReturnType(Method method) - { - switch (method.Results.Count) - { - case 0: - return IdentifierName(nameof(Task)); - - case 1: - return GenericName(nameof(Task)).AddTypeArgumentListArguments( - _names.MakeTypeSyntax(method.Results[0].Type, method.DeclaringInterface, TypeUsage.DomainClass)); - - default: - return GenericName(nameof(Task)).AddTypeArgumentListArguments( - TupleType(SeparatedList( - method.Results.Select( - f => TupleElement(_names.MakeTypeSyntax(f.Type, method.DeclaringInterface, TypeUsage.DomainClass)))))); - } - } - - ParameterSyntax[] TransformParameters(Method method) - { - var list = new List(); - - if (method.Params.Count > 0) - { - var arg0 = method.Params[0]; - - if (arg0.Name == null) - { - list.Add(Parameter(_names.AnonymousParameter.Identifier) - .WithType(_names.MakeTypeSyntax(arg0.Type, method.DeclaringInterface, TypeUsage.DomainClass))); - } - else - { - foreach (var arg in method.Params) - { - list.Add(Parameter(Identifier(arg.Name)) - .WithType(_names.MakeTypeSyntax(arg.Type, method.DeclaringInterface, TypeUsage.DomainClass))); - } - } - } - - list.Add(Parameter(_names.CancellationTokenParameter.Identifier) - .WithType(IdentifierName(nameof(CancellationToken))) - .WithDefault(EqualsValueClause(LiteralExpression( - SyntaxKind.DefaultLiteralExpression, - Token(SyntaxKind.DefaultKeyword))))); - - return list.ToArray(); - } - - IEnumerable MakeTypeParameters(TypeDefinition def) - { - foreach (string name in def.GenericParameters) - { - yield return TypeParameter(_names.GetGenericTypeParameter(name).Identifier); - } - } - - IEnumerable MakeTypeParameterConstraints(TypeDefinition def) - { - foreach (string name in def.GenericParameters) - { - yield return TypeParameterConstraintClause( - _names.GetGenericTypeParameter(name).IdentifierName) - .AddConstraints(ClassOrStructConstraint(SyntaxKind.ClassConstraint)); - } - } - - public MemberDeclarationSyntax MakeInterface(TypeDefinition type) - { - var ifaceDecl = InterfaceDeclaration(_names.MakeTypeName(type, NameUsage.Interface).Identifier) - .AddModifiers(Public) - .AddAttributeLists( - AttributeList() - .AddAttributes( - Attribute(IdentifierName("Proxy")) - .AddArgumentListArguments( - AttributeArgument( - TypeOfExpression(_names.MakeGenericTypeNameForAttribute(type, NameUsage.Proxy)))), - Attribute(IdentifierName("Skeleton")) - .AddArgumentListArguments( - AttributeArgument( - TypeOfExpression(_names.MakeGenericTypeNameForAttribute(type, NameUsage.Skeleton)))))); - - if (type.GenericParameters.Count > 0) - { - ifaceDecl = ifaceDecl.AddTypeParameterListParameters(MakeTypeParameters(type).ToArray()); - } - - if (type.Superclasses.Count == 0) - { - ifaceDecl = ifaceDecl.AddBaseListTypes(SimpleBaseType(IdentifierName(nameof(IDisposable)))); - } - else - { - foreach (var superClass in type.Superclasses) - { - ifaceDecl = ifaceDecl.AddBaseListTypes( - SimpleBaseType(_names.MakeTypeSyntax( - superClass, type, - TypeUsage.NotRelevant))); - } - } - - foreach (var method in type.Methods) - { - var methodDecl = MethodDeclaration( - TransformReturnType(method), - _names.GetCodeIdentifier(method).Identifier) - .AddParameterListParameters(TransformParameters(method)) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); - - if (method.GenericParameters.Count > 0) - { - methodDecl = methodDecl - .AddTypeParameterListParameters(MakeTypeParameters(method).ToArray()) - .AddConstraintClauses(MakeTypeParameterConstraints(method).ToArray()); - - } - - ifaceDecl = ifaceDecl.AddMembers(methodDecl); - } - - return ifaceDecl; - } - - bool IsSubjectToPipelining(Model.Type type, HashSet visited) - { - if (!visited.Add(type)) - return false; - - switch (type.Tag) - { - case TypeTag.AnyPointer: - case TypeTag.CapabilityPointer: - case TypeTag.Interface: - case TypeTag.ListPointer: - case TypeTag.StructPointer: - return true; - - case TypeTag.List: - return IsSubjectToPipelining(type.ElementType, visited); - - case TypeTag.Struct: - return type.Fields.Any(f => IsSubjectToPipelining(f.Type, visited)); - - default: - return false; - } - } - - bool IsSubjectToPipelining(Method method) - { - return method.Results.Any(r => IsSubjectToPipelining(r.Type, new HashSet())); - } - - IEnumerable MakeProxyCallInitializerAssignments(Method method) - { - foreach (var methodParam in method.Params) - { - yield return AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - _names.GetCodeIdentifier(methodParam).IdentifierName, - IdentifierName(methodParam.Name)); - } - } - - IEnumerable MakeProxyReturnResultTupleElements(Method method) - { - foreach (var item in method.ResultStruct.Fields) - { - yield return Argument(MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ResultLocal.IdentifierName, - _names.GetCodeIdentifier(item).IdentifierName)); - } - } - - StatementSyntax MakeProxyReturnResult(Method method) - { - if (method.ResultStruct.Definition.SpecialName == SpecialName.MethodResultStruct) - { - if (method.ResultStruct.Fields.Count == 0) - { - return ReturnStatement(); - } - else - { - return ReturnStatement(TupleExpression() - .AddArguments(MakeProxyReturnResultTupleElements(method).ToArray())); - } - - } - else - { - return ReturnStatement(_names.ResultLocal.IdentifierName); - } - } - - StatementSyntax MakeProxyCreateResult(Method method) - { - var resultType = method.ResultStruct; - var domainType = _names.MakeTypeSyntax(resultType, method.DeclaringInterface, TypeUsage.DomainClass); - - var createDomain = InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(nameof(Capnp.CapnpSerializable)), - GenericName(nameof(Capnp.CapnpSerializable.Create)) - .AddTypeArgumentListArguments(domainType))) - .AddArgumentListArguments( - Argument(_names.DeserializerLocal.IdentifierName)); - - return LocalDeclarationStatement( - VariableDeclaration( - IdentifierName("var")) - .WithVariables( - SingletonSeparatedList( - VariableDeclarator( - _names.ResultLocal.Identifier) - .WithInitializer( - EqualsValueClause(createDomain))))); - } - - IEnumerable MakeTypeParameters(Method method) - { - foreach (string name in method.GenericParameters) - { - yield return TypeParameter(_names.GetGenericTypeParameter(name).Identifier); - } - } - - IEnumerable MakeTypeParameterConstraints(Method method) - { - foreach (string name in method.GenericParameters) - { - yield return TypeParameterConstraintClause( - _names.GetGenericTypeParameter(name).IdentifierName) - .AddConstraints(ClassOrStructConstraint(SyntaxKind.ClassConstraint)); - } - } - - public MemberDeclarationSyntax MakeProxy(TypeDefinition type) - { - var classDecl = ClassDeclaration(_names.MakeTypeName(type, NameUsage.Proxy).Identifier) - .AddModifiers(Public) - .AddBaseListTypes( - SimpleBaseType(Type()), - SimpleBaseType(_names.MakeGenericTypeName(type, NameUsage.Interface))); - - if (type.GenericParameters.Count > 0) - { - classDecl = classDecl - .AddTypeParameterListParameters(MakeTypeParameters(type).ToArray()) - .AddConstraintClauses(MakeTypeParameterConstraints(type).ToArray()); - } - - var allMethods = - from c in Types.FromDefinition(type).AllImplementedClasses - from m in c.Definition.Methods - select m; - - foreach (var method in allMethods) - { - var bodyStmts = new List(); - - bodyStmts.Add(LocalDeclarationStatement( - VariableDeclaration( - IdentifierName("var")) - .WithVariables( - SingletonSeparatedList( - VariableDeclarator( - _names.ParamsLocal.Identifier) - .WithInitializer( - EqualsValueClause( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(nameof(Capnp.SerializerState)), - GenericName( - Identifier(nameof(Capnp.SerializerState.CreateForRpc))) - .WithTypeArgumentList( - TypeArgumentList( - SingletonSeparatedList( - _names.MakeTypeSyntax( - method.ParamsStruct, - method.ParamsStruct.Definition, - TypeUsage.Writer)))))))))))); - - if (method.ParamsStruct.Definition.SpecialName == SpecialName.MethodParamsStruct) - { - bodyStmts.Add(LocalDeclarationStatement( - VariableDeclaration( - IdentifierName("var")) - .WithVariables( - SingletonSeparatedList( - VariableDeclarator( - _names.AnonymousParameter.Identifier) - .WithInitializer( - EqualsValueClause( - ObjectCreationExpression( - _names.MakeTypeSyntax( - method.ParamsStruct, - method.ParamsStruct.Definition, - TypeUsage.DomainClass)) - .WithArgumentList( - ArgumentList()) - .WithInitializer( - InitializerExpression( - SyntaxKind.ObjectInitializerExpression, - SeparatedList( - CommonSnippetGen.MakeCommaSeparatedList( - MakeProxyCallInitializerAssignments(method)).ToArray()))))))))); - } - - bodyStmts.Add(ExpressionStatement( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.AnonymousParameter.IdentifierName, - _names.SerializeMethod.IdentifierName)) - .AddArgumentListArguments( - Argument(_names.ParamsLocal.IdentifierName)))); - - var call = InvocationExpression(IdentifierName(nameof(Capnp.Rpc.BareProxy.Call))) - .AddArgumentListArguments( - Argument( - LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal(method.DeclaringInterface.Id))), - Argument( - LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(method.Id))), - Argument( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ParamsLocal.IdentifierName, - GenericName(nameof(Capnp.SerializerState.Rewrap)) - .AddTypeArgumentListArguments(Type()))) - .AddArgumentListArguments()), - Argument( - LiteralExpression(SyntaxKind.FalseLiteralExpression)), - Argument( - _names.CancellationTokenParameter.IdentifierName)); - - MethodDeclarationSyntax methodDecl; - - if (IsSubjectToPipelining(method)) - { - methodDecl = MethodDeclaration( - TransformReturnType(method), - _names.GetCodeIdentifier(method).Identifier) - .AddParameterListParameters(TransformParameters(method)) - .AddModifiers(Public); - - var pipelineAwareCall = InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(nameof(Capnp.Rpc.Impatient)), - IdentifierName(nameof(Capnp.Rpc.Impatient.MakePipelineAware)))) - .AddArgumentListArguments( - Argument(call), - Argument(SimpleLambdaExpression( - Parameter(_names.DeserializerLocal.Identifier), - Block( - MakeProxyCreateResult(method), - MakeProxyReturnResult(method))))); - - bodyStmts.Add(ReturnStatement(pipelineAwareCall)); - } - else - { - methodDecl = MethodDeclaration( - TransformReturnType(method), - _names.GetCodeIdentifier(method).Identifier) - .AddParameterListParameters(TransformParameters(method)) - .AddModifiers(Public, Token(SyntaxKind.AsyncKeyword)); - - var whenReturned = MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - call, - IdentifierName(nameof(Capnp.Rpc.IPromisedAnswer.WhenReturned))); - - var assignAwaited = LocalDeclarationStatement( - VariableDeclaration( - IdentifierName("var")) - .AddVariables( - VariableDeclarator( - _names.DeserializerLocal.Identifier) - .WithInitializer( - EqualsValueClause( - AwaitExpression(whenReturned))))); - - bodyStmts.Add(assignAwaited); - bodyStmts.Add(MakeProxyCreateResult(method)); - bodyStmts.Add(MakeProxyReturnResult(method)); - } - - if (method.GenericParameters.Count > 0) - { - methodDecl = methodDecl - .AddTypeParameterListParameters(MakeTypeParameters(method).ToArray()) - .AddConstraintClauses(MakeTypeParameterConstraints(method).ToArray()); - } - - methodDecl = methodDecl.AddBodyStatements(bodyStmts.ToArray()); - - classDecl = classDecl.AddMembers(methodDecl); - } - - return classDecl; - } - - IEnumerable MakeSkeletonSetMethodTableArguments(TypeDefinition def) - { - foreach (var method in def.Methods) - { - if (method.GenericParameters.Count > 0) - { - yield return Argument( - GenericName(_names.GetCodeIdentifier(method).ToString()) - .AddTypeArgumentListArguments( - Enumerable.Repeat( - Type(), - method.GenericParameters.Count).ToArray())); - } - else - { - yield return Argument(_names.GetCodeIdentifier(method).IdentifierName); - } - } - } - - IEnumerable MakeSkeletonMethodResultStructInitializer(Method method) - { - foreach (var arg in method.Results) - { - yield return AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - _names.GetCodeIdentifier(arg).IdentifierName, - IdentifierName(arg.Name)); - } - } - - IEnumerable MakeSkeletonMethodCallArgs(Method method) - { - foreach (var arg in method.ParamsStruct.Fields) - { - yield return Argument( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ParamsLocal.IdentifierName, - _names.GetCodeIdentifier(arg).IdentifierName)); - } - } - - StatementSyntax MakeSkeletonMethodSerializerLocalDeclaration(Method method) - { - return LocalDeclarationStatement( - VariableDeclaration( - IdentifierName("var")) - .WithVariables( - SingletonSeparatedList( - VariableDeclarator( - _names.SerializerLocal.Identifier) - .WithInitializer( - EqualsValueClause( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(nameof(Capnp.SerializerState)), - GenericName( - Identifier(nameof(Capnp.SerializerState.CreateForRpc))) - .WithTypeArgumentList( - TypeArgumentList( - SingletonSeparatedList( - _names.MakeTypeSyntax( - method.ResultStruct, - method.ResultStruct.Definition, - TypeUsage.Writer))))))))))); - - } - - CSharpSyntaxNode MakeMaybeTailCallLambdaBody(Method method) - { - var block = Block( - MakeSkeletonMethodSerializerLocalDeclaration(method)); - - if (method.ResultStruct.Definition.SpecialName == SpecialName.MethodResultStruct) - { - block = block.AddStatements( - LocalDeclarationStatement( - VariableDeclaration( - IdentifierName("var")) - .AddVariables( - VariableDeclarator(_names.ResultLocal.Identifier) - .WithInitializer(EqualsValueClause(ObjectCreationExpression( - _names.MakeTypeSyntax( - method.ResultStruct, - method.ResultStruct.Definition, - TypeUsage.DomainClass)) - .WithInitializer( - InitializerExpression(SyntaxKind.ObjectInitializerExpression) - .AddExpressions( - MakeSkeletonMethodResultStructInitializer(method).ToArray()))))))); - } - - if (method.Results.Count > 0) - { - block = block.AddStatements( - ExpressionStatement( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ResultLocal.IdentifierName, - _names.SerializeMethod.IdentifierName)) - .AddArgumentListArguments( - Argument(_names.SerializerLocal.IdentifierName)))); - } - - block = block.AddStatements( - ReturnStatement(_names.SerializerLocal.IdentifierName)); - - return block; - } - - IEnumerable MakeSkeletonMethodBody(Method method) - { - var call = InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(SkeletonWorder.ImplName), - _names.GetCodeIdentifier(method).IdentifierName)); - - if (method.Params.Count > 0) - { - var paramsType = method.ParamsStruct; - var domainType = _names.MakeTypeSyntax(paramsType, method.ParamsStruct.Definition, TypeUsage.DomainClass); - - var createDomain = InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(nameof(Capnp.CapnpSerializable)), - GenericName(nameof(Capnp.CapnpSerializable.Create)) - .AddTypeArgumentListArguments(domainType))) - .AddArgumentListArguments( - Argument(_names.DeserializerLocal.IdentifierName)); - - if (method.ParamsStruct.Definition.SpecialName == SpecialName.MethodParamsStruct) - { - yield return LocalDeclarationStatement( - VariableDeclaration( - IdentifierName("var")) - .AddVariables( - VariableDeclarator(_names.ParamsLocal.Identifier) - .WithInitializer(EqualsValueClause(createDomain)))); - - call = call.AddArgumentListArguments( - MakeSkeletonMethodCallArgs(method).ToArray()); - } - else - { - call = call.AddArgumentListArguments( - Argument(createDomain)); - } - } - - call = call.AddArgumentListArguments( - Argument( - _names.CancellationTokenParameter.IdentifierName)); - - if (method.Results.Count == 0) - { - var awaitCall = AwaitExpression(call); - yield return ExpressionStatement(awaitCall); - yield return MakeSkeletonMethodSerializerLocalDeclaration(method); - yield return ReturnStatement(_names.SerializerLocal.IdentifierName); - } - else - { - ExpressionSyntax lambdaArg; - - if (method.ResultStruct.Definition.SpecialName == SpecialName.MethodResultStruct) - { - if (method.Results.Count == 1) - { - lambdaArg = SimpleLambdaExpression( - Parameter(Identifier(method.Results.Single().Name)), - MakeMaybeTailCallLambdaBody(method)); - } - else - { - lambdaArg = ParenthesizedLambdaExpression( - MakeMaybeTailCallLambdaBody(method)) - .AddParameterListParameters( - method.Results.Select(arg => Parameter(Identifier(arg.Name))).ToArray()); - } - } - else - { - lambdaArg = SimpleLambdaExpression( - Parameter(_names.ResultLocal.Identifier), - MakeMaybeTailCallLambdaBody(method)); - - } - - var maybeTailCall = InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(nameof(Capnp.Rpc.Impatient)), - IdentifierName(nameof(Capnp.Rpc.Impatient.MaybeTailCall)))) - .AddArgumentListArguments( - Argument(call), - Argument(lambdaArg)); - - yield return ReturnStatement(maybeTailCall); - } - } - - IEnumerable MakeSkeletonMethods(TypeDefinition def) - { - foreach (var method in def.Methods) - { - var methodDecl = MethodDeclaration( - Type>(), - _names.GetCodeIdentifier(method).Identifier) - .AddParameterListParameters( - Parameter(_names.DeserializerLocal.Identifier) - .WithType(Type()), - Parameter(_names.CancellationTokenParameter.Identifier) - .WithType(Type())) - .AddBodyStatements( - MakeSkeletonMethodBody(method).ToArray()); - - if (method.Results.Count == 0) - { - methodDecl = methodDecl.AddModifiers(Async); - } - - if (method.GenericParameters.Count > 0) - { - methodDecl = methodDecl - .AddTypeParameterListParameters(MakeTypeParameters(method).ToArray()) - .AddConstraintClauses(MakeTypeParameterConstraints(method).ToArray()); - } - - yield return methodDecl; - } - } - - public MemberDeclarationSyntax MakeSkeleton(TypeDefinition type) - { - var name = _names.MakeTypeName(type, NameUsage.Skeleton).Identifier; - var classDecl = ClassDeclaration(name) - .AddModifiers(Public) - .AddBaseListTypes( - SimpleBaseType( - GenericName(nameof(Capnp.Rpc.Skeleton)) - .AddTypeArgumentListArguments( - _names.MakeGenericTypeName(type, NameUsage.Interface)))) - .AddMembers( - // C'tor - ConstructorDeclaration(name) - .AddModifiers(Public) - .AddBodyStatements( - ExpressionStatement( - InvocationExpression( - IdentifierName(SkeletonWorder.SetMethodTableName)) - .AddArgumentListArguments( - MakeSkeletonSetMethodTableArguments(type).ToArray()))), - // InterfaceId - PropertyDeclaration(Type(), nameof(Capnp.Rpc.Skeleton.InterfaceId)) - .AddModifiers(Public, Override) - .WithExpressionBody( - ArrowExpressionClause( - ValueOf(type.Id))) - .WithSemicolonToken( - Token(SyntaxKind.SemicolonToken))); - - if (type.GenericParameters.Count > 0) - { - classDecl = classDecl - .AddTypeParameterListParameters(MakeTypeParameters(type).ToArray()) - .AddConstraintClauses(MakeTypeParameterConstraints(type).ToArray()); - } - - classDecl = classDecl.AddMembers(MakeSkeletonMethods(type).ToArray()); - - return classDecl; - } - - public bool RequiresPipeliningSupport(TypeDefinition type) - { - return type.Methods.Any(m => ExpandPipeliningPaths(m).Any()); - } - - IEnumerable> ExpandPipeliningPaths(Method method) - { - var stack = new Stack>(); - foreach (var field in method.ResultStruct.Fields) - { - stack.Push(new List() { field }); - } - - while (stack.Count > 0) - { - var path = stack.Pop(); - var last = path[path.Count - 1]; - - switch (last.Type.Tag) - { - case TypeTag.Interface: - case TypeTag.CapabilityPointer: - yield return path; - break; - - case TypeTag.Struct: - foreach (var field in last.Type.Fields) - { - if (path.Contains(field)) - { - // Recursive structs protection - continue; - } - - var copy = new List(); - copy.AddRange(path); - copy.Add(field); - stack.Push(copy); - } - break; - } - } - } - - readonly HashSet<(string, string)> _existingExtensionMethods = new HashSet<(string, string)>(); - - public MemberDeclarationSyntax MakePipeliningSupport(TypeDefinition type) - { - var classDecl = ClassDeclaration(_names.PipeliningExtensionsClassName.Identifier) - .AddModifiers(Public, Static, Partial); - - foreach (var method in type.Methods) - { - foreach (var path in ExpandPipeliningPaths(method)) - { - var accessPath = _names.MakeMemberAccessPathFieldName(method, path); - var methodName = _names.MakePipeliningSupportExtensionMethodName(path); - var capType = path[path.Count - 1].Type; - var capTypeSyntax = _names.MakeTypeSyntax(capType, null, TypeUsage.DomainClass); - - if (!_existingExtensionMethods.Add((capTypeSyntax.ToString(), methodName.ToString()))) - { - continue; - } - - var pathDecl = FieldDeclaration( - VariableDeclaration( - IdentifierName(nameof(Capnp.Rpc.MemberAccessPath))) - .AddVariables( - VariableDeclarator( - accessPath.Identifier) - .WithInitializer( - EqualsValueClause( - ObjectCreationExpression( - IdentifierName(nameof(Capnp.Rpc.MemberAccessPath))) - .AddArgumentListArguments( - path.Select( - f => Argument( - LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal(f.Offset)))).ToArray()))))) - .AddModifiers(Static, Readonly); - - - var methodDecl = MethodDeclaration( - capTypeSyntax, - methodName.Identifier) - .AddModifiers(Public, Static) - .AddParameterListParameters( - Parameter( - _names.TaskParameter.Identifier) - .AddModifiers(This) - .WithType(TransformReturnType(method))) - .AddBodyStatements( - ReturnStatement( - CastExpression( - capTypeSyntax, - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(nameof(Capnp.Rpc.CapabilityReflection)), - GenericName( - Identifier(nameof(Capnp.Rpc.CapabilityReflection.CreateProxy))) - .AddTypeArgumentListArguments( - capTypeSyntax))) - .AddArgumentListArguments( - Argument( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(nameof(Capnp.Rpc.Impatient)), - IdentifierName(nameof(Capnp.Rpc.Impatient.GetAnswer)))) - .AddArgumentListArguments( - Argument( - _names.TaskParameter.IdentifierName)), - IdentifierName(nameof(Capnp.Rpc.IPromisedAnswer.Access)))) - .AddArgumentListArguments( - Argument( - accessPath.IdentifierName))))))); - - classDecl = classDecl.AddMembers(pathDecl, methodDecl); - } - } - - return classDecl; - } - } -} diff --git a/capnpc-csharp/Generator/Name.cs b/capnpc-csharp/Generator/Name.cs deleted file mode 100644 index f85f324..0000000 --- a/capnpc-csharp/Generator/Name.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using System; -using System.Collections.Generic; -using System.Text; - -namespace CapnpC.Generator -{ - class Name - { - readonly string _name; - - public Name(string name) - { - _name = name ?? throw new ArgumentNullException(nameof(name)); - IdentifierName = SyntaxFactory.IdentifierName(_name); - Identifier = SyntaxFactory.Identifier(_name); - VariableDeclarator = SyntaxFactory.VariableDeclarator(_name); - } - - public IdentifierNameSyntax IdentifierName { get; } - public SyntaxToken Identifier { get; } - public VariableDeclaratorSyntax VariableDeclarator { get; } - - public override string ToString() => _name; - - public override bool Equals(object obj) - { - return obj is Name other && _name == other._name; - } - - public override int GetHashCode() => _name.GetHashCode(); - } -} diff --git a/capnpc-csharp/Generator/ReaderSnippetGen.cs b/capnpc-csharp/Generator/ReaderSnippetGen.cs deleted file mode 100644 index 9d57038..0000000 --- a/capnpc-csharp/Generator/ReaderSnippetGen.cs +++ /dev/null @@ -1,715 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using CapnpC.Model; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static CapnpC.Generator.SyntaxHelpers; - -namespace CapnpC.Generator -{ - class ReaderSnippetGen - { - readonly GenNames _names; - - public ReaderSnippetGen(GenNames names) - { - _names = names; - } - - MemberDeclarationSyntax MakeReaderImplicitConversionOperator1() - { - return ConversionOperatorDeclaration( - Token(SyntaxKind.ImplicitKeyword), - IdentifierName(nameof(Capnp.DeserializerState))) - .WithModifiers( - TokenList( - new[]{ - Token(SyntaxKind.PublicKeyword), - Token(SyntaxKind.StaticKeyword)})) - .WithParameterList( - ParameterList( - SingletonSeparatedList( - Parameter(_names.ReaderParameter.Identifier) - .WithType(_names.ReaderStruct.IdentifierName)))) - .WithExpressionBody( - ArrowExpressionClause( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ReaderParameter.IdentifierName, - _names.ReaderContextField.IdentifierName))) - .WithSemicolonToken( - Token(SyntaxKind.SemicolonToken)); - } - - MemberDeclarationSyntax MakeReaderImplicitConversionOperator2() - { - return ConversionOperatorDeclaration( - Token(SyntaxKind.ImplicitKeyword), - _names.ReaderStruct.IdentifierName) - .WithModifiers( - TokenList( - new[] { - Token(SyntaxKind.PublicKeyword), - Token(SyntaxKind.StaticKeyword) })) - .WithParameterList( - ParameterList( - SingletonSeparatedList( - Parameter(_names.ReaderContextField.Identifier) - .WithType(Type())))) - .WithExpressionBody( - ArrowExpressionClause( - ObjectCreationExpression(_names.ReaderStruct.IdentifierName) - .WithArgumentList( - ArgumentList( - SingletonSeparatedList( - Argument(_names.ReaderContextField.IdentifierName)))))) - .WithSemicolonToken( - Token(SyntaxKind.SemicolonToken)); - } - - MemberDeclarationSyntax MakeReaderCreateMethod() - { - return MethodDeclaration(_names.ReaderStruct.IdentifierName, _names.ReaderCreateMethod.Identifier) - .AddModifiers(Public, Static) - .WithParameterList( - ParameterList( - SingletonSeparatedList( - Parameter(_names.ContextParameter.Identifier) - .WithType( - Type())))) - .WithExpressionBody( - ArrowExpressionClause( - ObjectCreationExpression(_names.ReaderStruct.IdentifierName) - .AddArgumentListArguments(Argument(_names.ContextParameter.IdentifierName)))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); - } - - IEnumerable MakeReaderStructMembers() - { - yield return FieldDeclaration( - VariableDeclaration( - Type()) - .AddVariables(_names.ReaderContextField.VariableDeclarator)) - .AddModifiers(Readonly); - - yield return ConstructorDeclaration(_names.ReaderStruct.Identifier) - .AddModifiers(Public) - .WithParameterList( - ParameterList( - SingletonSeparatedList( - Parameter(_names.ContextParameter.Identifier) - .WithType(Type())))) - .WithBody( - Block( - SingletonList( - ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - ThisExpression(), - _names.ReaderContextField.IdentifierName), - _names.ContextParameter.IdentifierName))))); - - yield return MakeReaderCreateMethod(); - yield return MakeReaderImplicitConversionOperator1(); - yield return MakeReaderImplicitConversionOperator2(); - } - - IEnumerable MakeGroupReaderStructMembers() - { - yield return FieldDeclaration( - VariableDeclaration( - Type()) - .AddVariables(_names.ReaderContextField.VariableDeclarator)) - .AddModifiers(Readonly); - - yield return ConstructorDeclaration(_names.ReaderStruct.Identifier) - .AddModifiers(Public) - .WithParameterList( - ParameterList( - SingletonSeparatedList(Parameter(_names.GroupReaderContextArg.Identifier) - .WithType(Type())))) - .WithBody( - Block( - SingletonList( - ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - ThisExpression(), - _names.ReaderContextField.IdentifierName), - _names.GroupReaderContextArg.IdentifierName))))); - - yield return MakeReaderCreateMethod(); - yield return MakeReaderImplicitConversionOperator1(); - yield return MakeReaderImplicitConversionOperator2(); - } - - PropertyDeclarationSyntax MakeReaderProperty(TypeSyntax type, string name, ExpressionSyntax right, bool cond) - { - if (cond) - { - right = ConditionalExpression( - BinaryExpression( - SyntaxKind.EqualsExpression, - _names.UnionDiscriminatorProp.IdentifierName, - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.UnionDiscriminatorEnum.IdentifierName, - IdentifierName(name))), - right, - LiteralExpression( - SyntaxKind.DefaultLiteralExpression, - Token(SyntaxKind.DefaultKeyword))); - } - - return PropertyDeclaration(type, name) - .AddModifiers(Public) - .WithExpressionBody(ArrowExpressionClause(right)) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); - } - - static Func MakeCastFunc(TypeSyntax type) => - x => CastExpression(type, x); - - static Func MakeListCastFunc(string castName, Field field) - { - // Insight: List may have complex default values (e.g. [true, false, false, true] as a - // valid default value for a list of bools. This does not yet fit the author's mindset. - - //if (field.DefaultValueIsExplicit) - //{ - // return x => InvocationExpression( - // MemberAccessExpression( - // SyntaxKind.SimpleMemberAccessExpression, - // x, - // IdentifierName(castName)) - // ) - // .AddArgumentListArguments( - // Argument(ValueOf(field.DefaultValue))); - //} - //else - - { - return x => InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - x, - IdentifierName(castName)) - ); - } - } - - static Func MakeListCastFuncWithCons( - string castName, ExpressionSyntax cons) - { - return x => InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - x, - IdentifierName(castName)) - ).AddArgumentListArguments(Argument(cons)); - } - - static Func MakeGenericListCastFunc(string castName, TypeSyntax genericArgument) - { - return x => InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - x, - GenericName(castName).AddTypeArgumentListArguments(genericArgument)) - ); - } - - PropertyDeclarationSyntax MakeReadProperty(TypeSyntax type, string name, SimpleNameSyntax readName, - object indexOrBitOffset, ExpressionSyntax secondArg, - Func cast, bool cond) - { - var right = InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ReaderContextField.IdentifierName, - readName)) - .AddArgumentListArguments( - Argument(ValueOf(indexOrBitOffset))); - - if (secondArg != null) - { - right = right.AddArgumentListArguments(Argument(secondArg)); - } - - ExpressionSyntax expr = right; - - if (cast != null) - { - expr = cast(expr); - } - - return MakeReaderProperty(type, name, expr, cond); - } - - PropertyDeclarationSyntax MakeReadProperty(TypeSyntax type, string name, string readName, - object indexOrBitOffset, ExpressionSyntax secondArg, - Func cast, bool cond) - { - return MakeReadProperty(type, name, IdentifierName(readName), indexOrBitOffset, secondArg, cast, cond); - } - - PropertyDeclarationSyntax MakeReadPrimitiveProperty(Field field, string readName) - { - return MakeReadProperty(Type(), _names.GetCodeIdentifier(field).ToString(), readName, field.BitOffset.Value, - ValueOf(field.DefaultValue.ScalarValue), null, field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakeReadEnumProperty(Field field) - { - var typeSyntax = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader); - return MakeReadProperty(typeSyntax, - _names.GetCodeIdentifier(field).ToString(), - nameof(Capnp.SerializerExtensions.ReadDataUShort), field.BitOffset.Value, - ValueOf(field.DefaultValue.ScalarValue), - x => CastExpression(typeSyntax, x), - field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakeReadTextProperty(Field field) - { - return MakeReadProperty(Type(), _names.GetCodeIdentifier(field).ToString(), - nameof(Capnp.DeserializerState.ReadText), (int)field.Offset, - ValueOf(field.DefaultValue.ScalarValue), null, field.DiscValue.HasValue); - } - - MemberAccessExpressionSyntax MakeReaderCreator(TypeSyntax qtype) - { - return MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - qtype, - _names.ReaderCreateMethod.IdentifierName); - } - - PropertyDeclarationSyntax MakeReadStructProperty(Field field) - { - var qtype = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader); - var creator = MakeReaderCreator(qtype); - - return MakeReadProperty(qtype, _names.GetCodeIdentifier(field).ToString(), - nameof(Capnp.DeserializerState.ReadStruct), (int)field.Offset, - creator, null, field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakeReadGroupProperty(Field field) - { - var type = QualifiedName( - _names.MakeTypeName(field.Type.Definition).IdentifierName, - _names.ReaderStruct.IdentifierName); - - var right = ObjectCreationExpression(type) - .WithArgumentList( - ArgumentList( - SingletonSeparatedList( - Argument(_names.ReaderContextField.IdentifierName)))); - - return MakeReaderProperty(type, _names.GetCodeIdentifier(field).ToString(), right, field.DiscValue.HasValue); - } - - void MakeReadListPropertyImpl(Model.Type elementType, TypeDefinition scope, ExpressionSyntax context, int depth, - out TypeSyntax listType, out ExpressionSyntax impl) - { - var elementTypeSyntax = _names.MakeTypeSyntax(elementType, scope, TypeUsage.Reader); - listType = GenericName("IReadOnlyList").AddTypeArgumentListArguments(elementTypeSyntax); - - if (elementType.Tag == TypeTag.Interface || - elementType.Tag == TypeTag.CapabilityPointer) - { - if (depth == 0) - { - impl = InvocationExpression(MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ReaderContextField.IdentifierName, - GenericName(nameof(Capnp.DeserializerState.ReadCapList)) - .AddTypeArgumentListArguments(elementTypeSyntax) - )).AddArgumentListArguments(Argument(context)); - } - else - { - impl = InvocationExpression( - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - context, - GenericName(nameof(Capnp.DeserializerState.RequireCapList)) - .AddTypeArgumentListArguments(elementTypeSyntax) - )); - } - - return; - } - - if (depth == 0) - { - context = InvocationExpression(MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ReaderContextField.IdentifierName, - IdentifierName(nameof(Capnp.DeserializerState.ReadList)))) - .AddArgumentListArguments(Argument(context)); - } - else - { - context = InvocationExpression( - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - context, - IdentifierName(nameof(Capnp.DeserializerState.RequireList)) - )); - } - - string lambdaParamName = "_" + depth; - var lambdaParam = Parameter(Identifier(lambdaParamName)); - var lambdaArg = IdentifierName(lambdaParamName); - string castFuncName; - - switch (elementType.Tag) - { - case TypeTag.List: - { - - MakeReadListPropertyImpl( - elementType.ElementType, - scope, - lambdaArg, - depth + 1, - out var innerListType, - out var innerImpl); - - listType = GenericName("IReadOnlyList").AddTypeArgumentListArguments(innerListType); - - impl = InvocationExpression( - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - context, - IdentifierName(nameof(Capnp.ListDeserializer.Cast)))) - .AddArgumentListArguments( - Argument(SimpleLambdaExpression(lambdaParam, innerImpl))); - - return; - } - - case TypeTag.ListPointer: - { - listType = Type>(); - - context = InvocationExpression(MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - context, - IdentifierName(nameof(Capnp.DeserializerState.RequireList)) - )).AddArgumentListArguments(Argument(lambdaArg)); - - impl = InvocationExpression( - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - context, - IdentifierName(nameof(Capnp.ReadOnlyListExtensions.LazyListSelect)))) - .AddArgumentListArguments( - Argument(SimpleLambdaExpression(lambdaParam, context))); - - return; - } - - case TypeTag.Struct: - { - impl = InvocationExpression( - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - context, - IdentifierName(nameof(Capnp.ListDeserializer.Cast)))) - .AddArgumentListArguments( - Argument(MakeReaderCreator(elementTypeSyntax))); - - return; - } - - case TypeTag.Enum: - { - var cons = SimpleLambdaExpression( - lambdaParam, - CastExpression(elementTypeSyntax, lambdaArg)); - - impl = InvocationExpression( - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - context, - IdentifierName(nameof(Capnp.ListDeserializer.CastEnums)))) - .AddArgumentListArguments( - Argument(cons)); - - return; - } - - case TypeTag.AnyPointer: - case TypeTag.StructPointer: - { - listType = Type>(); - impl = context; - return; - } - - case TypeTag.Void: - { - listType = Type(); - impl = MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - context, - IdentifierName(nameof(Capnp.ListDeserializer.Count))); - return; - } - - case TypeTag.Data: - castFuncName = nameof(Capnp.ListDeserializer.CastData); - break; - - case TypeTag.Text: - castFuncName = nameof(Capnp.ListDeserializer.CastText2); - break; - - case TypeTag.Bool: - castFuncName = nameof(Capnp.ListDeserializer.CastBool); - break; - - case TypeTag.F32: - castFuncName = nameof(Capnp.ListDeserializer.CastFloat); - break; - - case TypeTag.F64: - castFuncName = nameof(Capnp.ListDeserializer.CastDouble); - break; - - case TypeTag.S8: - castFuncName = nameof(Capnp.ListDeserializer.CastSByte); - break; - - case TypeTag.U8: - castFuncName = nameof(Capnp.ListDeserializer.CastByte); - break; - - case TypeTag.S16: - castFuncName = nameof(Capnp.ListDeserializer.CastShort); - break; - - case TypeTag.U16: - case TypeTag.AnyEnum: - castFuncName = nameof(Capnp.ListDeserializer.CastUShort); - break; - - case TypeTag.S32: - castFuncName = nameof(Capnp.ListDeserializer.CastInt); - break; - - case TypeTag.U32: - castFuncName = nameof(Capnp.ListDeserializer.CastUInt); - break; - - case TypeTag.S64: - castFuncName = nameof(Capnp.ListDeserializer.CastLong); - break; - - case TypeTag.U64: - castFuncName = nameof(Capnp.ListDeserializer.CastULong); - break; - - default: - throw new NotImplementedException("Unexpected type tag, don't know how to deal with this"); - } - - impl = InvocationExpression(MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - context, - IdentifierName(castFuncName))); - } - - PropertyDeclarationSyntax MakeReadListProperty(Field field) - { - var elementType = field.Type.ElementType; - var context = ValueOf((int)field.Offset); - MakeReadListPropertyImpl(elementType, field.DeclaringType, context, 0, out var listType, out var impl); - return MakeReaderProperty(listType, _names.GetCodeIdentifier(field).ToString(), impl, field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakeReadAnyListProperty(Field field) - { - var type = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader); - - return MakeReadProperty(type, _names.GetCodeIdentifier(field).ToString(), - nameof(Capnp.DeserializerState.ReadList), - (int)field.Offset, null, x => CastExpression(type, x), field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakeReadCapProperty(Field field) - { - var type = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader); - var readName = GenericName(nameof(Capnp.DeserializerState.ReadCap)) - .AddTypeArgumentListArguments(type); - - return MakeReadProperty(type, _names.GetCodeIdentifier(field).ToString(), - readName, - (int)field.Offset, null, null, field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakeReadAnyCapProperty(Field field) - { - var type = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader); - - return MakeReadProperty(type, _names.GetCodeIdentifier(field).ToString(), - nameof(Capnp.DeserializerState.ReadCap), - (int)field.Offset, null, null, field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakeReadDataProperty(Field field) - { - var context = InvocationExpression(MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.ReaderContextField.IdentifierName, - IdentifierName(nameof(Capnp.DeserializerState.ReadList)))) - .AddArgumentListArguments(Argument(ValueOf((int)field.Offset))); - var impl = InvocationExpression(MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - context, - IdentifierName(nameof(Capnp.ListDeserializer.CastByte)))); - - return MakeReaderProperty( - _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Reader), - _names.GetCodeIdentifier(field).ToString(), impl, field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakeReadAnyPointerProperty(Field field) - { - var type = IdentifierName(nameof(Capnp.DeserializerState)); - - return MakeReadProperty(type, _names.GetCodeIdentifier(field).ToString(), - nameof(Capnp.DeserializerState.StructReadPointer), - (int)field.Offset, null, null, field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakeReaderUnionSelector(TypeDefinition def) - { - var type = _names.UnionDiscriminatorEnum.IdentifierName; - return MakeReadProperty( - type, - _names.UnionDiscriminatorProp.ToString(), - nameof(Capnp.SerializerExtensions.ReadDataUShort), - def.UnionInfo.TagOffset, - ValueOf(default(ushort)), - MakeCastFunc(type), false); - } - - PropertyDeclarationSyntax MakeReaderFieldProperty(Field field) - { - switch (field.Type.Tag) - { - case TypeTag.Bool: - return MakeReadPrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataBool)); - - case TypeTag.S8: - return MakeReadPrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataSByte)); - - case TypeTag.U8: - return MakeReadPrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataByte)); - - case TypeTag.S16: - return MakeReadPrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataShort)); - - case TypeTag.U16: - return MakeReadPrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataUShort)); - - case TypeTag.S32: - return MakeReadPrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataInt)); - - case TypeTag.U32: - return MakeReadPrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataUInt)); - - case TypeTag.S64: - return MakeReadPrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataLong)); - - case TypeTag.U64: - return MakeReadPrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataULong)); - - case TypeTag.F32: - return MakeReadPrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataFloat)); - - case TypeTag.F64: - return MakeReadPrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataDouble)); - - case TypeTag.Enum: - return MakeReadEnumProperty(field); - - case TypeTag.Text: - return MakeReadTextProperty(field); - - case TypeTag.Struct: - return MakeReadStructProperty(field); - - case TypeTag.Group: - return MakeReadGroupProperty(field); - - case TypeTag.List: - return MakeReadListProperty(field); - - case TypeTag.Interface: - return MakeReadCapProperty(field); - - case TypeTag.CapabilityPointer: - return MakeReadAnyCapProperty(field); - - case TypeTag.ListPointer: - return MakeReadAnyListProperty(field); - - case TypeTag.AnyPointer: - case TypeTag.StructPointer: - return MakeReadAnyPointerProperty(field); - - case TypeTag.Data: - return MakeReadDataProperty(field); - - default: - return null; - } - } - - public StructDeclarationSyntax MakeReaderStruct(TypeDefinition def) - { - var readerDecl = StructDeclaration(_names.ReaderStruct.ToString()).AddModifiers(Public); - - var members = def.Tag == TypeTag.Group ? - MakeGroupReaderStructMembers() : - MakeReaderStructMembers(); - - readerDecl = readerDecl.AddMembers(members.ToArray()); - - if (def.UnionInfo != null) - { - readerDecl = readerDecl.AddMembers(MakeReaderUnionSelector(def)); - } - - foreach (var field in def.Fields) - { - var propDecl = MakeReaderFieldProperty(field); - - if (propDecl != null) - { - readerDecl = readerDecl.AddMembers(propDecl); - } - } - - return readerDecl; - } - } -} diff --git a/capnpc-csharp/Generator/SerializerStateWorder.cs b/capnpc-csharp/Generator/SerializerStateWorder.cs deleted file mode 100644 index 8f64689..0000000 --- a/capnpc-csharp/Generator/SerializerStateWorder.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Capnp; -using System.Collections.Generic; -using System.Text; - -namespace CapnpC.Generator -{ - class SerializerStateWorder: SerializerState - { - public const string LinkName = nameof(SerializerStateWorder.Link); - public const string SetStructName = nameof(SerializerStateWorder.SetStruct); - } -} diff --git a/capnpc-csharp/Generator/SkeletonWorder.cs b/capnpc-csharp/Generator/SkeletonWorder.cs deleted file mode 100644 index 0d34191..0000000 --- a/capnpc-csharp/Generator/SkeletonWorder.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace CapnpC.Generator -{ - class SkeletonWorder : Capnp.Rpc.Skeleton - { - public override ulong InterfaceId => throw new NotImplementedException(); - - public const string SetMethodTableName = nameof(SkeletonWorder.SetMethodTable); - public const string ImplName = nameof(SkeletonWorder.Impl); - } -} diff --git a/capnpc-csharp/Generator/SyntaxHelpers.cs b/capnpc-csharp/Generator/SyntaxHelpers.cs deleted file mode 100644 index 4d087ae..0000000 --- a/capnpc-csharp/Generator/SyntaxHelpers.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace CapnpC.Generator -{ - static class SyntaxHelpers - { - public static string MakeCamel(string name) => $"{char.ToUpperInvariant(name[0])}{name.Substring(1)}"; - public static string MakeAllLower(string name) => $"@{name}"; - - public static readonly SyntaxToken Async = Token(SyntaxKind.AsyncKeyword); - public static readonly SyntaxToken Public = Token(SyntaxKind.PublicKeyword); - public static readonly SyntaxToken Private = Token(SyntaxKind.PrivateKeyword); - public static readonly SyntaxToken Readonly = Token(SyntaxKind.ReadOnlyKeyword); - public static readonly SyntaxToken Static = Token(SyntaxKind.StaticKeyword); - public static readonly SyntaxToken Override = Token(SyntaxKind.OverrideKeyword); - public static readonly SyntaxToken Partial = Token(SyntaxKind.PartialKeyword); - public static readonly SyntaxToken This = Token(SyntaxKind.ThisKeyword); - - public static TypeSyntax Type(Type type) - { - switch (0) - { - case 0 when type == typeof(bool): - return PredefinedType(Token(SyntaxKind.BoolKeyword)); - - case 0 when type == typeof(sbyte): - return PredefinedType(Token(SyntaxKind.SByteKeyword)); - - case 0 when type == typeof(byte): - return PredefinedType(Token(SyntaxKind.ByteKeyword)); - - case 0 when type == typeof(short): - return PredefinedType(Token(SyntaxKind.ShortKeyword)); - - case 0 when type == typeof(ushort): - return PredefinedType(Token(SyntaxKind.UShortKeyword)); - - case 0 when type == typeof(int): - return PredefinedType(Token(SyntaxKind.IntKeyword)); - - case 0 when type == typeof(uint): - return PredefinedType(Token(SyntaxKind.UIntKeyword)); - - case 0 when type == typeof(long): - return PredefinedType(Token(SyntaxKind.LongKeyword)); - - case 0 when type == typeof(ulong): - return PredefinedType(Token(SyntaxKind.ULongKeyword)); - - case 0 when type == typeof(float): - return PredefinedType(Token(SyntaxKind.FloatKeyword)); - - case 0 when type == typeof(double): - return PredefinedType(Token(SyntaxKind.DoubleKeyword)); - - case 0 when type == typeof(string): - return PredefinedType(Token(SyntaxKind.StringKeyword)); - - case 0 when type == typeof(object): - return PredefinedType(Token(SyntaxKind.ObjectKeyword)); - - case 0 when type.IsGenericType: - return GenericName(type.Name.Substring(0, type.Name.IndexOf('`'))) - .AddTypeArgumentListArguments(type.GetGenericArguments().Select(Type).ToArray()); - - default: - return ParseTypeName(type.Name); - } - } - - public static TypeSyntax Type() => Type(typeof(T)); - - public static ExpressionSyntax ValueOf(object value) - { - switch (value) - { - case bool x: - return LiteralExpression(x ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression); - - case sbyte x: - return CastExpression(Type(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); - - case byte x: - return CastExpression(Type(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); - - case short x: - return CastExpression(Type(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); - - case ushort x: - return CastExpression(Type(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); - - case int x: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); - - case uint x: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); - - case long x: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); - - case ulong x: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); - - case float x: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); - - case double x: - return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); - - case string x: - return LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(x)); - - case null: - return LiteralExpression(SyntaxKind.NullLiteralExpression); - - default: - throw new NotImplementedException(); - } - } - } -} diff --git a/capnpc-csharp/Generator/WriterSnippetGen.cs b/capnpc-csharp/Generator/WriterSnippetGen.cs deleted file mode 100644 index af62b09..0000000 --- a/capnpc-csharp/Generator/WriterSnippetGen.cs +++ /dev/null @@ -1,406 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using CapnpC.Model; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static CapnpC.Generator.SyntaxHelpers; - -namespace CapnpC.Generator -{ - class WriterSnippetGen - { - readonly GenNames _names; - - public WriterSnippetGen(GenNames names) - { - _names = names; - } - - IEnumerable MakeWriterStructMembers(TypeDefinition structType) - { - yield return ConstructorDeclaration(_names.WriterStruct.Identifier) - .AddModifiers(Public) - .WithBody( - Block( - ExpressionStatement( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - ThisExpression(), - IdentifierName(SerializerStateWorder.SetStructName))) - .AddArgumentListArguments( - Argument( - LiteralExpression( - SyntaxKind.NumericLiteralExpression, - Literal(structType.StructDataWordCount))), - Argument( - LiteralExpression( - SyntaxKind.NumericLiteralExpression, - Literal(structType.StructPointerCount))))))); - } - - IEnumerable MakeGroupWriterStructMembers() - { - yield return ConstructorDeclaration(_names.WriterStruct.Identifier) - .AddModifiers(Public) - .WithBody(Block()); - } - - PropertyDeclarationSyntax MakeWriterProperty( - TypeSyntax type, - string name, - ExpressionSyntax getter, - ExpressionSyntax setter, - bool cast, - bool cond) - { - if (cast) - { - getter = CastExpression(type, getter); - } - - if (cond) - { - getter = ConditionalExpression( - BinaryExpression( - SyntaxKind.EqualsExpression, - _names.UnionDiscriminatorProp.IdentifierName, - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _names.UnionDiscriminatorEnum.IdentifierName, - IdentifierName(name))), - getter, - LiteralExpression( - SyntaxKind.DefaultLiteralExpression, - Token(SyntaxKind.DefaultKeyword))); - } - - var accessors = new AccessorDeclarationSyntax[setter != null ? 2 : 1]; - - accessors[0] = AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) - .WithExpressionBody(ArrowExpressionClause(getter)) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); - - if (setter != null) - { - accessors[1] = AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) - .WithExpressionBody(ArrowExpressionClause(setter)) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); - } - - return PropertyDeclaration(type, name) - .AddModifiers(Public) - .AddAccessorListAccessors(accessors); - } - - ExpressionSyntax MakePointerSyntax(TypeSyntax type, object index) => - InvocationExpression( - GenericName(nameof(Capnp.SerializerState.BuildPointer)) - .AddTypeArgumentListArguments(type)) - .AddArgumentListArguments( - Argument(ValueOf(index))); - - ExpressionSyntax MakeReadCapSyntax(TypeSyntax type, object index) => - InvocationExpression( - GenericName(nameof(Capnp.SerializerState.ReadCap)) - .AddTypeArgumentListArguments(type)) - .AddArgumentListArguments( - Argument(ValueOf(index))); - - ExpressionSyntax MakeTypedPointerSyntax(object index, TypeSyntax type) => - InvocationExpression( - GenericName(nameof(Capnp.SerializerState.BuildPointer)) - .AddTypeArgumentListArguments(type)) - .AddArgumentListArguments( - Argument(ValueOf(index))); - - ExpressionSyntax MakeLinkSyntax(object index) => - InvocationExpression( - IdentifierName(SerializerStateWorder.LinkName)) - .AddArgumentListArguments( - Argument(ValueOf(index)), - Argument(IdentifierName("value"))); - - ExpressionSyntax MakeLinkObjectSyntax(object index) => - InvocationExpression( - IdentifierName(nameof(Capnp.SerializerState.LinkObject))) - .AddArgumentListArguments( - Argument(ValueOf(index)), - Argument(IdentifierName("value"))); - - PropertyDeclarationSyntax MakePointerProperty(TypeSyntax type, string name, object index, bool cast, bool cond) - { - ExpressionSyntax getter = MakePointerSyntax(type, index); - ExpressionSyntax setter = MakeLinkSyntax(index); - - return MakeWriterProperty(type, name, getter, setter, cast, cond); - } - - PropertyDeclarationSyntax MakePointerAsStructProperty( - TypeSyntax type, string name, object index, - bool cast, bool cond) - { - ExpressionSyntax getter = MakeTypedPointerSyntax(index, type); - ExpressionSyntax setter = MakeLinkSyntax(index); - - return MakeWriterProperty(type, name, getter, setter, cast, cond); - } - - PropertyDeclarationSyntax MakeProperty( - TypeSyntax outerType, - TypeSyntax innerType, - string name, - string readName, - string writeName, - object indexOrBitOffset, - ExpressionSyntax secondArg, - bool cast, - bool cond, - bool pasd) - { - var getter = InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - ThisExpression(), - IdentifierName(readName))) - .AddArgumentListArguments( - Argument(ValueOf(indexOrBitOffset)), - Argument(secondArg)); - - ExpressionSyntax value = IdentifierName("value"); - - if (cast) - { - value = CastExpression(innerType, value); - } - - var setter = InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - ThisExpression(), - IdentifierName(writeName))) - .AddArgumentListArguments( - Argument(ValueOf(indexOrBitOffset)), - Argument(value), - Argument(secondArg)); - - if (pasd) - { - setter.AddArgumentListArguments(Argument(secondArg)); - } - - return MakeWriterProperty(outerType, name, getter, setter, cast, cond); - } - - PropertyDeclarationSyntax MakePrimitiveProperty(Field field, string readName) - { - return MakeProperty(Type(), null, _names.GetCodeIdentifier(field).ToString(), - readName, - nameof(Capnp.SerializerExtensions.WriteData), - field.BitOffset.Value, - ValueOf(field.DefaultValue.ScalarValue), - false, - field.DiscValue.HasValue, - true); - } - - PropertyDeclarationSyntax MakeEnumProperty(Field field, string readName) - { - return MakeProperty(_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.NotRelevant), Type(), - _names.GetCodeIdentifier(field).ToString(), - readName, - nameof(Capnp.SerializerExtensions.WriteData), - field.BitOffset.Value, - ValueOf(field.DefaultValue.ScalarValue), - true, - field.DiscValue.HasValue, - true); - } - - PropertyDeclarationSyntax MakeTextProperty(Field field) - { - return MakeProperty(Type(), null, - _names.GetCodeIdentifier(field).ToString(), - nameof(Capnp.SerializerState.ReadText), - nameof(Capnp.SerializerState.WriteText), - (int)field.Offset, - ValueOf(field.DefaultValue.ScalarValue), - false, - field.DiscValue.HasValue, - false); - } - - PropertyDeclarationSyntax MakeStructProperty(Field field) - { - var qtype = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Writer); - - return MakePointerAsStructProperty(qtype, _names.GetCodeIdentifier(field).ToString(), - (int)field.Offset, false, field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakeGroupProperty(Field field) - { - var type = QualifiedName( - _names.MakeTypeName(field.Type.Definition).IdentifierName, - _names.WriterStruct.IdentifierName); - - var getter = InvocationExpression( - GenericName(nameof(Capnp.SerializerState.Rewrap)) - .AddTypeArgumentListArguments(type)); - - return MakeWriterProperty(type, _names.GetCodeIdentifier(field).ToString(), getter, null, false, field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakeListProperty(Field field) - { - var qtype = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Writer); - - return MakePointerProperty(qtype, _names.GetCodeIdentifier(field).ToString(), - (int)field.Offset, false, field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakePointerProperty(Field field) - { - var type = IdentifierName(nameof(Capnp.DynamicSerializerState)); - - return MakePointerProperty(type, _names.GetCodeIdentifier(field).ToString(), (int)field.Offset, false, field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakeCapProperty(Field field) - { - var type = _names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.Writer); - int index = (int)field.Offset; - string name = _names.GetCodeIdentifier(field).ToString(); - ExpressionSyntax getter = MakeReadCapSyntax(type, index); - ExpressionSyntax setter = MakeLinkObjectSyntax(index); - - return MakeWriterProperty(type, name, getter, setter, false, field.DiscValue.HasValue); - } - - PropertyDeclarationSyntax MakeWriterUnionSelector(TypeDefinition def) - { - return MakeProperty( - _names.UnionDiscriminatorEnum.IdentifierName, - Type(), - _names.UnionDiscriminatorProp.ToString(), - nameof(Capnp.SerializerExtensions.ReadDataUShort), - nameof(Capnp.SerializerExtensions.WriteData), - def.UnionInfo.TagOffset, - ValueOf(default(ushort)), - true, false, true); - } - - PropertyDeclarationSyntax MakeWriterFieldProperty(Field field) - { - switch (field.Type.Tag) - { - case TypeTag.Bool: - return MakePrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataBool)); - - case TypeTag.S8: - return MakePrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataSByte)); - - case TypeTag.U8: - return MakePrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataByte)); - - case TypeTag.S16: - return MakePrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataShort)); - - case TypeTag.U16: - return MakePrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataUShort)); - - case TypeTag.S32: - return MakePrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataInt)); - - case TypeTag.U32: - return MakePrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataUInt)); - - case TypeTag.S64: - return MakePrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataLong)); - - case TypeTag.U64: - return MakePrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataULong)); - - case TypeTag.F32: - return MakePrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataFloat)); - - case TypeTag.F64: - return MakePrimitiveProperty(field, - nameof(Capnp.SerializerExtensions.ReadDataDouble)); - - case TypeTag.Enum: - return MakeEnumProperty(field, nameof(Capnp.SerializerExtensions.ReadDataUShort)); - - case TypeTag.Text: - return MakeTextProperty(field); - - case TypeTag.Struct: - return MakeStructProperty(field); - - case TypeTag.Group: - return MakeGroupProperty(field); - - case TypeTag.List: - case TypeTag.Data: - return MakeListProperty(field); - - case TypeTag.AnyPointer: - case TypeTag.StructPointer: - case TypeTag.ListPointer: - return MakePointerProperty(field); - - case TypeTag.CapabilityPointer: - case TypeTag.Interface: - return MakeCapProperty(field); - - default: - return null; - } - } - - public ClassDeclarationSyntax MakeWriterStruct(TypeDefinition def) - { - var WriterDecl = ClassDeclaration(_names.WriterStruct.ToString()) - .AddModifiers(Public) - .AddBaseListTypes( - SimpleBaseType(IdentifierName(nameof(Capnp.SerializerState)))); - - var members = def.Tag == TypeTag.Group ? - MakeGroupWriterStructMembers() : - MakeWriterStructMembers(def); - - WriterDecl = WriterDecl.AddMembers(members.ToArray()); - - if (def.UnionInfo != null) - { - WriterDecl = WriterDecl.AddMembers(MakeWriterUnionSelector(def)); - } - - foreach (var field in def.Fields) - { - var propDecl = MakeWriterFieldProperty(field); - - if (propDecl != null) - { - WriterDecl = WriterDecl.AddMembers(propDecl); - } - } - - return WriterDecl; - } - } -} diff --git a/capnpc-csharp/Model/AbstractType.cs b/capnpc-csharp/Model/AbstractType.cs deleted file mode 100644 index 2c1451a..0000000 --- a/capnpc-csharp/Model/AbstractType.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Collections.Generic; - -namespace CapnpC.Model -{ - abstract class AbstractType - { - public TypeTag Tag { get; set; } - protected List Fields { get; } = new List(); - - public uint? FixedBitWidth - { - get - { - switch (Tag) - { - case TypeTag.Bool: - return 1; - - case TypeTag.U8: - case TypeTag.S8: - return 8; - - case TypeTag.U16: - case TypeTag.S16: - case TypeTag.Enum: - case TypeTag.AnyEnum: - return 16; - - case TypeTag.U32: - case TypeTag.S32: - case TypeTag.F32: - return 32; - - case TypeTag.U64: - case TypeTag.S64: - case TypeTag.F64: - return 64; - - default: - return null; - } - } - } - } -} diff --git a/capnpc-csharp/Model/Annotation.cs b/capnpc-csharp/Model/Annotation.cs deleted file mode 100644 index 36191b6..0000000 --- a/capnpc-csharp/Model/Annotation.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Diagnostics; - -namespace CapnpC.Model -{ - class Annotation : IDefinition - { - public ulong Id { get; } - public bool IsGenerated { get; } - public TypeTag Tag { get => TypeTag.Annotation; } - public IHasNestedDefinitions DeclaringElement { get; } - - public Type Type { get; set; } - - public Annotation(ulong id, IHasNestedDefinitions parent) - { - Trace.Assert(parent != null); - Id = id; - IsGenerated = (parent as IDefinition).IsGenerated; - DeclaringElement = parent; - parent.NestedDefinitions.Add(this); - } - } -} diff --git a/capnpc-csharp/Model/Constant.cs b/capnpc-csharp/Model/Constant.cs deleted file mode 100644 index 5879100..0000000 --- a/capnpc-csharp/Model/Constant.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Diagnostics; - -namespace CapnpC.Model -{ - class Constant : IDefinition - { - public ulong Id { get; } - public bool IsGenerated { get; } - public TypeTag Tag { get => TypeTag.Const; } - public IHasNestedDefinitions DeclaringElement { get; } - - public Value Value { get; set; } - - public Constant(ulong id, IHasNestedDefinitions parent) - { - Trace.Assert(parent != null); - Id = id; - IsGenerated = (parent as IDefinition).IsGenerated; - DeclaringElement = parent; - parent.NestedDefinitions.Add(this); - } - } -} diff --git a/capnpc-csharp/Model/DefinitionManager.cs b/capnpc-csharp/Model/DefinitionManager.cs deleted file mode 100644 index 95b9183..0000000 --- a/capnpc-csharp/Model/DefinitionManager.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace CapnpC.Model -{ - class DefinitionManager - { - readonly Dictionary _id2def = new Dictionary(); - - public GenFile CreateFile(ulong id, bool isGenerated) - => CreateId(id, () => new GenFile(id, isGenerated)); - public GenFile GetExistingFile(ulong id) - => GetId(id, TypeTag.File); - - public TypeDefinition CreateTypeDef(ulong id, TypeTag tag, IHasNestedDefinitions decl) - => CreateId(id, () => new TypeDefinition(tag, id, decl)); - public TypeDefinition GetExistingTypeDef(ulong id, TypeTag tag) - { - var def = GetId(id, tag); - if (def.Tag == TypeTag.Unknown) def.Tag = tag; - return def; - } - - public Annotation CreateAnnotation(ulong id, IHasNestedDefinitions decl) - => CreateId(id, () => new Annotation(id, decl)); - public Annotation GetExistingAnnotation(ulong id) - => GetId(id, TypeTag.Annotation); - - public Constant CreateConstant(ulong id, IHasNestedDefinitions decl) - => CreateId(id, () => new Constant(id, decl)); - public Constant GetExistingConstant(ulong id) - => GetId(id, TypeTag.Const); - - public IDefinition GetExistingDef(ulong id, TypeTag tag) - => GetId(id, tag); - - public IEnumerable Files - { - get => _id2def.Values.Where(d => d.Tag == TypeTag.File).Select(f => f as GenFile); - } - - T CreateId(ulong id, Func creator) where T : class, IDefinition - { - if (_id2def.TryGetValue(id, out var d)) - { - throw new ArgumentException(nameof(id), $"Attempting to redefine {d.Tag.ToString()} {id.StrId()} (as {nameof(T)})."); - } - var def = creator(); - _id2def.Add(id, def); - return def as T; - } - - T GetId(ulong id, TypeTag tag) where T : IDefinition - { - if (!_id2def.TryGetValue(id, out var anyDef)) - { - throw new ArgumentOutOfRangeException($"Attempting to retrieve nonexistent node {id.StrId()}."); - } - if (!(anyDef is T def) || (tag != TypeTag.Unknown && def.Tag != tag)) - { - throw new ArgumentOutOfRangeException($"Attempting to retrieve {tag.ToString()} {id.StrId()}, but found {anyDef.Tag.ToString()} instead."); - } - return def; - } - } -} diff --git a/capnpc-csharp/Model/Enumerant.cs b/capnpc-csharp/Model/Enumerant.cs deleted file mode 100644 index 96d9137..0000000 --- a/capnpc-csharp/Model/Enumerant.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace CapnpC.Model -{ - class Enumerant - { - string _literal; - public TypeDefinition TypeDefinition { get; set; } - public string Literal { - get => _literal; - set => _literal = IdentifierRenamer.ToNonKeyword(value); - } - public ushort? Ordinal { get; set; } - public int CodeOrder { get; set; } - } -} diff --git a/capnpc-csharp/Model/Field.cs b/capnpc-csharp/Model/Field.cs deleted file mode 100644 index eee384b..0000000 --- a/capnpc-csharp/Model/Field.cs +++ /dev/null @@ -1,52 +0,0 @@ -namespace CapnpC.Model -{ - class Field - { - public TypeDefinition DeclaringType { get; set; } - public Field Parent { get; set; } - public string Name { get; set; } - public Type Type { get; set; } - public Value DefaultValue { get; set; } - public bool DefaultValueIsExplicit { get; set; } - public ushort? DiscValue { get; set; } - public uint Offset { get; set; } - public int CodeOrder { get; set; } - - public ulong? BitOffset => (ulong)Offset * Type?.FixedBitWidth; - - public Field Clone() - { - var field = new Field() - { - DeclaringType = DeclaringType, - Parent = Parent, - Name = Name, - Type = Type, - DefaultValue = DefaultValue, - DefaultValueIsExplicit = DefaultValueIsExplicit, - DiscValue = DiscValue, - Offset = Offset, - CodeOrder = CodeOrder, - }; - field.InheritFreeGenericParameters(); - return field; - } - - public void InheritFreeGenericParameters() - { - Type.InheritFreeParameters(DeclaringType); - } - - public override bool Equals(object obj) - { - return obj is Field other && - DeclaringType == other.DeclaringType && - Name == other.Name; - } - - public override int GetHashCode() - { - return (DeclaringType, Name).GetHashCode(); - } - } -} diff --git a/capnpc-csharp/Model/GenFile.cs b/capnpc-csharp/Model/GenFile.cs deleted file mode 100644 index f889fce..0000000 --- a/capnpc-csharp/Model/GenFile.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; - -namespace CapnpC.Model -{ - class GenFile: IDefinition, IHasNestedDefinitions - { - public ulong Id { get; } - public bool IsGenerated { get; } - public TypeTag Tag { get => TypeTag.File; } - public IHasNestedDefinitions DeclaringElement { get => null; } - - public string Name { get; set; } - public string[] Namespace { get; set; } - - public IEnumerable NestedTypes { get => this.GetNestedTypes(); } - public ICollection NestedDefinitions { get; } = new List(); - public ICollection Constants { get; } = new List(); - - public GenFile(ulong id, bool isGenerated) - { - Id = id; - IsGenerated = isGenerated; - } - } -} diff --git a/capnpc-csharp/Model/GenericParameter.cs b/capnpc-csharp/Model/GenericParameter.cs deleted file mode 100644 index 8526b0d..0000000 --- a/capnpc-csharp/Model/GenericParameter.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace CapnpC.Model -{ - class GenericParameter - { - public IHasGenericParameters DeclaringEntity { get; set; } - public int Index { get; set; } - public string Name => DeclaringEntity.GenericParameters[Index]; - - public override bool Equals(object obj) - { - // Instead of equality by Name, we could instead take (DeclaringEntity, Index), but there is a caveat: - // Since methods can also own generic parameters, we have different classes of declaring entities involved. - // Both the method will define generic parameters, and the Cap'n'p-generated params/result structs. - // Therefore we end in two GenericParameter instances, one with the Method as declaring entity, the - // other one with the params/result type definition as declaring entity. They are semantically the same, - // and the easy way to match them is by Name. Equality by Name is the only working choice, even though - // it feels a little less reboust than by matching declaring entity + parameter position. - return obj is GenericParameter other && Name == other.Name; - } - - public override int GetHashCode() - { - return Name.GetHashCode(); - } - } -} diff --git a/capnpc-csharp/Model/HasGenericParameters.cs b/capnpc-csharp/Model/HasGenericParameters.cs deleted file mode 100644 index 6636ff4..0000000 --- a/capnpc-csharp/Model/HasGenericParameters.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; -namespace CapnpC.Model -{ - static class HasGenericParameters - { - public static IEnumerable GetLocalTypeParameters(this IHasGenericParameters me) - { - for (int i = 0; i < me.GenericParameters.Count; i++) - { - yield return new GenericParameter() - { - DeclaringEntity = me, - Index = i - }; - } - } - } -} diff --git a/capnpc-csharp/Model/IDefinition.cs b/capnpc-csharp/Model/IDefinition.cs deleted file mode 100644 index 9bd8572..0000000 --- a/capnpc-csharp/Model/IDefinition.cs +++ /dev/null @@ -1,11 +0,0 @@ - -namespace CapnpC.Model -{ - interface IDefinition - { - ulong Id { get; } - bool IsGenerated { get; } - TypeTag Tag { get; } - IHasNestedDefinitions DeclaringElement { get; } - } -} diff --git a/capnpc-csharp/Model/IHasGenericParameters.cs b/capnpc-csharp/Model/IHasGenericParameters.cs deleted file mode 100644 index 5b9ce58..0000000 --- a/capnpc-csharp/Model/IHasGenericParameters.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace CapnpC.Model -{ - interface IHasGenericParameters - { - List GenericParameters { get; } - } -} diff --git a/capnpc-csharp/Model/IHasNestedDefinitions.cs b/capnpc-csharp/Model/IHasNestedDefinitions.cs deleted file mode 100644 index 3885c60..0000000 --- a/capnpc-csharp/Model/IHasNestedDefinitions.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace CapnpC.Model -{ - interface IHasNestedDefinitions - { - IEnumerable NestedTypes { get; } - ICollection NestedDefinitions { get; } - ICollection Constants { get; } - } - - static partial class Extensions - { - public static IEnumerable GetNestedTypes(this IHasNestedDefinitions def) - => def.NestedDefinitions.Select(d => d as TypeDefinition).Where(d => d != null); - } -} diff --git a/capnpc-csharp/Model/IdentifierRenamer.cs b/capnpc-csharp/Model/IdentifierRenamer.cs deleted file mode 100644 index 9c6ff07..0000000 --- a/capnpc-csharp/Model/IdentifierRenamer.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.CodeAnalysis.CSharp; -using System; -using System.Collections.Generic; -using System.Text; - -namespace CapnpC.Model -{ - public class IdentifierRenamer - { - public static bool IsAnyKeyword(string str) - { - return SyntaxFacts.GetKeywordKind(str) != SyntaxKind.None - || SyntaxFacts.GetContextualKeywordKind(str) != SyntaxKind.None; - } - public static string ToNonKeyword(string str) - { - // Capnp schema identifiers should be already valid, but could be a keyword - if (IsAnyKeyword(str)) return $"@{str}"; - return str; - } - } -} diff --git a/capnpc-csharp/Model/InvalidSchemaException.cs b/capnpc-csharp/Model/InvalidSchemaException.cs deleted file mode 100644 index 4732ca8..0000000 --- a/capnpc-csharp/Model/InvalidSchemaException.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CapnpC.Model -{ - class InvalidSchemaException : Exception - { - public InvalidSchemaException(string message) : base(message) - { - } - } -} diff --git a/capnpc-csharp/Model/Method.cs b/capnpc-csharp/Model/Method.cs deleted file mode 100644 index e263f89..0000000 --- a/capnpc-csharp/Model/Method.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; - -namespace CapnpC.Model -{ - class Method: IHasGenericParameters - { - public TypeDefinition DeclaringInterface { get; set; } - public int Id { get; set; } - public string Name { get; set; } - public List Params { get; } = new List(); - public List Results { get; } = new List(); - public Type ParamsStruct { get; set; } - public Type ResultStruct { get; set; } - public List GenericParameters { get; } = new List(); - } -} diff --git a/capnpc-csharp/Model/SchemaModel.cs b/capnpc-csharp/Model/SchemaModel.cs deleted file mode 100644 index bd758c6..0000000 --- a/capnpc-csharp/Model/SchemaModel.cs +++ /dev/null @@ -1,783 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; - -namespace CapnpC.Model -{ - class SchemaModel - { - readonly Schema.CodeGeneratorRequest.Reader _request; - readonly List _generatedFiles = new List(); - readonly DefinitionManager _typeDefMgr = new DefinitionManager(); - - readonly Dictionary _id2node = new Dictionary(); - - public SchemaModel(Schema.CodeGeneratorRequest.Reader request) - { - _request = request; - } - - public IReadOnlyList FilesToGenerate => _generatedFiles; - - Schema.Node.Reader? IdToNode(ulong id, bool mustExist) - { - if (_id2node.TryGetValue(id, out var node)) - return node; - if (mustExist) - throw new InvalidSchemaException($"Node with ID {id.StrId()} is required by the codegen backend but is missing."); - return null; - } - - Schema.Node.Reader IdToNode(ulong id) - { - return (Schema.Node.Reader)IdToNode(id, true); - } - - void Build() - { - if (_request.Nodes == null || _request.Nodes.Count == 0) - { - throw new InvalidSchemaException("No nodes, nothing to generate"); - } - - foreach (var node in _request.Nodes) - { - if (_id2node.TryGetValue(node.Id, out var existingNode)) - { - throw new InvalidSchemaException($"Node {node.StrId()} \"{node.DisplayName}\" has a duplicate ID, prior node was \"{existingNode.DisplayName}\""); - } - _id2node[node.Id] = node; - } - - var requestedFiles = _request.RequestedFiles.ToDictionary(req => req.Id); - BuildPass1(requestedFiles); - BuildPass2(requestedFiles); - } - - // First pass: create type definitions for each node. - - struct Pass1State - { - public HashSet unprocessedNodes; - public IHasNestedDefinitions parent; - } - - void BuildPass1(Dictionary requestedFiles) - { - Pass1State state = new Pass1State() - { - unprocessedNodes = new HashSet(_id2node.Keys) - }; - foreach (var node in _id2node.Values.Where(n => n.IsFile)) - { - GenFile file; - bool isGenerated = requestedFiles.TryGetValue(node.Id, out var req); - var filename = isGenerated ? req.Filename : node.DisplayName; - file = ProcessFilePass1(node.Id, filename, state, isGenerated); - if (isGenerated) - _generatedFiles.Add(file); - } - if (state.unprocessedNodes.Count != 0) - { - throw new InvalidSchemaException("Unreferenced nodes were present in the schema."); - } - } - - GenFile ProcessFilePass1(ulong id, string name, Pass1State state, bool isGenerated) - { - var file = _typeDefMgr.CreateFile(id, isGenerated); - var node = IdToNode(id); - state.parent = null; - file.Namespace = GetNamespaceAnnotation(node); - file.Name = name; - return ProcessNodePass1(id, name, state) as GenFile; - } - - IDefinition ProcessNodePass1(ulong id, string name, Pass1State state) - { - bool mustExist = state.parent == null || (state.parent as IDefinition).IsGenerated; - if (!(IdToNode(id, mustExist) is Schema.Node.Reader node)) - return null; - if (!state.unprocessedNodes.Remove(id)) - return null; - - IDefinition def = null; - bool processNestedNodes = false; - bool processFields = false; - bool processInterfaceMethods = false; - - switch (node.GetKind()) - { - case NodeKind.Annotation: - return _typeDefMgr.CreateAnnotation(id, state.parent); - case NodeKind.Const: - return _typeDefMgr.CreateConstant(id, state.parent); - case NodeKind.File: - if (state.parent != null) - throw new InvalidSchemaException($"Did not expect a file node {node.StrId()} to be a nested node."); - var file = _typeDefMgr.GetExistingFile(id); - file.Namespace = GetNamespaceAnnotation(node); - file.Name = name; - state.parent = file; - def = file; - processNestedNodes = true; - break; - case NodeKind.Enum: - break; - case NodeKind.Interface: - processNestedNodes = true; - processFields = true; - processInterfaceMethods = true; - break; - case NodeKind.Struct: - case NodeKind.Group: - processNestedNodes = true; - processFields = true; - break; - default: - throw new InvalidSchemaException($"Don't know how to process node {node.StrId()} \"{node.DisplayName}\""); - } - - if (def == null) - { - Trace.Assert(state.parent != null, $"The {node.GetTypeTag().ToString()} node {node.StrId()} was expected to have a parent."); - var typeDef = _typeDefMgr.CreateTypeDef(id, node.GetTypeTag(), state.parent); - typeDef.Name = name; - state.parent = typeDef; - def = typeDef; - } - - if (processNestedNodes && node.NestedNodes != null) - foreach (var nested in node.NestedNodes) - { - ProcessNodePass1(nested.Id, nested.Name, state); - } - if (processFields && node.Fields != null) - foreach (var field in node.Fields.Where(f => f.IsGroup)) - { - var group = IdToNode(field.Group_TypeId); - if (!group.IsStruct || !group.Struct_IsGroup) - { - throw new InvalidSchemaException($"Expected node with id {group.StrId()} to be a struct definition"); - } - ProcessNodePass1(field.Group_TypeId, field.Name, state); - } - if (processInterfaceMethods && node.Interface_Methods != null) - foreach (var method in node.Interface_Methods) - { - var pnode = IdToNode(method.ParamStructType); - if (pnode.ScopeId == 0) ProcessNodePass1(pnode.Id, null, state); // Anonymous generated type - pnode = IdToNode(method.ResultStructType); - if (pnode.ScopeId == 0) ProcessNodePass1(pnode.Id, null, state); // Anonymous generated type - } - return def; - } - - string[] GetNamespaceAnnotation(Schema.Node.Reader fileNode) - { - foreach (var annotation in fileNode.Annotations) - { - if (annotation.Id == 0xb9c6f99ebf805f2c) // Cxx namespace - { - return annotation.Value.Text.Split(new string[1] { "::" }, default); - } - } - return null; - } - - // 2nd pass: Generate types based on definitions - - struct Pass2State - { - public Method currentMethod; - public HashSet processedNodes; - } - - void BuildPass2(Dictionary requestedFiles) - { - var state = new Pass2State() { processedNodes = new HashSet() }; - foreach (var file in _typeDefMgr.Files) - { - var node = IdToNode(file.Id); - ProcessNestedNodes(node.NestedNodes, state, file.IsGenerated); - } - } - - void ProcessNestedNodes(IEnumerable nestedNodes, Pass2State state, bool mustExist) - { - foreach (var nestedNode in nestedNodes) - { - ProcessNode(nestedNode.Id, state, mustExist); - } - } - - void ProcessBrand(Schema.Brand.Reader brandReader, Type type, Pass2State state) - { - foreach (var scopeReader in brandReader.Scopes) - { - var whatToBind = ProcessTypeDef(scopeReader.ScopeId, state); - int index = 0; - - switch (0) - { - case 0 when scopeReader.IsBind: - foreach (var bindingReader in scopeReader.Bind) - { - var typeParameter = new GenericParameter() - { - DeclaringEntity = whatToBind, - Index = index++ - }; - - switch (0) - { - case 0 when bindingReader.IsType: - type.BindGenericParameter(typeParameter, ProcessType(bindingReader.Type, state)); - break; - - case 0 when bindingReader.IsUnbound: - type.BindGenericParameter(typeParameter, Types.FromParameter(typeParameter)); - break; - } - } - break; - - case 0 when scopeReader.IsInherit: - for (index = 0; index < type.DeclaringType.Definition.GenericParameters.Count; index++) - { - var typeParameter = new GenericParameter() - { - DeclaringEntity = whatToBind, - Index = index - }; - - type.BindGenericParameter(typeParameter, Types.FromParameter(typeParameter)); - } - break; - } - } - } - - Type ProcessType(Schema.Type.Reader typeReader, Pass2State state) - { - Type result; - - switch (0) - { - case 0 when typeReader.IsAnyPointer: - switch (0) - { - case 0 when typeReader.AnyPointer_IsParameter: - return Types.FromParameter( - new GenericParameter() - { - DeclaringEntity = ProcessTypeDef(typeReader.AnyPointer_Parameter_ScopeId, state), - Index = typeReader.AnyPointer_Parameter_ParameterIndex - }); - - case 0 when typeReader.AnyPointer_IsImplicitMethodParameter: - return Types.FromParameter( - new GenericParameter() - { - DeclaringEntity = state.currentMethod ?? throw new InvalidOperationException("current method not set"), - Index = typeReader.AnyPointer_ImplicitMethodParameter_ParameterIndex - }); - - case 0 when typeReader.AnyPointer_IsUnconstrained: - - switch (0) - { - case 0 when typeReader.AnyPointer_Unconstrained_IsAnyKind: - return Types.AnyPointer; - - case 0 when typeReader.AnyPointer_Unconstrained_IsCapability: - return Types.CapabilityPointer; - - case 0 when typeReader.AnyPointer_Unconstrained_IsList: - return Types.ListPointer; - - case 0 when typeReader.AnyPointer_Unconstrained_IsStruct: - return Types.StructPointer; - - default: - throw new NotImplementedException(); - } - - default: - throw new NotImplementedException(); - } - - case 0 when typeReader.IsBool: - return Types.Bool; - - case 0 when typeReader.IsData: - return Types.Data; - - case 0 when typeReader.IsFloat64: - return Types.F64; - - case 0 when typeReader.IsEnum: - return Types.FromDefinition(ProcessTypeDef(typeReader.Enum_TypeId, state, TypeTag.Enum)); - - case 0 when typeReader.IsFloat32: - return Types.F32; - - case 0 when typeReader.IsInt16: - return Types.S16; - - case 0 when typeReader.IsInt32: - return Types.S32; - - case 0 when typeReader.IsInt64: - return Types.S64; - - case 0 when typeReader.IsInt8: - return Types.S8; - - case 0 when typeReader.IsInterface: - result = Types.FromDefinition(ProcessTypeDef(typeReader.Interface_TypeId, state, TypeTag.Interface)); - ProcessBrand(typeReader.Interface_Brand, result, state); - return result; - - case 0 when typeReader.IsList: - return Types.List(ProcessType(typeReader.List_ElementType, state)); - - case 0 when typeReader.IsStruct: - result = Types.FromDefinition(ProcessTypeDef(typeReader.Struct_TypeId, state, TypeTag.Struct)); - ProcessBrand(typeReader.Struct_Brand, result, state); - return result; - - case 0 when typeReader.IsText: - return Types.Text; - - case 0 when typeReader.IsUInt16: - return Types.U16; - - case 0 when typeReader.IsUInt32: - return Types.U32; - - case 0 when typeReader.IsUInt64: - return Types.U64; - - case 0 when typeReader.IsUInt8: - return Types.U8; - - case 0 when typeReader.IsVoid: - return Types.Void; - - default: - throw new NotImplementedException(); - } - } - - Value ProcessValue(Schema.Value.Reader valueReader) - { - var value = new Value(); - - switch (0) - { - case 0 when valueReader.IsAnyPointer: - value.ScalarValue = valueReader.AnyPointer; - value.Type = Types.AnyPointer; - break; - - case 0 when valueReader.IsBool: - value.ScalarValue = valueReader.Bool; - value.Type = Types.Bool; - break; - - case 0 when valueReader.IsData: - value.Items.AddRange(valueReader.Data.CastByte().Select(Value.Scalar)); - value.Type = Types.Data; - break; - - case 0 when valueReader.IsEnum: - value.ScalarValue = valueReader.Enum; - value.Type = Types.AnyEnum; - break; - - case 0 when valueReader.IsFloat32: - value.ScalarValue = valueReader.Float32; - value.Type = Types.F32; - break; - - case 0 when valueReader.IsFloat64: - value.ScalarValue = valueReader.Float64; - value.Type = Types.F64; - break; - - case 0 when valueReader.IsInt16: - value.ScalarValue = valueReader.Int16; - value.Type = Types.S16; - break; - - case 0 when valueReader.IsInt32: - value.ScalarValue = valueReader.Int32; - value.Type = Types.S32; - break; - - case 0 when valueReader.IsInt64: - value.ScalarValue = valueReader.Int64; - value.Type = Types.S64; - break; - - case 0 when valueReader.IsInt8: - value.ScalarValue = valueReader.Int8; - value.Type = Types.S8; - break; - - case 0 when valueReader.IsInterface: - value.ScalarValue = null; - value.Type = Types.CapabilityPointer; - break; - - case 0 when valueReader.IsList: - value.RawValue = valueReader.List; - value.Type = Types.ListPointer; - break; - - case 0 when valueReader.IsStruct: - value.RawValue = valueReader.Struct; - value.Type = Types.StructPointer; - break; - - case 0 when valueReader.IsText: - value.ScalarValue = valueReader.Text; - value.Type = Types.Text; - break; - - case 0 when valueReader.IsUInt16: - value.ScalarValue = valueReader.UInt16; - value.Type = Types.U16; - break; - - case 0 when valueReader.IsUInt32: - value.ScalarValue = valueReader.UInt32; - value.Type = Types.U32; - break; - - case 0 when valueReader.IsUInt64: - value.ScalarValue = valueReader.UInt64; - value.Type = Types.U64; - break; - - case 0 when valueReader.IsUInt8: - value.ScalarValue = valueReader.UInt8; - value.Type = Types.U8; - break; - - case 0 when valueReader.IsVoid: - value.Type = Types.Void; - break; - - default: - throw new NotImplementedException(); - } - - return value; - } - - void ProcessFields(Schema.Node.Reader reader, TypeDefinition declaringType, List fields, Pass2State state) - { - if (reader.Fields == null) - { - return; - } - - foreach (var fieldReader in reader.Fields) - { - var field = new Field() - { - DeclaringType = declaringType, - Name = fieldReader.Name, - CodeOrder = fieldReader.CodeOrder - }; - - if (fieldReader.DiscriminantValue != Schema.Field.Reader.NoDiscriminant) - { - field.DiscValue = fieldReader.DiscriminantValue; - } - - switch (0) - { - case 0 when fieldReader.IsGroup: - var def = ProcessTypeDef(fieldReader.Group_TypeId, state, TypeTag.Group); - field.Type = Types.FromDefinition(def); - break; - - case 0 when fieldReader.IsSlot: - field.DefaultValue = ProcessValue(fieldReader.Slot_DefaultValue); - field.DefaultValueIsExplicit = fieldReader.Slot_HadExplicitDefault; - field.Offset = fieldReader.Slot_Offset; - field.Type = ProcessType(fieldReader.Slot_Type, state); - field.DefaultValue.Type = field.Type; - break; - - default: - throw new NotImplementedException(); - } - - field.InheritFreeGenericParameters(); - - fields.Add(field); - } - } - - TypeDefinition ProcessInterfaceOrStructTail(TypeDefinition def, Schema.Node.Reader reader, Pass2State state) - { - def.IsGeneric = reader.IsGeneric; - - if (def.IsGeneric) - { - foreach (var paramReader in reader.Parameters) - { - def.GenericParameters.Add(paramReader.Name); - } - } - - ProcessNestedNodes(reader.NestedNodes, state, def.File.IsGenerated); - - ProcessFields(reader, def, def.Fields, state); - - if (reader.IsInterface) - { - foreach (var methodReader in reader.Interface_Methods) - { - var method = new Method() - { - DeclaringInterface = def, - Id = def.Methods.Count, - Name = methodReader.Name - }; - foreach (var implicitParameterReader in methodReader.ImplicitParameters) - { - method.GenericParameters.Add(implicitParameterReader.Name); - } - state.currentMethod = method; - - def.Methods.Add(method); - - var paramNode = IdToNode(methodReader.ParamStructType); - var paramType = ProcessParameterList(paramNode, methodReader.ParamBrand, method.Params, state); - if (paramType != null) - { - paramType.SpecialName = SpecialName.MethodParamsStruct; - paramType.UsingMethod = method; - method.ParamsStruct = Types.FromDefinition(paramType); - } - else - { - method.ParamsStruct = method.Params[0].Type; - } - method.ParamsStruct.InheritFreeParameters(def); - method.ParamsStruct.InheritFreeParameters(method); - - var resultNode = IdToNode(methodReader.ResultStructType); - var resultType = ProcessParameterList(resultNode, methodReader.ResultBrand, method.Results, state); - if (resultType != null) - { - resultType.SpecialName = SpecialName.MethodResultStruct; - resultType.UsingMethod = method; - method.ResultStruct = Types.FromDefinition(resultType); - } - else - { - method.ResultStruct = method.Results[0].Type; - } - method.ResultStruct.InheritFreeParameters(def); - method.ResultStruct.InheritFreeParameters(method); - } - - state.currentMethod = null; - } - return def; - } - - TypeDefinition ProcessStruct(Schema.Node.Reader structReader, TypeDefinition def, Pass2State state) - { - def.StructDataWordCount = structReader.Struct_DataWordCount; - def.StructPointerCount = structReader.Struct_PointerCount; - - if (structReader.Struct_DiscriminantCount > 0) - { - def.UnionInfo = new TypeDefinition.DiscriminationInfo( - structReader.Struct_DiscriminantCount, - 16u * structReader.Struct_DiscriminantOffset); - } - - return ProcessInterfaceOrStructTail(def, structReader, state); - } - - TypeDefinition ProcessParameterList(Schema.Node.Reader reader, Schema.Brand.Reader brandReader, List list, Pass2State state) - { -//# 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.) - - if (!reader.IsStruct) - { - throw new InvalidSchemaException("Expected a struct"); - } - - var def = ProcessTypeDef(reader.Id, state, TypeTag.Struct); - - if (reader.ScopeId == 0) - { - // Auto-generated => Named parameter list - foreach (var field in def.Fields) list.Add(field); - return def; - } - else - { - // Single, anonymous, struct-typed parameter - var type = Types.FromDefinition(def); - ProcessBrand(brandReader, type, state); - var anon = new Field() { Type = type }; - list.Add(anon); - return null; - } - } - - TypeDefinition ProcessInterface(Schema.Node.Reader ifaceReader, TypeDefinition def, Pass2State state) - { - foreach (var superClassReader in ifaceReader.Interface_Superclasses) - { - var superClass = ProcessTypeDef(superClassReader.Id, state, TypeTag.Interface); - def.Superclasses.Add(Types.FromDefinition(superClass)); - } - - return ProcessInterfaceOrStructTail(def, ifaceReader, state); - } - - TypeDefinition ProcessEnum(Schema.Node.Reader enumReader, TypeDefinition def, Pass2State state) - { - foreach (var fieldReader in enumReader.Enumerants) - { - var field = new Enumerant() - { - TypeDefinition = def, - Literal = fieldReader.Name, - CodeOrder = fieldReader.CodeOrder - }; - - if (fieldReader.Ordinal_IsExplicit) - { - field.Ordinal = fieldReader.Ordinal_Explicit; - } - - def.Enumerants.Add(field); - } - return def; - } - - Constant ProcessConst(Schema.Node.Reader constReader, Constant @const, Pass2State state) - { - var value = ProcessValue(constReader.Const_Value); - value.Type = ProcessType(constReader.Const_Type, state); - @const.Value = value; - return @const; - } - - TypeDefinition ProcessTypeDef(ulong id, Pass2State state, TypeTag tag = default) - { - var def = ProcessNode(id, state, true, tag); - var typeDef = def as TypeDefinition; - if (typeDef == null) - throw new ArgumentException( - $"Expected node {id.StrId()} to be a TypeDefinition but got {def.GetType().Name} instead.", - nameof(id)); - return typeDef; - } - - IDefinition ProcessNode(ulong id, Pass2State state, bool mustExist, TypeTag tag = default) - { - if (!(IdToNode(id, mustExist) is Schema.Node.Reader node)) return null; - var kind = node.GetKind(); - if (tag == TypeTag.Unknown) tag = kind.GetTypeTag(); - var def = _typeDefMgr.GetExistingDef(id, tag); - if (state.processedNodes.Contains(id)) return def; - state.processedNodes.Add(id); - - switch (def) - { - case Annotation annotation: - return annotation; - case Constant constant: - def.DeclaringElement.Constants.Add(ProcessConst(node, constant, state)); - return def; - case TypeDefinition typeDef when kind == NodeKind.Enum: - return ProcessEnum(node, typeDef, state); - case TypeDefinition typeDef when kind == NodeKind.Interface: - return ProcessInterface(node, typeDef, state); - case TypeDefinition typeDef when kind == NodeKind.Struct || kind == NodeKind.Group: - return ProcessStruct(node, typeDef, state); - default: - throw new InvalidProgramException($"An unexpected node {node.StrId()} was found during the 2nd schema model building pass."); - } - } - - public static SchemaModel Create(Schema.CodeGeneratorRequest.Reader request) - { - var model = new SchemaModel(request); - model.Build(); - return model; - } - } - - public enum NodeKind - { - Unknown, - Annotation, - Const, - Enum, - File, - Interface, - Struct, - Group - } - - public static class SchemaExtensions - { - public static string GetName(this Schema.Node.Reader node) - => node.DisplayName.Substring((int)node.DisplayNamePrefixLength); - - public static string StrId(this Schema.Node.Reader node) - => $"0x{node.Id:X}"; - - public static string StrId(this ulong nodeId) - => $"0x{nodeId:X}"; - - public static NodeKind GetKind(this Schema.Node.Reader node) - { - if (node.IsStruct) - return node.Struct_IsGroup ? NodeKind.Group : NodeKind.Struct; - if (node.IsInterface) return NodeKind.Interface; - if (node.IsEnum) return NodeKind.Enum; - if (node.IsConst) return NodeKind.Const; - if (node.IsAnnotation) return NodeKind.Annotation; - if (node.IsFile) return NodeKind.File; - return NodeKind.Unknown; - } - - internal static TypeTag GetTypeTag(this NodeKind kind) - { - switch (kind) - { - case NodeKind.Enum: return TypeTag.Enum; - case NodeKind.Interface: return TypeTag.Interface; - case NodeKind.Struct: return TypeTag.Struct; - case NodeKind.Group: return TypeTag.Group; - default: return TypeTag.Unknown; - } - } - - internal static TypeTag GetTypeTag(this Schema.Node.Reader node) - => node.GetKind().GetTypeTag(); - } -} diff --git a/capnpc-csharp/Model/SpecialName.cs b/capnpc-csharp/Model/SpecialName.cs deleted file mode 100644 index 89f546f..0000000 --- a/capnpc-csharp/Model/SpecialName.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace CapnpC.Model -{ - enum SpecialName - { - NothingSpecial, - MethodParamsStruct, - MethodResultStruct - } -} diff --git a/capnpc-csharp/Model/Type.cs b/capnpc-csharp/Model/Type.cs deleted file mode 100644 index 17f2736..0000000 --- a/capnpc-csharp/Model/Type.cs +++ /dev/null @@ -1,201 +0,0 @@ -using Capnp; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; - -namespace CapnpC.Model -{ - class Type: AbstractType - { - // Representation of a type expression in the schema language - - public TypeDefinition Definition { get; set; } - // The model for all nodes that are not file nodes - they define types - - public GenericParameter Parameter { get; set; } - // A reference to type parameter in this scope - - public Type ElementType { get; set; } - // The type of a list element, if this is a list. - - readonly Dictionary _parameterBindings = - new Dictionary(); - public Type(TypeTag tag) - { - Tag = tag; - } - - public bool IsValueType - { - get - { - switch (Tag) - { - case TypeTag.AnyPointer: - case TypeTag.CapabilityPointer: - case TypeTag.Data: - case TypeTag.Group: - case TypeTag.Interface: - case TypeTag.List when ElementType.Tag != TypeTag.Void: - case TypeTag.ListPointer: - case TypeTag.Struct: - case TypeTag.StructPointer: - case TypeTag.Text: - case TypeTag.Void: - return false; - - default: - return true; - } - } - } - - public void InheritFreeParameters(IHasGenericParameters declaringType) - { - while (declaringType != null) - { - foreach (var p in declaringType.GetLocalTypeParameters()) - { - if (!_parameterBindings.ContainsKey(p)) - { - _parameterBindings[p] = Types.FromParameter(p); - } - } - - declaringType = (declaringType as TypeDefinition)?.DeclaringElement as IHasGenericParameters; - } - } - - Type SubstituteGenerics(Type type) - { - if (type == null) - { - return null; - } - - if (type.Parameter != null) - { - if (_parameterBindings.TryGetValue(type.Parameter, out var boundType)) - { - return boundType; - } - else - { - return Types.AnyPointer; - } - } - - var stype = new Type(type.Tag) - { - Definition = type.Definition, - ElementType = SubstituteGenerics(type.ElementType) - }; - - foreach (var kvp in type._parameterBindings) - { - var p = kvp.Value.Parameter; - - if (p != null && _parameterBindings.TryGetValue(p, out var boundType)) - { - stype._parameterBindings[kvp.Key] = boundType; - } - else - { - stype._parameterBindings[kvp.Key] = kvp.Value; - } - } - - return stype; - } - - Field SubstituteGenerics(Field field) - { - var result = field.Clone(); - result.Type = SubstituteGenerics(result.Type); - return result; - } - - public new IReadOnlyList Fields => Definition.Fields.LazyListSelect(SubstituteGenerics); - - public Type DeclaringType - { - get - { - var parentDef = Definition?.DeclaringElement as TypeDefinition; - // FIXME: Will become more sophisticated as soon as generics are implemented - return parentDef != null ? Types.FromDefinition(parentDef) : null; - } - } - - public (int, Type) GetRank() - { - var cur = this; - int rank = 0; - - while (cur.Tag == TypeTag.List) - { - cur = cur.ElementType; - ++rank; - } - - return (rank, cur); - } - - public IEnumerable AllImplementedClasses - { - get - { - var stk = new Stack(); - stk.Push(this); - var set = new HashSet(); - while (stk.Count > 0) - { - var def = stk.Pop(); - - if (def == null) - { - break; - } - - if (set.Add(def)) - { - foreach (var super in def.Definition.Superclasses) - { - stk.Push(super); - } - } - } - return set; - } - } - - public Type ResolveGenericParameter(GenericParameter genericParameter) - { - if (_parameterBindings.TryGetValue(genericParameter, out var type)) - { - return type; - } - else - { - return Types.AnyPointer; - } - } - - public void BindGenericParameter(GenericParameter genericParameter, Type boundType) - { - _parameterBindings.Add(genericParameter, boundType); - } - - public override bool Equals(object obj) - { - return obj is Type other && Definition == other.Definition; - } - - public override int GetHashCode() - { - return Definition?.GetHashCode() ?? 0; - } - } -} diff --git a/capnpc-csharp/Model/TypeCategory.cs b/capnpc-csharp/Model/TypeCategory.cs deleted file mode 100644 index 3411ac1..0000000 --- a/capnpc-csharp/Model/TypeCategory.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace CapnpC.Model -{ - enum TypeCategory - { - Value, - Pointer - } -} diff --git a/capnpc-csharp/Model/TypeDefinition.cs b/capnpc-csharp/Model/TypeDefinition.cs deleted file mode 100644 index dcbe512..0000000 --- a/capnpc-csharp/Model/TypeDefinition.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -namespace CapnpC.Model -{ - class TypeDefinition : AbstractType, IDefinition, IHasNestedDefinitions, IHasGenericParameters - { - public class DiscriminationInfo - { - public DiscriminationInfo(ushort numOptions, uint tagOffset) - { - NumOptions = numOptions; - TagOffset = tagOffset; - } - - public ushort NumOptions { get; } - public uint TagOffset { get; } - } - - public TypeDefinition(TypeTag tag, ulong id, IHasNestedDefinitions parent) - { - Trace.Assert(parent != null); - Tag = tag; - Id = id; - IsGenerated = (parent as IDefinition).IsGenerated; - DeclaringElement = parent; - if (tag == TypeTag.Group) - ((TypeDefinition)parent).NestedGroups.Add(this); - else - parent.NestedDefinitions.Add(this); - } - - public ulong Id { get; } - public bool IsGenerated { get; } - public IHasNestedDefinitions DeclaringElement { get; } - - public Method UsingMethod { get; set; } - public string Name { get; set; } - public SpecialName SpecialName { get; set; } - public DiscriminationInfo UnionInfo { get; set; } - public new List Fields => base.Fields; - public List Enumerants { get; } = new List(); - public ICollection NestedDefinitions { get; } = new List(); - public IEnumerable NestedTypes { get => this.GetNestedTypes(); } - public List NestedGroups { get; } = new List(); - public ICollection Constants { get; } = new List(); - public List Methods { get; } = new List(); - public List Superclasses { get; } = new List(); - public List GenericParameters { get; } = new List(); - public bool IsGeneric { get; set; } - public ushort StructDataWordCount { get; set; } - public ushort StructPointerCount { get; set; } - - public IEnumerable DefinitionHierarchy - { - get - { - IHasNestedDefinitions cur = this; - - while (cur is TypeDefinition def) - { - yield return def; - cur = def.DeclaringElement; - } - } - } - - public GenFile File - { - get - { - IHasNestedDefinitions cur = this; - while (cur is TypeDefinition def) cur = def.DeclaringElement; - return cur as GenFile; - } - } - - public IEnumerable AllTypeParameters - { - get - { - return from def in DefinitionHierarchy - from p in def.GetLocalTypeParameters() - select p; - } - } - } -} diff --git a/capnpc-csharp/Model/TypeTag.cs b/capnpc-csharp/Model/TypeTag.cs deleted file mode 100644 index 122b6d7..0000000 --- a/capnpc-csharp/Model/TypeTag.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace CapnpC.Model -{ - enum TypeTag - { - Unknown, - Void, - Bool, - S8, - U8, - S16, - U16, - S32, - U32, - S64, - U64, - F32, - F64, - List, - Data, - Text, - AnyPointer, - StructPointer, - ListPointer, - CapabilityPointer, - ParameterPointer, - ImplicitMethodParameterPointer, - Struct, - Group, - Interface, - Enum, - AnyEnum, - Const, - Annotation, - File - } -} diff --git a/capnpc-csharp/Model/Types.cs b/capnpc-csharp/Model/Types.cs deleted file mode 100644 index ee20603..0000000 --- a/capnpc-csharp/Model/Types.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; - -namespace CapnpC.Model -{ - static class Types - { - public static readonly Type Void = new Type(TypeTag.Void); - public static readonly Type Bool = new Type(TypeTag.Bool); - public static readonly Type S8 = new Type(TypeTag.S8); - public static readonly Type U8 = new Type(TypeTag.U8); - public static readonly Type S16 = new Type(TypeTag.S16); - public static readonly Type U16 = new Type(TypeTag.U16); - public static readonly Type S32 = new Type(TypeTag.S32); - public static readonly Type U32 = new Type(TypeTag.U32); - public static readonly Type S64 = new Type(TypeTag.S64); - public static readonly Type U64 = new Type(TypeTag.U64); - public static readonly Type F32 = new Type(TypeTag.F32); - public static readonly Type F64 = new Type(TypeTag.F64); - public static readonly Type AnyPointer = new Type(TypeTag.AnyPointer); - public static readonly Type StructPointer = new Type(TypeTag.StructPointer); - public static readonly Type ListPointer = new Type(TypeTag.ListPointer); - public static readonly Type CapabilityPointer = new Type(TypeTag.CapabilityPointer); - public static readonly Type Data = new Type(TypeTag.Data); - public static readonly Type Text = new Type(TypeTag.Text); - public static readonly Type AnyEnum = new Type(TypeTag.AnyEnum); - - public static Type List(Type elementType) - { - return new Type(TypeTag.List) - { - ElementType = elementType - }; - } - - public static Type FromDefinition(TypeDefinition def) - { - if (def.Tag == TypeTag.Unknown) - { - throw new InvalidOperationException("Oops, type definition is not yet valid, cannot create type"); - } - - return new Type(def.Tag) - { - Definition = def - }; - } - - public static Type FromParameter(GenericParameter genericParameter) - { - return new Type(TypeTag.AnyPointer) - { - Parameter = genericParameter - }; - } - } -} diff --git a/capnpc-csharp/Model/Value.cs b/capnpc-csharp/Model/Value.cs deleted file mode 100644 index 955e51a..0000000 --- a/capnpc-csharp/Model/Value.cs +++ /dev/null @@ -1,300 +0,0 @@ -using Capnp; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace CapnpC.Model -{ - class Value - { - public static Value Scalar(T scalar) - { - var value = new Value() - { - ScalarValue = scalar - }; - - if (typeof(T) == typeof(bool)) - value.Type = Types.Bool; - else if (typeof(T) == typeof(float)) - value.Type = Types.F32; - else if (typeof(T) == typeof(double)) - value.Type = Types.F64; - else if (typeof(T) == typeof(sbyte)) - value.Type = Types.S8; - else if (typeof(T) == typeof(byte)) - value.Type = Types.U8; - else if (typeof(T) == typeof(short)) - value.Type = Types.S16; - else if (typeof(T) == typeof(ushort)) - value.Type = Types.U16; - else if (typeof(T) == typeof(int)) - value.Type = Types.S32; - else if (typeof(T) == typeof(uint)) - value.Type = Types.U32; - else if (typeof(T) == typeof(long)) - value.Type = Types.S64; - else if (typeof(T) == typeof(ulong)) - value.Type = Types.U64; - else if (typeof(T) == typeof(string)) - value.Type = Types.Text; - else - throw new NotImplementedException(); - - return value; - } - - public Type Type { get; set; } - public object ScalarValue { get; set; } - public Capnp.DeserializerState RawValue { get; set; } - public List Items { get; } = new List(); - public int VoidListCount { get; set; } - public ushort DiscriminatorValue { get; private set; } - public List<(Field, Value)> Fields { get; } = new List<(Field, Value)>(); - - public Enumerant GetEnumerant() - { - if (Type.Tag != TypeTag.Enum) - throw new InvalidOperationException(); - - if (Type.Definition.Enumerants[0].Ordinal.HasValue) - return Type.Definition.Enumerants.Single(e => e.Ordinal == (ushort)ScalarValue); - else - return Type.Definition.Enumerants[(ushort)ScalarValue]; - } - - void DecodeStruct() - { - if (RawValue.Kind != Capnp.ObjectKind.Struct) - { - throw new NotSupportedException(); - } - - var def = Type.Definition; - - if (def.UnionInfo != null) - { - DiscriminatorValue = RawValue.ReadDataUShort(def.UnionInfo.TagOffset, ushort.MaxValue); - } - - foreach (var field in Type.Fields) - { - if (field.DiscValue.HasValue && field.DiscValue.Value != DiscriminatorValue) - continue; - - Value value = new Value() - { - Type = field.Type - }; - - switch (field.Type.Tag) - { - case TypeTag.AnyEnum: - value.ScalarValue = field.DefaultValue?.ScalarValue as ushort? ?? 0; - break; - - case TypeTag.AnyPointer: - value.RawValue = RawValue.StructReadPointer((int)field.Offset); - break; - - case TypeTag.Bool: - value.ScalarValue = RawValue.ReadDataBool(field.BitOffset.Value, (field.DefaultValue?.ScalarValue as bool?) ?? false); - break; - - case TypeTag.CapabilityPointer: - case TypeTag.Interface: - continue; - - case TypeTag.Data: - case TypeTag.Group: - case TypeTag.Struct: - case TypeTag.List: - case TypeTag.Text: - value.RawValue = RawValue.StructReadPointer((int)field.Offset); - value.Decode(); - break; - - case TypeTag.ListPointer: - case TypeTag.StructPointer: - value.RawValue = RawValue.StructReadPointer((int)field.Offset); - break; - - case TypeTag.Enum: - value.ScalarValue = field.DefaultValue?.ScalarValue as ushort? ?? ushort.MaxValue; - break; - - case TypeTag.F32: - value = Scalar(RawValue.ReadDataFloat(field.BitOffset.Value, (field.DefaultValue?.ScalarValue as float?) ?? 0.0f)); - break; - - case TypeTag.F64: - value = Scalar(RawValue.ReadDataDouble(field.BitOffset.Value, (field.DefaultValue?.ScalarValue as double?) ?? 0.0f)); - break; - - case TypeTag.S16: - value = Scalar(RawValue.ReadDataShort(field.BitOffset.Value, (field.DefaultValue?.ScalarValue as short?) ?? 0)); - break; - - case TypeTag.S32: - value = Scalar(RawValue.ReadDataInt(field.BitOffset.Value, (field.DefaultValue?.ScalarValue as int?) ?? 0)); - break; - - case TypeTag.S64: - value = Scalar(RawValue.ReadDataLong(field.BitOffset.Value, (field.DefaultValue?.ScalarValue as long?) ?? 0)); - break; - - case TypeTag.S8: - value = Scalar(RawValue.ReadDataSByte(field.BitOffset.Value, (field.DefaultValue?.ScalarValue as sbyte?) ?? 0)); - break; - - case TypeTag.U16: - value = Scalar(RawValue.ReadDataUShort(field.BitOffset.Value, (field.DefaultValue?.ScalarValue as ushort?) ?? 0)); - break; - - case TypeTag.U32: - value = Scalar(RawValue.ReadDataUInt(field.BitOffset.Value, (field.DefaultValue?.ScalarValue as uint?) ?? 0)); - break; - - case TypeTag.U64: - value = Scalar(RawValue.ReadDataULong(field.BitOffset.Value, (field.DefaultValue?.ScalarValue as ulong?) ?? 0)); - break; - - case TypeTag.U8: - value = Scalar(RawValue.ReadDataByte(field.BitOffset.Value, (field.DefaultValue?.ScalarValue as byte?) ?? 0)); - break; - - case TypeTag.Void: - continue; - - default: - throw new NotImplementedException(); - } - - Fields.Add((field, value)); - } - } - - void DecodeList() - { - switch (Type.Tag) - { - case TypeTag.Data: - Items.AddRange(RawValue.RequireList().CastByte().Select(Scalar)); - break; - - case TypeTag.List: - switch (Type.ElementType.Tag) - { - case TypeTag.AnyEnum: - case TypeTag.Enum: - Items.AddRange(RawValue.RequireList().CastUShort().Select(u => { - var v = Scalar(u); - v.Type = Type.ElementType; - return v; })); - break; - - case TypeTag.AnyPointer: - Items.AddRange(RawValue.RequireList().Cast(d => new Value() { Type = Type.ElementType, RawValue = d })); - break; - - case TypeTag.Bool: - Items.AddRange(RawValue.RequireList().CastBool().Select(Scalar)); - break; - - case TypeTag.Data: - case TypeTag.Group: - case TypeTag.Struct: - case TypeTag.List: - Items.AddRange(RawValue.RequireList().Cast(d => { - var v = new Value() { Type = Type.ElementType, RawValue = d }; - v.Decode(); - return v; - })); - break; - - case TypeTag.Text: - Items.AddRange(RawValue.RequireList().CastText2().Select(Scalar)); - break; - - case TypeTag.F32: - Items.AddRange(RawValue.RequireList().CastFloat().Select(Scalar)); - break; - - case TypeTag.F64: - Items.AddRange(RawValue.RequireList().CastDouble().Select(Scalar)); - break; - - case TypeTag.S8: - Items.AddRange(RawValue.RequireList().CastSByte().Select(Scalar)); - break; - - case TypeTag.S16: - Items.AddRange(RawValue.RequireList().CastShort().Select(Scalar)); - break; - - case TypeTag.S32: - Items.AddRange(RawValue.RequireList().CastInt().Select(Scalar)); - break; - - case TypeTag.S64: - Items.AddRange(RawValue.RequireList().CastLong().Select(Scalar)); - break; - - case TypeTag.Void: - VoidListCount = RawValue.RequireList().Count; - break; - - case TypeTag.U16: - Items.AddRange(RawValue.RequireList().CastUShort().Select(Scalar)); - break; - - case TypeTag.U32: - Items.AddRange(RawValue.RequireList().CastUInt().Select(Scalar)); - break; - - case TypeTag.U64: - Items.AddRange(RawValue.RequireList().CastULong().Select(Scalar)); - break; - - case TypeTag.U8: - Items.AddRange(RawValue.RequireList().CastByte().Select(Scalar)); - break; - - default: - throw new NotImplementedException(); - } - break; - - case TypeTag.ListPointer: - Items.AddRange(RawValue.RequireList().Cast(d => new Value() { Type = Type.ElementType, RawValue = d })); - break; - - case TypeTag.Text: - ScalarValue = RawValue.RequireList().CastText(); - break; - } - } - - public void Decode() - { - if (RawValue.Kind == ObjectKind.Nil) return; - - switch (Type.Tag) - { - case TypeTag.Group: - case TypeTag.Struct: - DecodeStruct(); - break; - - case TypeTag.List: - case TypeTag.ListPointer: - case TypeTag.Text: - case TypeTag.Data: - DecodeList(); - break; - } - - RawValue = default(Capnp.DeserializerState); - } - } -} diff --git a/capnpc-csharp/Program.cs b/capnpc-csharp/Program.cs index 3f71b4b..b8eccee 100644 --- a/capnpc-csharp/Program.cs +++ b/capnpc-csharp/Program.cs @@ -1,30 +1,14 @@ using Capnp; +using CapnpC.CSharp.Generator; using System; using System.IO; using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleToAttribute("capnpc-csharp.tests")] +using System.Security; namespace CapnpC { internal class Program { - internal static void GenerateFromStream(Stream input) - { - WireFrame segments; - - using (input) - { - segments = Framing.ReadSegments(input); - } - - var dec = DeserializerState.CreateRoot(segments); - var reader = Schema.CodeGeneratorRequest.Reader.Create(dec); - var model = Model.SchemaModel.Create(reader); - var codeGen = new Generator.CodeGenerator(model, new Generator.GeneratorOptions()); - codeGen.Generate(); - } - static void Main(string[] args) { Stream input; @@ -41,13 +25,36 @@ namespace CapnpC input = Console.OpenStandardInput(); } - try + var result = CapnpCompilation.GenerateFromStream(input); + + if (result.IsSuccess) { - GenerateFromStream(input); + foreach (var generatedFile in result.GeneratedFiles) + { + if (generatedFile.IsSuccess) + { + string outputFile = generatedFile.CapnpFilePath + ".cs"; + + try + { + File.WriteAllText(outputFile, generatedFile.GeneratedContent); + } + catch (Exception exception) + { + Console.Error.WriteLine(exception.Message); + Environment.ExitCode = -1; + } + } + else + { + Console.Error.WriteLine($"Error generating {generatedFile.CapnpFilePath}: {generatedFile.Exception.Message}"); + Environment.ExitCode = -1; + } + } } - catch (Exception exception) + else { - Console.Error.WriteLine(exception.Message); + Console.Error.WriteLine(result.Exception.Message); Environment.ExitCode = -1; } } diff --git a/capnpc-csharp/Schema/SchemaSerialization.cs b/capnpc-csharp/Schema/SchemaSerialization.cs deleted file mode 100644 index a61281a..0000000 --- a/capnpc-csharp/Schema/SchemaSerialization.cs +++ /dev/null @@ -1,1577 +0,0 @@ -using Capnp; -using System; -using System.Collections.Generic; -using System.Text; - -namespace CapnpC.Schema -{ - namespace Superclass - { - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public ulong Id => State.ReadDataULong(0); - public Brand.Reader Brand => State.ReadStruct(0, Schema.Brand.Reader.Create); - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(1, 1); - } - - public ulong Id - { - get => this.ReadDataULong(0); - set => this.WriteData(0, value); - } - - public Brand.Writer Brand - { - get => BuildPointer(0); - set => Link(0, value); - } - } - } - - namespace Method - { - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public string Name => State.ReadText(0); - public ushort CodeOrder => State.ReadDataUShort(0); - public IReadOnlyList ImplicitParameters => State.ReadListOfStructs(4, Node.Parameter.Reader.Create); - public ulong ParamStructType => State.ReadDataULong(64); - public Brand.Reader ParamBrand => State.ReadStruct(2, Brand.Reader.Create); - public ulong ResultStructType => State.ReadDataULong(128); - public Brand.Reader ResultBrand => State.ReadStruct(3, Brand.Reader.Create); - public IReadOnlyList Annotations => State.ReadListOfStructs(1, Annotation.Reader.Create); - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(5, 3); - } - - public string Name - { - get => ReadText(0); - set => WriteText(0, value); - } - - public ushort CodeOrder - { - get => this.ReadDataUShort(0); - set => this.WriteData(0, value); - } - - public ListOfStructsSerializer ImplicitParameters - { - get => BuildPointer>(4); - set => Link(4, value); - } - - public ref ulong ParamStructType => ref this.RefData(8); - - public Brand.Writer ParamBrand - { - get => BuildPointer(2); - set => Link(2, value); - } - - public ulong ResultStructType - { - get => this.ReadDataULong(128); - set => this.WriteData(128, value); - } - - public Brand.Writer ResultBrand - { - get => BuildPointer(3); - set => Link(3, value); - } - - public ListOfStructsSerializer Annotations - { - get => BuildPointer>(1); - set => Link(1, value); - } - } - } - - namespace Type - { - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public ushort Tag => State.ReadDataUShort(0); - public bool IsVoid => Tag == 0; - public bool IsBool => Tag == 1; - public bool IsInt8 => Tag == 2; - public bool IsInt16 => Tag == 3; - public bool IsInt32 => Tag == 4; - public bool IsInt64 => Tag == 5; - public bool IsUInt8 => Tag == 6; - public bool IsUInt16 => Tag == 7; - public bool IsUInt32 => Tag == 8; - public bool IsUInt64 => Tag == 9; - public bool IsFloat32 => Tag == 10; - public bool IsFloat64 => Tag == 11; - public bool IsText => Tag == 12; - public bool IsData => Tag == 13; - public bool IsList => Tag == 14; - public Reader List_ElementType => IsList ? State.ReadStruct(0, Create) : default; - public bool IsEnum => Tag == 15; - public ulong Enum_TypeId => IsEnum ? State.ReadDataULong(64) : 0; - public Brand.Reader Enum_Brand => IsEnum ? State.ReadStruct(0, Brand.Reader.Create) : default; - public bool IsStruct => Tag == 16; - public ulong Struct_TypeId => IsStruct ? State.ReadDataULong(64) : 0; - public Brand.Reader Struct_Brand => IsStruct ? State.ReadStruct(0, Brand.Reader.Create) : default; - public bool IsInterface => Tag == 17; - public ulong Interface_TypeId => IsInterface ? State.ReadDataULong(64) : 0; - public Brand.Reader Interface_Brand => IsInterface ? State.ReadStruct(0, Brand.Reader.Create) : default; - public bool IsAnyPointer => Tag == 18; - public ushort AnyPointer_Tag => IsAnyPointer ? State.ReadDataUShort(64) : default; - public bool AnyPointer_IsUnconstrained => IsAnyPointer && AnyPointer_Tag == 0; - public ushort AnyPointer_Unconstrained_Tag => AnyPointer_IsUnconstrained ? State.ReadDataUShort(80) : (ushort)0; - public bool AnyPointer_Unconstrained_IsAnyKind => AnyPointer_IsUnconstrained && AnyPointer_Unconstrained_Tag == 0; - public bool AnyPointer_Unconstrained_IsStruct => AnyPointer_IsUnconstrained && AnyPointer_Unconstrained_Tag == 1; - public bool AnyPointer_Unconstrained_IsList => AnyPointer_IsUnconstrained && AnyPointer_Unconstrained_Tag == 2; - public bool AnyPointer_Unconstrained_IsCapability => AnyPointer_IsUnconstrained && AnyPointer_Unconstrained_Tag == 3; - public bool AnyPointer_IsParameter => IsAnyPointer && AnyPointer_Tag == 1; - public ulong AnyPointer_Parameter_ScopeId => AnyPointer_IsParameter ? State.ReadDataULong(128) : 0; - public ushort AnyPointer_Parameter_ParameterIndex => AnyPointer_IsParameter ? State.ReadDataUShort(80) : (ushort)0; - public bool AnyPointer_IsImplicitMethodParameter => AnyPointer_Tag == 2; - public ushort AnyPointer_ImplicitMethodParameter_ParameterIndex => AnyPointer_IsImplicitMethodParameter ? State.ReadDataUShort(80) : default; - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(3, 1); - } - - public ref ushort Tag => ref this.RefData(0); - - public bool IsVoid - { - get => Tag == 0; - set => Tag = 0; - } - - public bool IsBool - { - get => Tag == 1; - set => Tag = 1; - } - - public bool IsInt8 - { - get => Tag == 2; - set => Tag = 2; - } - - public bool IsInt16 - { - get => Tag == 3; - set => Tag = 3; - } - - public bool IsInt32 - { - get => Tag == 4; - set => Tag = 4; - } - - public bool IsInt64 - { - get => Tag == 5; - set => Tag = 5; - } - - public bool IsUInt8 - { - get => Tag == 6; - set => Tag = 6; - } - - public bool IsUInt16 - { - get => Tag == 7; - set => Tag = 7; - } - - public bool IsUInt32 - { - get => Tag == 8; - set => Tag = 8; - } - - public bool IsUInt64 - { - get => Tag == 9; - set => Tag = 9; - } - - public bool IsFloat32 - { - get => Tag == 10; - set => Tag = 10; - } - - public bool IsFloat64 - { - get => Tag == 11; - set => Tag = 11; - } - - public bool IsText - { - get => Tag == 12; - set => Tag = 12; - } - - public bool IsData - { - get => Tag == 13; - set => Tag = 13; - } - - public bool IsList - { - get => Tag == 14; - set => Tag = 14; - } - - public Writer List_ElementType - { - get => IsList ? BuildPointer(0) : default; - set { Link(0, value); } - } - - public bool IsEnum - { - get => Tag == 15; - set => Tag = 15; - } - - public ulong Enum_TypeId - { - get => IsEnum ? this.ReadDataULong(64) : 0; - set { this.WriteData(64, value); } - } - - public Brand.Writer Enum_Brand - { - get => IsEnum ? BuildPointer(0) : default; - set => Link(0, value); - } - - public bool IsStruct - { - get => Tag == 16; - set => Tag = 16; - } - - public ulong Struct_TypeId - { - get => IsStruct ? this.ReadDataULong(64) : 0; - set => this.WriteData(64, value); - } - - public Brand.Writer Struct_Brand - { - get => IsStruct ? BuildPointer(0) : default; - set => Link(0, value); - } - - public bool IsInterface - { - get => Tag == 17; - set => Tag = 17; - } - - public ulong Interface_TypeId - { - get => IsStruct ? this.ReadDataULong(64) : 0; - set => this.WriteData(64, value); - } - - public Brand.Writer Interface_Brand - { - get => IsStruct ? BuildPointer(0) : default; - set => Link(0, value); - } - - public bool IsAnyPointer - { - get => Tag == 18; - set => Tag = 18; - } - - public ushort AnyPointer_Tag - { - get => IsAnyPointer ? this.ReadDataUShort(64) : default; - set => this.WriteData(64, value); - } - - public bool AnyPointer_IsUnconstrained - { - get => IsAnyPointer && AnyPointer_Tag == 0; - set => AnyPointer_Tag = 0; - } - - public ushort AnyPointer_Unconstrained_Tag - { - get => AnyPointer_IsUnconstrained ? this.ReadDataUShort(80) : (ushort)0; - set => this.WriteData(80, value); - } - - public bool AnyPointer_Unconstrained_IsAnyKind - { - get => AnyPointer_IsUnconstrained && AnyPointer_Unconstrained_Tag == 0; - set => AnyPointer_Unconstrained_Tag = 0; - } - - public bool AnyPointer_Unconstrained_IsStruct - { - get => AnyPointer_IsUnconstrained && AnyPointer_Unconstrained_Tag == 1; - set => AnyPointer_Unconstrained_Tag = 1; - } - - public bool AnyPointer_Unconstrained_IsList - { - get => AnyPointer_IsUnconstrained && AnyPointer_Unconstrained_Tag == 2; - set => AnyPointer_Unconstrained_Tag = 2; - } - - public bool AnyPointer_Unconstrained_IsCapability - { - get => AnyPointer_IsUnconstrained && AnyPointer_Unconstrained_Tag == 3; - set => AnyPointer_Unconstrained_Tag = 3; - } - - public bool AnyPointer_IsParameter - { - get => IsAnyPointer && AnyPointer_Tag == 1; - set => AnyPointer_Tag = 1; - } - - public ulong AnyPointer_Parameter_ScopeId - { - get => AnyPointer_IsParameter ? this.ReadDataULong(128) : 0; - set => this.WriteData(128, value); - } - - public ushort AnyPointer_Parameter_ParameterIndex - { - get => AnyPointer_IsParameter ? this.ReadDataUShort(80) : (ushort)0; - set => this.WriteData(80, value); - } - - public bool AnyPointer_IsImplicitMethodParameter - { - get => AnyPointer_Tag == 2; - set => AnyPointer_Tag = 2; - } - - public ushort AnyPointer_ImplicitMethodParameter_ParameterIndex - { - get => AnyPointer_IsImplicitMethodParameter ? this.ReadDataUShort(80) : default; - set => this.WriteData(80, value); - } - } - } - - namespace Brand - { - namespace Scope - { - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public ulong ScopeId => State.ReadDataULong(0); - public ushort Tag => State.ReadDataUShort(64); - public bool IsBind => Tag == 0; - public IReadOnlyList Bind => IsBind ? State.ReadListOfStructs(0, Binding.Reader.Create) : null; - public bool IsInherit => Tag == 1; - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(2, 1); - } - - public ulong ScopeId - { - get => this.ReadDataULong(0); - set => this.WriteData(0, value); - } - - public ushort Tag - { - get => this.ReadDataUShort(64); - set => this.WriteData(64, value); - } - - public bool IsBind - { - get => Tag == 0; - set => Tag = 0; - } - - public ListOfStructsSerializer Bind - { - get => IsBind ? BuildPointer>(0) : default; - set => Link(0, value); - } - - public bool IsInherit - { - get => Tag == 1; - set => Tag = 1; - } - } - - namespace Binding - { - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public ushort Tag => State.ReadDataUShort(0); - public bool IsUnbound => Tag == 0; - public bool IsType => Tag == 1; - public Type.Reader Type => IsType ? State.ReadStruct(0, Schema.Type.Reader.Create) : default; - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(1, 1); - } - - public ushort Tag - { - get => this.ReadDataUShort(0); - set => this.WriteData(0, value); - } - - public bool IsUnbound - { - get => Tag == 0; - set => Tag = 0; - } - - public bool IsType - { - get => Tag == 1; - set => Tag = 1; - } - - public Type.Writer Type - { - get => IsType ? BuildPointer(0) : default; - set => Link(0, value); - } - } - } - } - - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public IReadOnlyList Scopes => State.ReadListOfStructs(0, Scope.Reader.Create); - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(0, 1); - } - - public ListOfStructsSerializer Scopes - { - get => BuildPointer>(0); - set => Link(0, value); - } - } - } - - namespace Value - { - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public ushort Tag => State.ReadDataUShort(0); - public bool IsVoid => Tag == 0; - public bool IsBool => Tag == 1; - public bool Bool => IsBool ? State.ReadDataBool(16) : default; - public bool IsInt8 => Tag == 2; - public sbyte Int8 => IsInt8 ? State.ReadDataSByte(16) : default; - public bool IsInt16 => Tag == 3; - public short Int16 => IsInt16 ? State.ReadDataShort(16) : default; - public bool IsInt32 => Tag == 4; - public int Int32 => IsInt32 ? State.ReadDataInt(32) : default; - public bool IsInt64 => Tag == 5; - public long Int64 => IsInt64 ? State.ReadDataLong(64) : default; - public bool IsUInt8 => Tag == 6; - public byte UInt8 => IsUInt8 ? State.ReadDataByte(16) : default; - public bool IsUInt16 => Tag == 7; - public ushort UInt16 => IsUInt16 ? State.ReadDataUShort(16) : default; - public bool IsUInt32 => Tag == 8; - public uint UInt32 => IsUInt32 ? State.ReadDataUInt(32) : default; - public bool IsUInt64 => Tag == 9; - public ulong UInt64 => IsUInt64 ? State.ReadDataULong(64) : default; - public bool IsFloat32 => Tag == 10; - public float Float32 => IsFloat32 ? State.ReadDataFloat(32) : default; - public bool IsFloat64 => Tag == 11; - public double Float64 => IsFloat64 ? State.ReadDataDouble(64) : default; - public bool IsText => Tag == 12; - public string Text => IsText ? State.ReadText(0) : default; - public bool IsData => Tag == 13; - public ListDeserializer Data => IsData ? State.ReadList(0) : default; - public bool IsList => Tag == 14; - public DeserializerState List => IsList ? State.StructReadPointer(0) : default; - public bool IsEnum => Tag == 15; - public ushort Enum => IsEnum ? State.ReadDataUShort(16) : default; - public bool IsStruct => Tag == 16; - public DeserializerState Struct => IsStruct ? State.StructReadPointer(0) : default; - public bool IsInterface => Tag == 17; - public bool IsAnyPointer => Tag == 18; - public DeserializerState AnyPointer => IsAnyPointer ? State.StructReadPointer(0) : default; - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(2, 1); - } - - public ushort Tag - { - get => this.ReadDataUShort(0); - set => this.WriteData(0, value); - } - - public bool IsVoid - { - get => Tag == 0; - set => Tag = 0; - } - - public bool IsBool - { - get => Tag == 1; - set => Tag = 1; - } - - public bool Bool - { - get => IsBool ? this.ReadDataBool(16) : default; - set => this.WriteData(16, value); - } - - public bool IsInt8 - { - get => Tag == 2; - set => Tag = 2; - } - - public sbyte Int8 - { - get => IsInt8 ? this.ReadDataSByte(16) : default; - set => this.WriteData(16, value); - } - - public bool IsInt16 - { - get => Tag == 3; - set => Tag = 3; - } - - public short Int16 - { - get => IsInt16 ? this.ReadDataShort(16) : default; - set => this.WriteData(16, value); - } - - public bool IsInt32 - { - get => Tag == 4; - set => Tag = 4; - } - - public int Int32 - { - get => IsInt32 ? this.ReadDataInt(32) : default; - set => this.WriteData(32, value); - } - - public bool IsInt64 - { - get => Tag == 5; - set => Tag = 5; - } - - public long Int64 - { - get => IsInt64 ? this.ReadDataLong(64) : default; - set => this.WriteData(64, value); - } - - public bool IsUInt8 - { - get => Tag == 6; - set => Tag = 6; - } - - public byte UInt8 - { - get => IsUInt8 ? this.ReadDataByte(16) : default; - set => this.WriteData(16, value); - } - - public bool IsUInt16 - { - get => Tag == 7; - set => Tag = 7; - } - - public ushort UInt16 - { - get => IsUInt16 ? this.ReadDataUShort(16) : default; - set => this.WriteData(16, value); - } - - public bool IsUInt32 - { - get => Tag == 8; - set => Tag = 8; - } - - public uint UInt32 - { - get => IsUInt32 ? this.ReadDataUInt(32) : default; - set => this.WriteData(32, value); - } - - public bool IsUInt64 - { - get => Tag == 9; - set => Tag = 9; - } - - public ulong UInt64 - { - get => IsUInt64 ? this.ReadDataULong(64) : default; - set => this.WriteData(64, value); - } - - public bool IsFloat32 - { - get => Tag == 10; - set => Tag = 10; - } - - public float Float32 - { - get => IsFloat32 ? this.ReadDataFloat(32) : default; - set => this.WriteData(32, value); - } - - public bool IsFloat64 - { - get => Tag == 11; - set => Tag = 11; - } - - public double Float64 - { - get => IsFloat64 ? this.ReadDataDouble(64) : default; - set => this.WriteData(64, value); - } - - public bool IsText - { - get => Tag == 12; - set => Tag = 12; - } - - public string Text - { - get => IsText ? ReadText(0) : default; - set => WriteText(0, value); - } - - public bool IsData - { - get => Tag == 13; - set => Tag = 13; - } - - public SerializerState Data - { - get => IsData ? BuildPointer(0) : default; - set => Link(0, value); - } - - public bool IsList - { - get => Tag == 14; - set => Tag = 14; - } - - public SerializerState List - { - get => IsList ? BuildPointer(0) : default; - set => Link(0, value); - } - - public bool IsEnum - { - get => Tag == 15; - set => Tag = 15; - } - - public ushort Enum - { - get => IsEnum ? this.ReadDataUShort(16) : default; - set => this.WriteData(16, value); - } - - public bool IsStruct - { - get => Tag == 16; - set => Tag = 16; - } - - public SerializerState Struct - { - get => IsStruct ? BuildPointer(0) : default; - set => Link(0, value); - } - - public bool IsInterface - { - get => Tag == 17; - set => Tag = 17; - } - - public bool IsAnyPointer - { - get => Tag == 18; - set => Tag = 18; - } - - public SerializerState AnyPointer - { - get => IsAnyPointer ? BuildPointer(0) : default; - set => Link(0, value); - } - } - } - - namespace Annotation - { - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public ulong Id => State.ReadDataULong(0); - public Brand.Reader Brand => State.ReadStruct(1, Schema.Brand.Reader.Create); - public Value.Reader Value => State.ReadStruct(0, Schema.Value.Reader.Create); - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(1, 2); - } - - public ref ulong Id => ref this.RefData(0); - - public Brand.Writer Brand - { - get => BuildPointer(1); - set => Link(1, value); - } - - public Value.Writer Value - { - get => BuildPointer(0); - set => Link(0, value); - } - } - } - - public enum ElementSize: ushort - { - Empty = 0, - Bit = 1, - Byte = 2, - TwoBytes = 3, - FourBytes = 4, - EightBytes = 5, - Pointer = 6, - InlineComposite = 7 - } - - namespace Field - { - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public string Name => State.ReadText(0); - public ushort CodeOrder => State.ReadDataUShort(0); - public IReadOnlyList Annotations => State.ReadListOfStructs(1, Annotation.Reader.Create); - public ushort DiscriminantValue => State.ReadDataUShort(16, 65535); - public ushort Tag => State.ReadDataUShort(64); - public bool IsSlot => Tag == 0; - public uint Slot_Offset => IsSlot ? State.ReadDataUInt(32) : default; - public Type.Reader Slot_Type => IsSlot ? State.ReadStruct(2, Type.Reader.Create) : default; - public Value.Reader Slot_DefaultValue => IsSlot ? State.ReadStruct(3, Value.Reader.Create) : default; - public bool Slot_HadExplicitDefault => IsSlot ? State.ReadDataBool(128) : default; - public bool IsGroup => Tag == 1; - public ulong Group_TypeId => IsGroup ? State.ReadDataULong(128) : default; - public ushort Ordinal_Tag => State.ReadDataUShort(80); - public bool Ordinal_IsImplicit => Ordinal_Tag == 0; - public bool Ordinal_IsExplicit => Ordinal_Tag == 1; - public ushort Ordinal_Explicit => Ordinal_IsExplicit ? State.ReadDataUShort(96) : default; - - public const ushort NoDiscriminant = 0xffff; - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(3, 3); - } - - public string Name - { - get => ReadText(0); - set => WriteText(0, value); - } - - public ref ushort CodeOrder => ref this.RefData(0); - - public ListOfStructsSerializer Annotations - { - get => BuildPointer>(1); - set => Link(1, value); - } - - public ushort DiscriminantValue - { - get => this.ReadDataUShort(16, 65535); - set => this.WriteData(16, value, (ushort)65535); - } - - public ref ushort Tag => ref this.RefData(8); - - public bool IsSlot - { - get => Tag == 0; - set => Tag = 0; - } - - public uint Slot_Offset - { - get => IsSlot ? this.ReadDataUInt(32) : default; - set => this.WriteData(32, value); - } - - public Type.Writer Slot_Type - { - get => IsSlot ? BuildPointer(2) : default; - set => Link(2, value); - } - - public Value.Writer Slot_DefaultValue - { - get => IsSlot ? BuildPointer(3) : default; - set => Link(3, value); - } - - public bool Slot_HadExplicitDefault - { - get => IsSlot ? this.ReadDataBool(128) : default; - set => this.WriteData(128, value); - } - - public bool IsGroup - { - get => Tag == 1; - set => Tag = 1; - } - - public ref ulong Group_TypeId => ref this.RefData(2); - - public ref ushort Ordinal_Tag => ref this.RefData(5); - - public bool Ordinal_IsImplicit - { - get => Ordinal_Tag == 0; - set => Ordinal_Tag = 0; - } - - public bool Ordinal_IsExplicit - { - get => Ordinal_Tag == 1; - set => Ordinal_Tag = 1; - } - - public ref ushort Ordinal_Explicit => ref this.RefData(6); - } - } - - namespace Node - { - namespace Parameter - { - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public string Name => State.ReadText(0); - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(0, 1); - } - - public string Name - { - get => ReadText(0); - set => WriteText(0, value); - } - } - } - - namespace NestedNode - { - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public string Name => State.ReadText(0); - public ulong Id => State.ReadDataULong(0); - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(1, 1); - } - - public string Name - { - get => ReadText(0); - set => WriteText(0, value); - } - - public ref ulong Id => ref this.RefData(0); - } - } - - namespace SourceInfo - { - namespace Member - { - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public string DocComment => State.ReadText(0); - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(0, 1); - } - - public string DocComment - { - get => ReadText(0); - set => WriteText(0, value); - } - } - } - - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public ulong Id => State.ReadDataULong(0); - public string DocComment => State.ReadText(0); - public IReadOnlyList Members => State.ReadListOfStructs(1, Member.Reader.Create); - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(1, 2); - } - - public ref ulong Id => ref this.RefData(0); - - public string DocComment - { - get => ReadText(0); - set => WriteText(0, value); - } - - public ListOfStructsSerializer Members - { - get => BuildPointer>(1); - set => Link(1, value); - } - } - } - - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public ulong Id => State.ReadDataULong(0); - public string DisplayName => State.ReadText(0); - public uint DisplayNamePrefixLength => State.ReadDataUInt(64); - public ulong ScopeId => State.ReadDataULong(128); - public IReadOnlyList Parameters => State.ReadListOfStructs(5, Parameter.Reader.Create); - public bool IsGeneric => State.ReadDataBool(288); - public IReadOnlyList NestedNodes => State.ReadListOfStructs(1, NestedNode.Reader.Create); - public IReadOnlyList Annotations => State.ReadListOfStructs(2, Annotation.Reader.Create); - public ushort Tag => State.ReadDataUShort(96); - public bool IsFile => Tag == 0; - public bool IsStruct => Tag == 1; - public ushort Struct_DataWordCount => IsStruct ? State.ReadDataUShort(112) : default; - public ushort Struct_PointerCount => IsStruct ? State.ReadDataUShort(192) : default; - public ElementSize Struct_PreferredListEncoding => IsStruct ? (ElementSize)State.ReadDataUShort(208) : default; - public bool Struct_IsGroup => IsStruct ? State.ReadDataBool(224) : default; - public ushort Struct_DiscriminantCount => IsStruct ? State.ReadDataUShort(240) : default; - public uint Struct_DiscriminantOffset => IsStruct ? State.ReadDataUInt(256) : default; - public IReadOnlyList Fields => IsStruct ? State.ReadListOfStructs(3, Field.Reader.Create) : default; - public bool IsEnum => Tag == 2; - public IReadOnlyList Enumerants => IsEnum ? State.ReadListOfStructs(3, Field.Reader.Create) : default; - public bool IsInterface => Tag == 3; - public IReadOnlyList Interface_Methods => IsInterface ? State.ReadListOfStructs(3, Method.Reader.Create) : default; - public IReadOnlyList Interface_Superclasses => IsInterface ? State.ReadListOfStructs(4, Superclass.Reader.Create) : default; - public bool IsConst => Tag == 4; - public Type.Reader Const_Type => IsConst ? State.ReadStruct(3, Type.Reader.Create) : default; - public Value.Reader Const_Value => IsConst ? State.ReadStruct(4, Value.Reader.Create) : default; - public bool IsAnnotation => Tag == 5; - public Type.Reader Annotation_Type => IsAnnotation ? State.ReadStruct(3, Type.Reader.Create) : default; - public bool Annotation_TargetsFile => IsAnnotation ? State.ReadDataBool(112) : default; - public bool Annotation_TargetsConst => IsAnnotation ? State.ReadDataBool(113) : default; - public bool Annotation_TargetsEnum => IsAnnotation ? State.ReadDataBool(114) : default; - public bool Annotation_TargetsEnumerant => IsAnnotation ? State.ReadDataBool(115) : default; - public bool Annotation_TargetsStruct => IsAnnotation ? State.ReadDataBool(116) : default; - public bool Annotation_TargetsField => IsAnnotation ? State.ReadDataBool(117) : default; - public bool Annotation_TargetsUnion => IsAnnotation ? State.ReadDataBool(118) : default; - public bool Annotation_TargetsGroup => IsAnnotation ? State.ReadDataBool(119) : default; - public bool Annotation_TargetsInterface => IsAnnotation ? State.ReadDataBool(120) : default; - public bool Annotation_TargetsMethod => IsAnnotation ? State.ReadDataBool(121) : default; - public bool Annotation_TargetsParam => IsAnnotation ? State.ReadDataBool(122) : default; - public bool Annotation_TargetsAnnotation => IsAnnotation ? State.ReadDataBool(123) : default; - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(5, 6); - } - - public ulong Id - { - get => this.ReadDataULong(0); - set => this.WriteData(0, value); - } - - public string DisplayName - { - get => ReadText(0); - set => WriteText(0, value); - } - - public ref uint DisplayNamePrefixLength => ref this.RefData(2); - - public ref ulong ScopeId => ref this.RefData(2); - - public ListOfStructsSerializer Parameters - { - get => BuildPointer>(5); - set => Link(5, value); - } - - public bool IsGeneric - { - get => this.ReadDataBool(288); - set => this.WriteData(288, value); - } - - public ListOfStructsSerializer NestedNodes - { - get => BuildPointer>(1); - set => Link(1, value); - } - - public ListOfStructsSerializer Annotations - { - get => BuildPointer>(2); - set => Link(2, value); - } - - public ref ushort Tag => ref this.RefData(6); - - public bool IsFile - { - get => Tag == 0; - set => Tag = 0; - } - - public bool IsStruct - { - get => Tag == 1; - set => Tag = 1; - } - - public ref ushort Struct_DataWordCount => ref this.RefData(7); - - public ref ushort Struct_PointerCount => ref this.RefData(12); - - public ref ElementSize Struct_PreferredListEncoding => ref this.RefData(13); - - public bool Struct_IsGroup - { - get => IsStruct ? this.ReadDataBool(224) : default; - set => this.WriteData(224, value); - } - - public ref ushort Struct_DiscriminantCount => ref this.RefData(15); - - public ref uint Struct_DiscriminantOffset => ref this.RefData(8); - - public ListOfStructsSerializer Fields - { - get => BuildPointer>(3); - set => Link(3, value); - } - - public bool IsEnum - { - get => Tag == 2; - set => Tag = 2; - } - - public ListOfStructsSerializer Enumerants - { - get => BuildPointer>(3); - set => Link(3, value); - } - - public bool IsInterface - { - get => Tag == 3; - set => Tag = 3; - } - - public ListOfStructsSerializer Interface_Methods - { - get => BuildPointer>(3); - set => Link(3, value); - } - - public ListOfStructsSerializer Interface_Superclasses - { - get => IsInterface ? BuildPointer>(4) : default; - set => Link(4, value); - } - - public bool IsConst - { - get => Tag == 4; - set => Tag = 4; - } - - public Type.Writer Const_Type - { - get => IsConst ? BuildPointer(3) : default; - set => Link(3, value); - } - - public Value.Writer Const_Value - { - get => IsConst ? BuildPointer(4) : default; - set => Link(4, value); - } - - public bool IsAnnotation - { - get => Tag == 5; - set => Tag = 5; - } - - public Type.Writer Annotation_Type - { - get => IsAnnotation ? BuildPointer(3) : default; - set => Link(3, value); - } - - public bool Annotation_TargetsFile - { - get => IsAnnotation ? this.ReadDataBool(112) : default; - set => this.WriteData(112, value); - } - - public bool Annotation_TargetsConst - { - get => IsAnnotation ? this.ReadDataBool(113) : default; - set => this.WriteData(113, value); - } - - public bool Annotation_TargetsEnum - { - get => IsAnnotation ? this.ReadDataBool(114) : default; - set => this.WriteData(114, value); - } - - public bool Annotation_TargetsEnumerant - { - get => IsAnnotation ? this.ReadDataBool(115) : default; - set => this.WriteData(115, value); - } - - public bool Annotation_TargetsStruct - { - get => IsAnnotation ? this.ReadDataBool(116) : default; - set => this.WriteData(116, value); - } - - public bool Annotation_TargetsField - { - get => IsAnnotation ? this.ReadDataBool(117) : default; - set => this.WriteData(117, value); - } - - public bool Annotation_TargetsUnion - { - get => IsAnnotation ? this.ReadDataBool(118) : default; - set => this.WriteData(118, value); - } - - public bool Annotation_TargetsGroup - { - get => IsAnnotation ? this.ReadDataBool(119) : default; - set => this.WriteData(119, value); - } - - public bool Annotation_TargetsInterface - { - get => IsAnnotation ? this.ReadDataBool(120) : default; - set => this.WriteData(120, value); - } - - public bool Annotation_TargetsMethod - { - get => IsAnnotation ? this.ReadDataBool(121) : default; - set => this.WriteData(121, value); - } - - public bool Annotation_TargetsParam - { - get => IsAnnotation ? this.ReadDataBool(122) : default; - set => this.WriteData(122, value); - } - - public bool Annotation_TargetsAnnotation - { - get => IsAnnotation ? this.ReadDataBool(123) : default; - set => this.WriteData(123, value); - } - } - } - - namespace CapnpVersion - { - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public ushort Major => State.ReadDataUShort(0); - public byte Minor => State.ReadDataByte(16); - public byte Micro => State.ReadDataByte(24); - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(1, 0); - } - - public ref ushort Major => ref this.RefData(0); - public ref byte Minor => ref this.RefData(2); - public ref byte Micro => ref this.RefData(3); - } - } - - namespace CodeGeneratorRequest - { - namespace RequestedFile - { - namespace Import - { - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public ulong Id => State.ReadDataULong(0); - public string Name => State.ReadText(0); - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(1, 1); - } - - public ref ulong Id => ref this.RefData(0); - - public string Name - { - get => ReadText(0); - set => WriteText(0, value); - } - } - } - - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public ulong Id => State.ReadDataULong(0); - public string Filename => State.ReadText(0); - public IReadOnlyList Imports => State.ReadListOfStructs(1, Import.Reader.Create); - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(1, 2); - } - - public ref ulong Id => ref this.RefData(0); - - public string Filename - { - get => ReadText(0); - set => WriteText(0, value); - } - - public ListOfStructsSerializer Imports - { - get => BuildPointer>(1); - set => Link(1, value); - } - } - } - - public struct Reader - { - public DeserializerState State { get; } - - public Reader(DeserializerState ctx) - { - State = ctx; - } - - public static Reader Create(DeserializerState ctx) => new Reader(ctx); - - public CapnpVersion.Reader CapnpVersion => State.ReadStruct(2, Schema.CapnpVersion.Reader.Create); - public IReadOnlyList Nodes => State.ReadListOfStructs(0, Node.Reader.Create); - public IReadOnlyList SourceInfo => State.ReadListOfStructs(3, Node.SourceInfo.Reader.Create); - public IReadOnlyList RequestedFiles => State.ReadListOfStructs(1, RequestedFile.Reader.Create); - } - - public class Writer: SerializerState - { - public Writer() - { - SetStruct(0, 3); - } - - public CapnpVersion.Writer CapnpVersion - { - get => BuildPointer(2); - set => Link(2, value); - } - - public ListOfStructsSerializer Nodes - { - get => BuildPointer>(0); - set => Link(0, value); - } - - public ListOfStructsSerializer SourceInfo - { - get => BuildPointer>(3); - set => Link(3, value); - } - - public ListOfStructsSerializer RequestedFiles - { - get => BuildPointer>(1); - set => Link(1, value); - } - } - } -} diff --git a/capnpc-csharp/Schema/schema-with-offsets.capnp b/capnpc-csharp/Schema/schema-with-offsets.capnp deleted file mode 100644 index 45fe760..0000000 --- a/capnpc-csharp/Schema/schema-with-offsets.capnp +++ /dev/null @@ -1,235 +0,0 @@ -# schema.capnp -@0xa93fc509624c72d9; -$import "/capnp/c++.capnp".namespace("capnp::schema"); -struct Node @0xe682ab4cf923a417 { # 40 bytes, 6 ptrs - id @0 :UInt64; # bits[0, 64) - displayName @1 :Text; # ptr[0] - displayNamePrefixLength @2 :UInt32; # bits[64, 96) - scopeId @3 :UInt64; # bits[128, 192) - parameters @32 :List(Parameter); # ptr[5] - isGeneric @33 :Bool; # bits[288, 289) - nestedNodes @4 :List(NestedNode); # ptr[1] - annotations @5 :List(Annotation); # ptr[2] - union { # tag bits [96, 112) - file @6 :Void; # bits[0, 0), union tag = 0 - struct :group { # union tag = 1 - dataWordCount @7 :UInt16; # bits[112, 128) - pointerCount @8 :UInt16; # bits[192, 208) - preferredListEncoding @9 :ElementSize; # bits[208, 224) - isGroup @10 :Bool; # bits[224, 225) - discriminantCount @11 :UInt16; # bits[240, 256) - discriminantOffset @12 :UInt32; # bits[256, 288) - fields @13 :List(Field); # ptr[3] - } - enum :group { # union tag = 2 - enumerants @14 :List(Enumerant); # ptr[3] - } - interface :group { # union tag = 3 - methods @15 :List(Method); # ptr[3] - superclasses @31 :List(Superclass); # ptr[4] - } - const :group { # union tag = 4 - type @16 :Type; # ptr[3] - value @17 :Value; # ptr[4] - } - annotation :group { # union tag = 5 - type @18 :Type; # ptr[3] - targetsFile @19 :Bool; # bits[112, 113) - targetsConst @20 :Bool; # bits[113, 114) - targetsEnum @21 :Bool; # bits[114, 115) - targetsEnumerant @22 :Bool; # bits[115, 116) - targetsStruct @23 :Bool; # bits[116, 117) - targetsField @24 :Bool; # bits[117, 118) - targetsUnion @25 :Bool; # bits[118, 119) - targetsGroup @26 :Bool; # bits[119, 120) - targetsInterface @27 :Bool; # bits[120, 121) - targetsMethod @28 :Bool; # bits[121, 122) - targetsParam @29 :Bool; # bits[122, 123) - targetsAnnotation @30 :Bool; # bits[123, 124) - } - } - struct Parameter @0xb9521bccf10fa3b1 { # 0 bytes, 1 ptrs - name @0 :Text; # ptr[0] - } - struct NestedNode @0xdebf55bbfa0fc242 { # 8 bytes, 1 ptrs - name @0 :Text; # ptr[0] - id @1 :UInt64; # bits[0, 64) - } - struct SourceInfo @0xf38e1de3041357ae { # 8 bytes, 2 ptrs - id @0 :UInt64; # bits[0, 64) - docComment @1 :Text; # ptr[0] - members @2 :List(Member); # ptr[1] - struct Member @0xc2ba9038898e1fa2 { # 0 bytes, 1 ptrs - docComment @0 :Text; # ptr[0] - } - } -} -struct Field @0x9aad50a41f4af45f { # 24 bytes, 4 ptrs - name @0 :Text; # ptr[0] - codeOrder @1 :UInt16; # bits[0, 16) - annotations @2 :List(Annotation); # ptr[1] - discriminantValue @3 :UInt16 = 65535; # bits[16, 32) - union { # tag bits [64, 80) - slot :group { # union tag = 0 - offset @4 :UInt32; # bits[32, 64) - type @5 :Type; # ptr[2] - defaultValue @6 :Value; # ptr[3] - hadExplicitDefault @10 :Bool; # bits[128, 129) - } - group :group { # union tag = 1 - typeId @7 :UInt64; # bits[128, 192) - } - } - ordinal :group { - union { # tag bits [80, 96) - implicit @8 :Void; # bits[0, 0), union tag = 0 - explicit @9 :UInt16; # bits[96, 112), union tag = 1 - } - } - const noDiscriminant @0x97b14cbe7cfec712 :UInt16 = 65535; -} -struct Enumerant @0x978a7cebdc549a4d { # 8 bytes, 2 ptrs - name @0 :Text; # ptr[0] - codeOrder @1 :UInt16; # bits[0, 16) - annotations @2 :List(Annotation); # ptr[1] -} -struct Superclass @0xa9962a9ed0a4d7f8 { # 8 bytes, 1 ptrs - id @0 :UInt64; # bits[0, 64) - brand @1 :Brand; # ptr[0] -} -struct Method @0x9500cce23b334d80 { # 24 bytes, 5 ptrs - name @0 :Text; # ptr[0] - codeOrder @1 :UInt16; # bits[0, 16) - implicitParameters @7 :List(Node.Parameter); # ptr[4] - paramStructType @2 :UInt64; # bits[64, 128) - paramBrand @5 :Brand; # ptr[2] - resultStructType @3 :UInt64; # bits[128, 192) - resultBrand @6 :Brand; # ptr[3] - annotations @4 :List(Annotation); # ptr[1] -} -struct Type @0xd07378ede1f9cc60 { # 24 bytes, 1 ptrs - union { # tag bits [0, 16) - void @0 :Void; # bits[0, 0), union tag = 0 - bool @1 :Void; # bits[0, 0), union tag = 1 - int8 @2 :Void; # bits[0, 0), union tag = 2 - int16 @3 :Void; # bits[0, 0), union tag = 3 - int32 @4 :Void; # bits[0, 0), union tag = 4 - int64 @5 :Void; # bits[0, 0), union tag = 5 - uint8 @6 :Void; # bits[0, 0), union tag = 6 - uint16 @7 :Void; # bits[0, 0), union tag = 7 - uint32 @8 :Void; # bits[0, 0), union tag = 8 - uint64 @9 :Void; # bits[0, 0), union tag = 9 - float32 @10 :Void; # bits[0, 0), union tag = 10 - float64 @11 :Void; # bits[0, 0), union tag = 11 - text @12 :Void; # bits[0, 0), union tag = 12 - data @13 :Void; # bits[0, 0), union tag = 13 - list :group { # union tag = 14 - elementType @14 :Type; # ptr[0] - } - enum :group { # union tag = 15 - typeId @15 :UInt64; # bits[64, 128) - brand @21 :Brand; # ptr[0] - } - struct :group { # union tag = 16 - typeId @16 :UInt64; # bits[64, 128) - brand @22 :Brand; # ptr[0] - } - interface :group { # union tag = 17 - typeId @17 :UInt64; # bits[64, 128) - brand @23 :Brand; # ptr[0] - } - anyPointer :group { # union tag = 18 - union { # tag bits [64, 80) - unconstrained :group { # union tag = 0 - union { # tag bits [80, 96) - anyKind @18 :Void; # bits[0, 0), union tag = 0 - struct @25 :Void; # bits[0, 0), union tag = 1 - list @26 :Void; # bits[0, 0), union tag = 2 - capability @27 :Void; # bits[0, 0), union tag = 3 - } - } - parameter :group { # union tag = 1 - scopeId @19 :UInt64; # bits[128, 192) - parameterIndex @20 :UInt16; # bits[80, 96) - } - implicitMethodParameter :group { # union tag = 2 - parameterIndex @24 :UInt16; # bits[80, 96) - } - } - } - } -} -struct Brand @0x903455f06065422b { # 0 bytes, 1 ptrs - scopes @0 :List(Scope); # ptr[0] - struct Scope @0xabd73485a9636bc9 { # 16 bytes, 1 ptrs - scopeId @0 :UInt64; # bits[0, 64) - union { # tag bits [64, 80) - bind @1 :List(Binding); # ptr[0], union tag = 0 - inherit @2 :Void; # bits[0, 0), union tag = 1 - } - } - struct Binding @0xc863cd16969ee7fc { # 8 bytes, 1 ptrs - union { # tag bits [0, 16) - unbound @0 :Void; # bits[0, 0), union tag = 0 - type @1 :Type; # ptr[0], union tag = 1 - } - } -} -struct Value @0xce23dcd2d7b00c9b { # 16 bytes, 1 ptrs - union { # tag bits [0, 16) - void @0 :Void; # bits[0, 0), union tag = 0 - bool @1 :Bool; # bits[16, 17), union tag = 1 - int8 @2 :Int8; # bits[16, 24), union tag = 2 - int16 @3 :Int16; # bits[16, 32), union tag = 3 - int32 @4 :Int32; # bits[32, 64), union tag = 4 - int64 @5 :Int64; # bits[64, 128), union tag = 5 - uint8 @6 :UInt8; # bits[16, 24), union tag = 6 - uint16 @7 :UInt16; # bits[16, 32), union tag = 7 - uint32 @8 :UInt32; # bits[32, 64), union tag = 8 - uint64 @9 :UInt64; # bits[64, 128), union tag = 9 - float32 @10 :Float32; # bits[32, 64), union tag = 10 - float64 @11 :Float64; # bits[64, 128), union tag = 11 - text @12 :Text; # ptr[0], union tag = 12 - data @13 :Data; # ptr[0], union tag = 13 - list @14 :AnyPointer; # ptr[0], union tag = 14 - enum @15 :UInt16; # bits[16, 32), union tag = 15 - struct @16 :AnyPointer; # ptr[0], union tag = 16 - interface @17 :Void; # bits[0, 0), union tag = 17 - anyPointer @18 :AnyPointer; # ptr[0], union tag = 18 - } -} -struct Annotation @0xf1c8950dab257542 { # 8 bytes, 2 ptrs - id @0 :UInt64; # bits[0, 64) - brand @2 :Brand; # ptr[1] - value @1 :Value; # ptr[0] -} -enum ElementSize @0xd1958f7dba521926 { - empty @0; - bit @1; - byte @2; - twoBytes @3; - fourBytes @4; - eightBytes @5; - pointer @6; - inlineComposite @7; -} -struct CapnpVersion @0xd85d305b7d839963 { # 8 bytes, 0 ptrs - major @0 :UInt16; # bits[0, 16) - minor @1 :UInt8; # bits[16, 24) - micro @2 :UInt8; # bits[24, 32) -} -struct CodeGeneratorRequest @0xbfc546f6210ad7ce { # 0 bytes, 4 ptrs - capnpVersion @2 :CapnpVersion; # ptr[2] - nodes @0 :List(Node); # ptr[0] - sourceInfo @3 :List(Node.SourceInfo); # ptr[3] - requestedFiles @1 :List(RequestedFile); # ptr[1] - struct RequestedFile @0xcfea0eb02e810062 { # 8 bytes, 2 ptrs - id @0 :UInt64; # bits[0, 64) - filename @1 :Text; # ptr[0] - imports @2 :List(Import); # ptr[1] - struct Import @0xae504193122357e5 { # 8 bytes, 1 ptrs - id @0 :UInt64; # bits[0, 64) - name @1 :Text; # ptr[0] - } - } -} diff --git a/capnpc-csharp/capnpc-csharp.csproj b/capnpc-csharp/capnpc-csharp.csproj index 3e3531e..4c58994 100644 --- a/capnpc-csharp/capnpc-csharp.csproj +++ b/capnpc-csharp/capnpc-csharp.csproj @@ -27,6 +27,7 @@ +