From fd7ada499f902fef231c7525bc60ef703a095e8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6llner?= Date: Thu, 30 Jan 2020 21:53:08 +0100 Subject: [PATCH] WIP --- .../CapnpC.CSharp.Generator.Tests.csproj | 8 +- .../CodeGenerator.feature | 20 +- .../CodeGenerator.feature.cs | 352 ++++++++++++++++-- .../CodeGeneratorUnitTests.cs | 69 +++- .../NullableDisable.capnp.bin | Bin 0 -> 1720 bytes .../NullableEnable.capnp.bin | Bin 0 -> 1720 bytes .../Embedded Resources/UnitTest13.capnp.bin | Bin 0 -> 1320 bytes .../Embedded Resources/UnitTest14.capnp.bin | Bin 0 -> 1888 bytes .../Embedded Resources/UnitTest15.capnp.bin | Bin 0 -> 4728 bytes .../Embedded Resources/test.cs | 134 +++---- .../FeatureSteps/CodeGeneratorSteps.cs | 84 ++++- .../No Resources/NullableDisable.capnp | 9 + .../No Resources/NullableEnable.capnp | 9 + .../No Resources/UnitTest13.capnp | 8 + .../No Resources/UnitTest14.capnp | 10 + .../No Resources/UnitTest15.capnp | 25 ++ .../Util/InlineAssemblyCompiler.cs | 28 +- CapnpC.CSharp.Generator/CapnpCompilation.cs | 15 +- .../CodeGen/CodeGenerator.cs | 4 +- .../CodeGen/CommonSnippetGen.cs | 4 +- .../CodeGen/DomainClassSnippetGen.cs | 14 +- CapnpC.CSharp.Generator/CodeGen/GenNames.cs | 127 ++++--- .../CodeGen/GeneratorOptions.cs | 3 +- .../CodeGen/InterfaceSnippetGen.cs | 31 +- .../CodeGen/SyntaxHelpers.cs | 4 +- CapnpC.CSharp.Generator/Model/Enumerant.cs | 1 + CapnpC.CSharp.Generator/Model/Field.cs | 1 + CapnpC.CSharp.Generator/Model/GenFile.cs | 2 +- CapnpC.CSharp.Generator/Model/Method.cs | 2 + CapnpC.CSharp.Generator/Model/SchemaModel.cs | 26 +- .../Model/SupportedAnnotations.cs | 89 +++++ .../Model/TypeDefinition.cs | 1 + ...npC.CSharp.MsBuild.Generation.Tests.csproj | 2 +- include/csharp.capnp | 8 +- 34 files changed, 859 insertions(+), 231 deletions(-) create mode 100644 CapnpC.CSharp.Generator.Tests/Embedded Resources/NullableDisable.capnp.bin create mode 100644 CapnpC.CSharp.Generator.Tests/Embedded Resources/NullableEnable.capnp.bin create mode 100644 CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest13.capnp.bin create mode 100644 CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest14.capnp.bin create mode 100644 CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest15.capnp.bin create mode 100644 CapnpC.CSharp.Generator.Tests/No Resources/NullableDisable.capnp create mode 100644 CapnpC.CSharp.Generator.Tests/No Resources/NullableEnable.capnp create mode 100644 CapnpC.CSharp.Generator.Tests/No Resources/UnitTest13.capnp create mode 100644 CapnpC.CSharp.Generator.Tests/No Resources/UnitTest14.capnp create mode 100644 CapnpC.CSharp.Generator.Tests/No Resources/UnitTest15.capnp create mode 100644 CapnpC.CSharp.Generator/Model/SupportedAnnotations.cs diff --git a/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj b/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj index 07457e7..77462b1 100644 --- a/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj +++ b/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + netcoreapp3.0 CapnpC.CSharp.Generator.Tests false @@ -16,9 +16,9 @@ - - - + + + diff --git a/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature index 3485d84..ca18d19 100644 --- a/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature +++ b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature @@ -49,11 +49,21 @@ Scenario: Multiple errors Scenario Outline: Valid generator output Given I have a binary code generator request + And I enable generation of nullable reference types according to + And I enable the compiler support of nullable reference types according to When I invoke capnpc-csharp - Then the invocation must succeed and the generated code must compile + Then the invocation must succeed and attempting to compile the generated code gives Examples: - | bin | - | Issue19.capnp.bin | - | Issue21.capnp.bin | - | Issue22.capnp.bin | \ No newline at end of file + | bin | nullablegen | nullablesupp | outcome | + | test.capnp.bin | false | false | success | + | test.capnp.bin | true | false | success | + | test.capnp.bin | false | true | warnings | + | test.capnp.bin | true | true | success | + | Issue19.capnp.bin | false | false | success | + | Issue21.capnp.bin | false | false | success | + | Issue22.capnp.bin | false | false | success | + | NullableDisable.capnp.bin | true | false | success | + | NullableDisable.capnp.bin | true | true | warnings | + | NullableEnable.capnp.bin | false | true | success | + | NullableEnable.capnp.bin | false | false | errors | \ No newline at end of file diff --git a/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs index de6a0cc..768e1cc 100644 --- a/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs +++ b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs @@ -1,8 +1,8 @@ // ------------------------------------------------------------------------------ // // This code was generated by SpecFlow (http://www.specflow.org/). -// SpecFlow Version:3.0.0.0 -// SpecFlow Generator Version:3.0.0.0 +// SpecFlow Version:3.1.0.0 +// SpecFlow Generator Version:3.1.0.0 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -13,9 +13,11 @@ namespace CapnpC.CSharp.Generator.Tests { using TechTalk.SpecFlow; + using System; + using System.Linq; - [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.0.0.0")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "3.1.0.0")] [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute()] public partial class CodeGeneratorFeature @@ -25,6 +27,8 @@ namespace CapnpC.CSharp.Generator.Tests private Microsoft.VisualStudio.TestTools.UnitTesting.TestContext _testContext; + private string[] _featureTags = ((string[])(null)); + #line 1 "CodeGenerator.feature" #line hidden @@ -68,7 +72,7 @@ namespace CapnpC.CSharp.Generator.Tests } [Microsoft.VisualStudio.TestTools.UnitTesting.TestCleanupAttribute()] - public virtual void ScenarioTearDown() + public virtual void TestTearDown() { testRunner.OnScenarioEnd(); } @@ -94,35 +98,78 @@ namespace CapnpC.CSharp.Generator.Tests [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] public virtual void ComparingBackendOutputWithReference() { + string[] tagsOfScenario = ((string[])(null)); TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Comparing backend output with reference", null, ((string[])(null))); #line 6 this.ScenarioInitialize(scenarioInfo); - this.ScenarioStart(); +#line hidden + bool isScenarioIgnored = default(bool); + bool isFeatureIgnored = default(bool); + if ((tagsOfScenario != null)) + { + isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((this._featureTags != null)) + { + isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((isScenarioIgnored || isFeatureIgnored)) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); #line 7 testRunner.Given("I have a binary code generator request \"test.capnp.bin\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line hidden #line 8 testRunner.And("my reference output is \"test.cs\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden #line 9 testRunner.When("I invoke capnpc-csharp", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden #line 10 testRunner.Then("the generated output must match the reference", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden + } this.ScenarioCleanup(); } public virtual void InvalidBinaryCodeGeneratorRequests(string bin, string[] exampleTags) { + string[] tagsOfScenario = exampleTags; TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Invalid binary code generator requests", null, exampleTags); #line 12 this.ScenarioInitialize(scenarioInfo); - this.ScenarioStart(); +#line hidden + bool isScenarioIgnored = default(bool); + bool isFeatureIgnored = default(bool); + if ((tagsOfScenario != null)) + { + isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((this._featureTags != null)) + { + isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((isScenarioIgnored || isFeatureIgnored)) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); #line 13 testRunner.Given(string.Format("I have a binary code generator request {0}", bin), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line hidden #line 14 testRunner.When("I invoke capnpc-csharp", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden #line 15 testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden + } this.ScenarioCleanup(); } @@ -155,19 +202,41 @@ this.InvalidBinaryCodeGeneratorRequests("test.cs", ((string[])(null))); [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] public virtual void CombiningFrontendAndBackend() { + string[] tagsOfScenario = ((string[])(null)); TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Combining frontend and backend", null, ((string[])(null))); #line 22 this.ScenarioInitialize(scenarioInfo); - this.ScenarioStart(); +#line hidden + bool isScenarioIgnored = default(bool); + bool isFeatureIgnored = default(bool); + if ((tagsOfScenario != null)) + { + isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((this._featureTags != null)) + { + isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((isScenarioIgnored || isFeatureIgnored)) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); #line 23 testRunner.Given("capnp.exe is installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line hidden #line 24 testRunner.And("I have a schema \"UnitTest1.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden #line 25 testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden #line 26 testRunner.Then("code generation must succeed", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden + } this.ScenarioCleanup(); } @@ -176,19 +245,41 @@ this.ScenarioInitialize(scenarioInfo); [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] public virtual void MissingFrontend() { + string[] tagsOfScenario = ((string[])(null)); TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Missing frontend", null, ((string[])(null))); #line 28 this.ScenarioInitialize(scenarioInfo); - this.ScenarioStart(); +#line hidden + bool isScenarioIgnored = default(bool); + bool isFeatureIgnored = default(bool); + if ((tagsOfScenario != null)) + { + isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((this._featureTags != null)) + { + isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((isScenarioIgnored || isFeatureIgnored)) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); #line 29 testRunner.Given("capnp.exe is not installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line hidden #line 30 testRunner.And("I have a schema \"UnitTest1.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden #line 31 testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden #line 32 testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden + } this.ScenarioCleanup(); } @@ -197,23 +288,47 @@ this.ScenarioInitialize(scenarioInfo); [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] public virtual void SchemaWithoutID() { + string[] tagsOfScenario = ((string[])(null)); TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Schema without ID", null, ((string[])(null))); #line 34 this.ScenarioInitialize(scenarioInfo); - this.ScenarioStart(); +#line hidden + bool isScenarioIgnored = default(bool); + bool isFeatureIgnored = default(bool); + if ((tagsOfScenario != null)) + { + isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((this._featureTags != null)) + { + isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((isScenarioIgnored || isFeatureIgnored)) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); #line 35 testRunner.Given("capnp.exe is installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line hidden #line 36 testRunner.And("I have a schema \"Empty1.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden #line 37 testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden #line 38 testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden #line 39 testRunner.And("the reason must be bad input", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden #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(); } @@ -222,75 +337,256 @@ this.ScenarioInitialize(scenarioInfo); [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] public virtual void MultipleErrors() { + string[] tagsOfScenario = ((string[])(null)); TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Multiple errors", null, ((string[])(null))); #line 42 this.ScenarioInitialize(scenarioInfo); - this.ScenarioStart(); +#line hidden + bool isScenarioIgnored = default(bool); + bool isFeatureIgnored = default(bool); + if ((tagsOfScenario != null)) + { + isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((this._featureTags != null)) + { + isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((isScenarioIgnored || isFeatureIgnored)) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); #line 43 testRunner.Given("capnp.exe is installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line hidden #line 44 testRunner.And("I have a schema \"invalid.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden #line 45 testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden #line 46 testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden #line 47 testRunner.And("the reason must be bad input", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden #line 48 testRunner.And("the error output must contain multiple messages", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden + } this.ScenarioCleanup(); } - public virtual void ValidGeneratorOutput(string bin, string[] exampleTags) + public virtual void ValidGeneratorOutput(string bin, string nullablegen, string nullablesupp, string outcome, string[] exampleTags) { + string[] tagsOfScenario = exampleTags; TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Valid generator output", null, exampleTags); #line 50 this.ScenarioInitialize(scenarioInfo); - this.ScenarioStart(); +#line hidden + bool isScenarioIgnored = default(bool); + bool isFeatureIgnored = default(bool); + if ((tagsOfScenario != null)) + { + isScenarioIgnored = tagsOfScenario.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((this._featureTags != null)) + { + isFeatureIgnored = this._featureTags.Where(__entry => __entry != null).Where(__entry => String.Equals(__entry, "ignore", StringComparison.CurrentCultureIgnoreCase)).Any(); + } + if ((isScenarioIgnored || isFeatureIgnored)) + { + testRunner.SkipScenario(); + } + else + { + this.ScenarioStart(); #line 51 testRunner.Given(string.Format("I have a binary code generator request {0}", bin), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); -#line 52 - testRunner.When("I invoke capnpc-csharp", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); -#line 53 - testRunner.Then("the invocation must succeed and the generated code must compile", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden +#line 52 + testRunner.And(string.Format("I enable generation of nullable reference types according to {0}", nullablegen), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden +#line 53 + testRunner.And(string.Format("I enable the compiler support of nullable reference types according to {0}", nullablesupp), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden +#line 54 + testRunner.When("I invoke capnpc-csharp", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line hidden +#line 55 + testRunner.Then(string.Format("the invocation must succeed and attempting to compile the generated code gives {0" + + "}", outcome), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + } this.ScenarioCleanup(); } [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] - [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Issue19.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 0")] [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] - [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Issue19.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 0")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "test.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")] + public virtual void ValidGeneratorOutput_Variant0() + { +#line 50 +this.ValidGeneratorOutput("test.capnp.bin", "false", "false", "success", ((string[])(null))); +#line hidden + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 1")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 1")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "test.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "true")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")] + public virtual void ValidGeneratorOutput_Variant1() + { +#line 50 +this.ValidGeneratorOutput("test.capnp.bin", "true", "false", "success", ((string[])(null))); +#line hidden + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 2")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 2")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "test.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "true")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "warnings")] + public virtual void ValidGeneratorOutput_Variant2() + { +#line 50 +this.ValidGeneratorOutput("test.capnp.bin", "false", "true", "warnings", ((string[])(null))); +#line hidden + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 3")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 3")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "test.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "true")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "true")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")] + public virtual void ValidGeneratorOutput_Variant3() + { +#line 50 +this.ValidGeneratorOutput("test.capnp.bin", "true", "true", "success", ((string[])(null))); +#line hidden + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 4")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 4")] [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "Issue19.capnp.bin")] - public virtual void ValidGeneratorOutput_Issue19_Capnp_Bin() + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")] + public virtual void ValidGeneratorOutput_Variant4() { #line 50 -this.ValidGeneratorOutput("Issue19.capnp.bin", ((string[])(null))); +this.ValidGeneratorOutput("Issue19.capnp.bin", "false", "false", "success", ((string[])(null))); #line hidden } [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] - [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Issue21.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 5")] [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] - [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Issue21.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 5")] [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "Issue21.capnp.bin")] - public virtual void ValidGeneratorOutput_Issue21_Capnp_Bin() + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")] + public virtual void ValidGeneratorOutput_Variant5() { #line 50 -this.ValidGeneratorOutput("Issue21.capnp.bin", ((string[])(null))); +this.ValidGeneratorOutput("Issue21.capnp.bin", "false", "false", "success", ((string[])(null))); #line hidden } [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] - [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Issue22.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 6")] [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] - [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Issue22.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 6")] [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "Issue22.capnp.bin")] - public virtual void ValidGeneratorOutput_Issue22_Capnp_Bin() + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")] + public virtual void ValidGeneratorOutput_Variant6() { #line 50 -this.ValidGeneratorOutput("Issue22.capnp.bin", ((string[])(null))); +this.ValidGeneratorOutput("Issue22.capnp.bin", "false", "false", "success", ((string[])(null))); +#line hidden + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 7")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 7")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableDisable.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "true")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")] + public virtual void ValidGeneratorOutput_Variant7() + { +#line 50 +this.ValidGeneratorOutput("NullableDisable.capnp.bin", "true", "false", "success", ((string[])(null))); +#line hidden + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 8")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 8")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableDisable.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "true")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "true")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "warnings")] + public virtual void ValidGeneratorOutput_Variant8() + { +#line 50 +this.ValidGeneratorOutput("NullableDisable.capnp.bin", "true", "true", "warnings", ((string[])(null))); +#line hidden + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 9")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 9")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableEnable.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "true")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")] + public virtual void ValidGeneratorOutput_Variant9() + { +#line 50 +this.ValidGeneratorOutput("NullableEnable.capnp.bin", "false", "true", "success", ((string[])(null))); +#line hidden + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 10")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 10")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableEnable.capnp.bin")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "errors")] + public virtual void ValidGeneratorOutput_Variant10() + { +#line 50 +this.ValidGeneratorOutput("NullableEnable.capnp.bin", "false", "false", "errors", ((string[])(null))); #line hidden } } diff --git a/CapnpC.CSharp.Generator.Tests/CodeGeneratorUnitTests.cs b/CapnpC.CSharp.Generator.Tests/CodeGeneratorUnitTests.cs index 162e09a..4ccbd9b 100644 --- a/CapnpC.CSharp.Generator.Tests/CodeGeneratorUnitTests.cs +++ b/CapnpC.CSharp.Generator.Tests/CodeGeneratorUnitTests.cs @@ -22,7 +22,7 @@ namespace CapnpC.CSharp.Generator.Tests [TestMethod] public void Test01NestedClash() { - var (model, codegen) = LoadAndGenerate("UnitTest1.capnp.bin"); + var (model, codegen, _) = LoadAndGenerate("UnitTest1.capnp.bin"); var structFoo = GetTypeDef(0x93db6ba5509bac24, model); var names = codegen.GetNames(); var fieldName = names.GetCodeIdentifier(structFoo.Fields[0]).ToString(); @@ -51,7 +51,7 @@ namespace CapnpC.CSharp.Generator.Tests [TestMethod] public void Test10ImportedNamespaces() { - var (model, codegen) = LoadAndGenerate("UnitTest10.capnp.bin"); + var (model, codegen, _) = LoadAndGenerate("UnitTest10.capnp.bin"); var outerTypeDef = GetGeneratedFile("UnitTest10.capnp", model).NestedTypes.First(); var outerType = Model.Types.FromDefinition(outerTypeDef); var innerType = outerTypeDef.Fields[0].Type; @@ -81,6 +81,60 @@ namespace CapnpC.CSharp.Generator.Tests LoadAndGenerate("UnitTest12.capnp.bin"); } + [TestMethod] + public void Test13CSharpNamespace() + { + var (model, _, _) = LoadAndGenerate("UnitTest13.capnp.bin"); + var outerTypeDef = GetGeneratedFile("UnitTest13.capnp", model).NestedTypes.First(); + string[] outerNamespace = { "Foo", "Bar", "Baz" }; + CollectionAssert.AreEqual(outerNamespace, (outerTypeDef.DeclaringElement as Model.GenFile).Namespace); + } + + [TestMethod] + public void Test14CSharpNamespacePrecedesCxxNamespace() + { + var (model, _, _) = LoadAndGenerate("UnitTest14.capnp.bin"); + var outerTypeDef = GetGeneratedFile("UnitTest14.capnp", model).NestedTypes.First(); + string[] outerNamespace = { "Foo", "Bar", "Baz" }; + CollectionAssert.AreEqual(outerNamespace, (outerTypeDef.DeclaringElement as Model.GenFile).Namespace); + } + + [TestMethod] + public void Test15CSharpMemberNames() + { + var (_, _, code) = LoadAndGenerate("UnitTest15.capnp.bin"); + try + { + Assert.IsTrue(code.Contains("CsStruct", StringComparison.Ordinal), "Generated code must contain C# struct name"); + Assert.IsFalse(code.Contains("SomeStruct", StringComparison.Ordinal), "Generated code must not contain original struct name"); + Assert.IsTrue(code.Contains("CsField", StringComparison.Ordinal), "Generated code must contain C# field name"); + Assert.IsFalse(code.Contains("someField", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original field name"); + Assert.IsTrue(code.Contains("CsUnion", StringComparison.Ordinal), "Generated code must contain C# union name"); + Assert.IsFalse(code.Contains("someUnion", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original union name"); + Assert.IsTrue(code.Contains("CsGroup", StringComparison.Ordinal), "Generated code must contain C# group name"); + Assert.IsFalse(code.Contains("someGroup", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original group name"); + Assert.IsTrue(code.Contains("CsEnum", StringComparison.Ordinal), "Generated code must contain C# enum name"); + Assert.IsFalse(code.Contains("SomeEnum", StringComparison.Ordinal), "Generated code must not contain original enum name"); + Assert.IsTrue(code.Contains("CsEnumerant", StringComparison.Ordinal), "Generated code must contain C# enumerant name"); + Assert.IsFalse(code.Contains("someEnumerant", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original enumerant name"); + Assert.IsTrue(code.Contains("CsField", StringComparison.Ordinal), "Generated code must contain C# field name"); + Assert.IsFalse(code.Contains("someField", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original field name"); + Assert.IsTrue(code.Contains("CsInterface", StringComparison.Ordinal), "Generated code must contain C# interface name"); + Assert.IsFalse(code.Contains("SomeInterface", StringComparison.Ordinal), "Generated code must not contain original interface name"); + Assert.IsTrue(code.Contains("CsMethod", StringComparison.Ordinal), "Generated code must contain C# method name"); + Assert.IsFalse(code.Contains("someMethod", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original method name"); + Assert.IsTrue(code.Contains("CsField", StringComparison.Ordinal), "Generated code must contain C# field name"); + Assert.IsFalse(code.Contains("someField", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original field name"); + Assert.IsTrue(code.Contains("CsResult", StringComparison.Ordinal), "Generated code must contain C# method parameter name"); + Assert.IsFalse(code.Contains("someResult", StringComparison.OrdinalIgnoreCase), "Generated code must not contain original method parameter name"); + } + catch (AssertFailedException) + { + Console.WriteLine(code); + throw; + } + } + [TestMethod] public void Test20AnnotationAndConst() { @@ -93,15 +147,20 @@ namespace CapnpC.CSharp.Generator.Tests LoadAndGenerate("schema-with-offsets.capnp.bin"); } - static (Model.SchemaModel, CodeGen.CodeGenerator) LoadAndGenerate(string inputName) + static (Model.SchemaModel, CodeGen.CodeGenerator, string) LoadAndGenerate(string inputName) { var model = Load(inputName); var codegen = new CodeGen.CodeGenerator(model, new CodeGen.GeneratorOptions()); var code = model.FilesToGenerate.Select(f => codegen.Transform(f)).ToArray(); - Assert.IsTrue(Util.InlineAssemblyCompiler.TryCompileCapnp(code), "Compilation was not successful"); + Assert.AreEqual( + Util.InlineAssemblyCompiler.CompileSummary.Success, + Util.InlineAssemblyCompiler.TryCompileCapnp( + Microsoft.CodeAnalysis.NullableContextOptions.Disable, + code), + "Compilation was not successful with no warnings"); - return (model, codegen); + return (model, codegen, code[0]); } static Model.GenFile GetGeneratedFile(string name, Model.SchemaModel model) diff --git a/CapnpC.CSharp.Generator.Tests/Embedded Resources/NullableDisable.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/NullableDisable.capnp.bin new file mode 100644 index 0000000000000000000000000000000000000000..14f05c8dbdd594ee40531bef29e1d33599139cd1 GIT binary patch literal 1720 zcmcIky=xRf6n}dkYQ$3l5=9VK)WSe+4fp|RL=Qhe6ugTFcI#$xci}R#%+3|DvG6}g zXQ#G;jhz-&u@(#e04qT(EG$w4{Jou>%kIDtEi&+C=FR)P-@G^TW{8NsL2PT#EGC}< zqU{>d8O$3HsI&q7IYy#`d4C*zlMc|_mzVe6-QD@PoUcyrwqW`Sj^7whKmw35|Frh{ z*XP09i`LH;08K>jw$Oe24i>&cX2547vxo-tdLDVz!|{}{RfN_4U|54}L#{zC>=Ey) ze~fnlJRiV!#f$gSlz4-!%WM6aAMc;Q2aw5m2bFAz&cZlfCwl1d-iLl2etx^X6m>5! z_enNlUz>lf6e~oVnB_Oqz9FSDu^B3v?LzWd^*pM-lN8 zNUAr*@BgMVVLSxkcYPis*GXpdQ1&xATEh5K#_yH)G=Ki*0_^1eIiK78C;qytlhZJ4 zmQr%>!Qn4ratz|?jP+9`{NsTz1EE8s!oGcmBJ7+CU0H=%tO_k;B0{r~imY|GAm(%B z$X#O}R}JB+(qW=jgrh_qIY;&@=i7wN|MntA{-kbT}H}B2786u)@5Zh`r59L!p zv|AxM2fYS?Nn5a=VM-Mx>i`Rwd&2TNbU@f+hQNB~mipVeOf z`rKc5(fHW_ppFRM7PgPy!^C&U9QbTx7Eyy;%_E=oa6Dz~G{RbcFl<0}AuEte`^5X| zKjU2j&j;{b^WwcSBi>-=>PBzw$NMMn0c3pM!BnOpoQu@c+jhT2I?2Ssr4(bxV$h z!}#e?+>+dnVf(WXm3i2a_h&zMulz1L5Em!g&meD#duMwQBI8YwrE%hR_e0`!z>0TO z8S}fmPxB)7wfW~pF+;QsEx(!O4Jnn0%|OX)0?D;<9xX2z&d2BV-08sTqUGPbJzvhd znxBS?gezsz`2F9Um~;d>zw3(_xlS^p2eOyZ@e;;Y8NXlNv;6s=3$T;>=X`GWpZN2x zPR?RsyOff94-S7B$_a?8Gq%r^@Q?e#^o0(M3VZe$im-hlbY&H4u`aZbi3rVBDze7W zf|$>hBX^B`Txo{uN{5MB6OIyf0uHOQryKR-DWdhBA1zEX0Az_KR~cc zr(!4Ao74&x0S#CPX;O#$2?4)1b91-18m%($y*F>(o44=RED_NMz^`e#g-tIaYSxJE zVLuH(q*IU{IMH=SZ-Un88qI#+fBtFZ;&9EKUQYI*I)=|L;CFzZ0QZBb$hRI z)__4B5quoVRr_B!H~>xoADOo}0h@A>dpXeHr)(Q^Wqt(V74QRi3|s*Jiuap&Fn6p! zzg~wO*DKUzGAiT(<-!!vBKZGefE!wBr5#Zyljd0=3$3hrxT&lZHdk7tZ9Z%#?e12l zi)2|yp);#=vL=i*>8gr5!l;4Hg-Kt?ZOg~aM~QRA&ar%dBMR|z?3_ba?TD_`gWR%J zu&Yt%3*W0D(>bS&=!WBC!hSY@C8d(5nFe;pO6+puLUy6FWVRzrk>$dhMDSbnH*vXg zpLJ}{_d*+ySHlT5uHX2UxDng3l@{v}?{{|(?e zlsu7A+01S$Y1q89uB^YUY6pFN_}xb6T&bf3?wjspFXc6HRdbPh44j{O3pWAM)VTG?11D6!LGW1^%=E literal 0 HcmV?d00001 diff --git a/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest14.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest14.capnp.bin new file mode 100644 index 0000000000000000000000000000000000000000..0e48988e8e4fb84759ae11ff85d4fe81826a3418 GIT binary patch literal 1888 zcmcIlOKTKC5boJzec^(FBr1vn9+W(05)j0>nI%yX0`9J0M3BjBYa*NJWoGseCE)9# z7f}#VP}GYD!Lv`i<)&!BUlBaSQ#>g7s(X5Ow%HB2q@lXHs;g_hu161Jj4gxI=w-XH z=+7~BqKC0VSoeY~&`;=|fHSsL&U-QE*%r3v$J4X#PXGH%V?7Lh zyt_Gj`FnAu?@nR40Gm7zyiH~E$T|4=2;~&GLZ&P#kb5NZ_7mDq*0$Y3N#i(w4a+m& zgtGxo@#r>&F5mq6;_u>zT`(ZLw&=SvSR!WO2@Jhr1^>^U|EPz&F{vv_f&VtK}o>dq-1^2kp_wdu1o&{W{AAL^q?0M3WJ)P5i zLVa5Ty-NFpWJ3BnBM(3}KFz{Lt>#bH_;^UO+J{-%_pSI*+$nz4_w;2GFU9E*NM_hM z8HOV9lUWhQWS$u^0B$fisIqE?LRxMp9#ly!KTPGjmDla?MDh6kaOMB}o9Z8uJKi6u zppUA$$~Eg^BlmrVb1I>p-|fPi)(@Up@v0suKUDYnU8cKbhwhuKj@J5}G4;AnOntWQ z_EYlHq2E_6YhFBTH%rgHA|g8wRc>EZF97PKkUnra4;p_S4(Puz3Qq6Zro}S_s_RI{ ZgX-o!NZ*V8M-fQ9ZKb&mRdoOW literal 0 HcmV?d00001 diff --git a/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest15.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest15.capnp.bin new file mode 100644 index 0000000000000000000000000000000000000000..2cd9b987ecc036a88629ccbaa34d55a0758fc329 GIT binary patch literal 4728 zcmc&&O=w(I6uy&W`XdG_w*F+}fCX)^GY%NUppW5uQJ&N`aumt>br&51`Duo8%Nnly+P!D{6>DZ?) z-oAD`mKOhf2P4avXBG6B;$gj>Z-dA8F8fzMH~~pX4ff`d`DI`kHb=4EF;K3Il6x4L-TT(Jlc6v6RnCE@4SEbYq=r69^0Xhk~dq>*u zN5^Y3y6XkCrqgx1z8882=e^L?Vbk+ z$=9mo6qNNOzwX>IvF_&#w{`$H!bSr7L787qftvjKr>7@5!=VR(w%!xqsrNJ}^&%Po z6vfT-7WYSWGh(Cq+i@?%eon&M_cQ%K;A^7~>-$-JQA+u2JwGpQ($9;V^m8+aOGJG2 zkGoEXcd`I8EqfnIpHN$$GN~K#u3%l@ee_ZC&LDplDEBY*blb0E{bQ^|0%Dp%db|2{_yWdmphMti{}oAGS7M?F!0W znjFikV|(H~{Wos(!#J=Jq-}{m#T8{VeBf>%>j$qQYTyCkvS!J6iJ$m?t@=3!Ju|OZ zfgpjc^;_?y5g+xJb=dOe_rK!!PDkSZKg^G}SJV!Z1<-$My&w1;!MKq!9=tAiPd^9B zy!T^c8;gs1*O=wNTnbFBNr_TSQU5miGhWMD=V1MO?BzykUnU+r1qS4ML%t7qU!4H% z1LnQ2>X7sO&U0h(4Gdr-=f=dxwqk7ce@ztV2i9-i2Sp(7bm@1{xDP1rd6Az?Pt|5Y^TfBKa>7s&FB$0{A&nbUrS z6{fP_`IV+OuPck@n+TO)_#W!A{@Zq97C%LD*zJ|9VymVe=Ghhdk{99+W*-0V!aSm1 Xx9mJ63o!Hdzx(M)-v2ebAcFrFYTEZb literal 0 HcmV?d00001 diff --git a/CapnpC.CSharp.Generator.Tests/Embedded Resources/test.cs b/CapnpC.CSharp.Generator.Tests/Embedded Resources/test.cs index 84c9f1d..73828e6 100644 --- a/CapnpC.CSharp.Generator.Tests/Embedded Resources/test.cs +++ b/CapnpC.CSharp.Generator.Tests/Embedded Resources/test.cs @@ -56,7 +56,7 @@ namespace Capnproto_test.Capnp.Test Float64List = reader.Float64List; TextList = reader.TextList; DataList = reader.DataList; - StructList = reader.StructList.ToReadOnlyList(_ => CapnpSerializable.Create(_)); + StructList = reader.StructList?.ToReadOnlyList(_ => CapnpSerializable.Create(_)); EnumList = reader.EnumList; InterfaceList = reader.InterfaceList; applyDefaults(); @@ -581,7 +581,7 @@ namespace Capnproto_test.Capnp.Test Float64List = reader.Float64List; TextList = reader.TextList; DataList = reader.DataList; - StructList = reader.StructList.ToReadOnlyList(_ => CapnpSerializable.Create(_)); + StructList = reader.StructList?.ToReadOnlyList(_ => CapnpSerializable.Create(_)); EnumList = reader.EnumList; InterfaceList = reader.InterfaceList; applyDefaults(); @@ -1185,7 +1185,7 @@ namespace Capnproto_test.Capnp.Test { var reader = READER.create(arg_); AnyStructField = CapnpSerializable.Create(reader.AnyStructField); - AnyListField = reader.AnyListField.ToReadOnlyList(_ => (object)_); + AnyListField = reader.AnyListField?.ToReadOnlyList(_ => (object)_); CapabilityField = reader.CapabilityField; applyDefaults(); } @@ -5173,16 +5173,16 @@ namespace Capnproto_test.Capnp.Test void ICapnpSerializable.Deserialize(DeserializerState arg_) { var reader = READER.create(arg_); - List0 = reader.List0.ToReadOnlyList(_ => CapnpSerializable.Create(_)); - List1 = reader.List1.ToReadOnlyList(_ => CapnpSerializable.Create(_)); - List8 = reader.List8.ToReadOnlyList(_ => CapnpSerializable.Create(_)); - List16 = reader.List16.ToReadOnlyList(_ => CapnpSerializable.Create(_)); - List32 = reader.List32.ToReadOnlyList(_ => CapnpSerializable.Create(_)); - List64 = reader.List64.ToReadOnlyList(_ => CapnpSerializable.Create(_)); - ListP = reader.ListP.ToReadOnlyList(_ => CapnpSerializable.Create(_)); + List0 = reader.List0?.ToReadOnlyList(_ => CapnpSerializable.Create(_)); + List1 = reader.List1?.ToReadOnlyList(_ => CapnpSerializable.Create(_)); + List8 = reader.List8?.ToReadOnlyList(_ => CapnpSerializable.Create(_)); + List16 = reader.List16?.ToReadOnlyList(_ => CapnpSerializable.Create(_)); + List32 = reader.List32?.ToReadOnlyList(_ => CapnpSerializable.Create(_)); + List64 = reader.List64?.ToReadOnlyList(_ => CapnpSerializable.Create(_)); + ListP = reader.ListP?.ToReadOnlyList(_ => CapnpSerializable.Create(_)); Int32ListList = reader.Int32ListList; TextListList = reader.TextListList; - StructListList = reader.StructListList.ToReadOnlyList(_2 => _2.ToReadOnlyList(_ => CapnpSerializable.Create(_))); + StructListList = reader.StructListList?.ToReadOnlyList(_2 => _2?.ToReadOnlyList(_ => CapnpSerializable.Create(_))); applyDefaults(); } @@ -7745,7 +7745,7 @@ namespace Capnproto_test.Capnp.Test { var reader = READER.create(arg_); SomeText = reader.SomeText; - StructList = reader.StructList.ToReadOnlyList(_ => CapnpSerializable.Create(_)); + StructList = reader.StructList?.ToReadOnlyList(_ => CapnpSerializable.Create(_)); applyDefaults(); } @@ -7990,7 +7990,7 @@ namespace Capnproto_test.Capnp.Test Foo = CapnpSerializable.Create(reader.Foo); Rev = CapnpSerializable.Create>(reader.Rev); - List = reader.List.ToReadOnlyList(_ => CapnpSerializable.Create.Inner>(_)); + List = reader.List?.ToReadOnlyList(_ => CapnpSerializable.Create.Inner>(_)); applyDefaults(); } @@ -8479,7 +8479,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc.Inner2.DeepNest.DeepNestInterface.Params_call.WRITER>(); var arg_ = new Capnproto_test.Capnp.Test.TestGenerics.Inner2.DeepNest.DeepNestInterface.Params_call() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(9816138025992274567UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create.Inner2.DeepNest.DeepNestInterface.Result_call>(d_); return; @@ -8609,7 +8609,7 @@ namespace Capnproto_test.Capnp.Test public Task<(TQux, Capnproto_test.Capnp.Test.TestGenerics)> Call(Capnproto_test.Capnp.Test.TestGenerics.Inner2 arg_, CancellationToken cancellationToken_ = default) { var in_ = SerializerState.CreateForRpc.Inner2.WRITER>(); - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(14548678385738242652UL, 0, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create.Interface.Result_call>(d_); @@ -8992,7 +8992,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc.WRITER>(); var arg_ = new Capnproto_test.Capnp.Test.TestImplicitMethodParams.Params_call() {Foo = foo, Bar = bar}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(10058534285777328794UL, 0, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create>(d_); @@ -9119,7 +9119,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc.Params_call.WRITER>(); var arg_ = new Capnproto_test.Capnp.Test.TestImplicitMethodParamsInGeneric.Params_call() {Foo = foo, Bar = bar}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(16112979978201007305UL, 0, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create>(d_); @@ -9918,7 +9918,7 @@ namespace Capnproto_test.Capnp.Test AnyKindAsStruct = CapnpSerializable.Create(reader.AnyKindAsStruct); AnyStructAsStruct = CapnpSerializable.Create(reader.AnyStructAsStruct); AnyKindAsList = CapnpSerializable.Create(reader.AnyKindAsList); - AnyListAsList = reader.AnyListAsList.ToReadOnlyList(_ => (object)_); + AnyListAsList = reader.AnyListAsList?.ToReadOnlyList(_ => (object)_); applyDefaults(); } @@ -10028,7 +10028,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestInterface.Params_foo() {I = i, J = j}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(9865999890858873522UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return (r_.X); @@ -10039,7 +10039,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestInterface.Params_bar() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(9865999890858873522UL, 1, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -10050,7 +10050,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestInterface.Params_baz() {S = s}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(9865999890858873522UL, 2, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -10443,7 +10443,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestExtends.Params_qux() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(16494920484927878984UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -10452,7 +10452,7 @@ namespace Capnproto_test.Capnp.Test public async Task Corge(Capnproto_test.Capnp.Test.TestAllTypes arg_, CancellationToken cancellationToken_ = default) { var in_ = SerializerState.CreateForRpc(); - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(16494920484927878984UL, 1, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -10463,7 +10463,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestExtends.Params_grault() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(16494920484927878984UL, 2, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return r_; @@ -10474,7 +10474,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestInterface.Params_foo() {I = i, J = j}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(9865999890858873522UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return (r_.X); @@ -10485,7 +10485,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestInterface.Params_bar() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(9865999890858873522UL, 1, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -10496,7 +10496,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestInterface.Params_baz() {S = s}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(9865999890858873522UL, 2, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -10733,7 +10733,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestExtends.Params_qux() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(16494920484927878984UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -10742,7 +10742,7 @@ namespace Capnproto_test.Capnp.Test public async Task Corge(Capnproto_test.Capnp.Test.TestAllTypes arg_, CancellationToken cancellationToken_ = default) { var in_ = SerializerState.CreateForRpc(); - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(16494920484927878984UL, 1, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -10753,7 +10753,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestExtends.Params_grault() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(16494920484927878984UL, 2, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return r_; @@ -10764,7 +10764,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestInterface.Params_foo() {I = i, J = j}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(9865999890858873522UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return (r_.X); @@ -10775,7 +10775,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestInterface.Params_bar() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(9865999890858873522UL, 1, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -10786,7 +10786,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestInterface.Params_baz() {S = s}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(9865999890858873522UL, 2, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -10818,7 +10818,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestPipeline.Params_getCap() {N = n, InCap = inCap}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(11935670180855499984UL, 0, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create(d_); @@ -10833,7 +10833,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestPipeline.Params_testPointers() {Cap = cap, Obj = obj, List = list}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(11935670180855499984UL, 1, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -10844,7 +10844,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestPipeline.Params_getAnyCap() {N = n, InCap = inCap}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(11935670180855499984UL, 2, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create(d_); @@ -11471,7 +11471,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestCallOrder.Params_getCallSequence() {Expected = expected}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(11594359141811814481UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return (r_.N); @@ -11637,7 +11637,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestTailCallee.Params_foo() {I = i, T = t}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(15985132292242203195UL, 0, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create(d_); @@ -11851,7 +11851,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestTailCaller.Params_foo() {I = i, Callee = callee}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(9731139705278181429UL, 0, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create(d_); @@ -12006,7 +12006,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMoreStuff.Params_callFoo() {Cap = cap}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(15980754968839795663UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return (r_.S); @@ -12017,7 +12017,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMoreStuff.Params_callFooWhenResolved() {Cap = cap}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(15980754968839795663UL, 1, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return (r_.S); @@ -12028,7 +12028,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMoreStuff.Params_neverReturn() {Cap = cap}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(15980754968839795663UL, 2, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create(d_); @@ -12043,7 +12043,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMoreStuff.Params_hold() {Cap = cap}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(15980754968839795663UL, 3, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -12054,7 +12054,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMoreStuff.Params_callHeld() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(15980754968839795663UL, 4, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return (r_.S); @@ -12065,7 +12065,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMoreStuff.Params_getHeld() {}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(15980754968839795663UL, 5, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create(d_); @@ -12080,7 +12080,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMoreStuff.Params_echo() {Cap = cap}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(15980754968839795663UL, 6, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create(d_); @@ -12095,7 +12095,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMoreStuff.Params_expectCancel() {Cap = cap}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(15980754968839795663UL, 7, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -12106,7 +12106,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMoreStuff.Params_methodWithDefaults() {A = a, B = b, C = c}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(15980754968839795663UL, 8, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return (r_.D, r_.E); @@ -12117,7 +12117,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMoreStuff.Params_getHandle() {}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(15980754968839795663UL, 9, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create(d_); @@ -12132,7 +12132,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMoreStuff.Params_getNull() {}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(15980754968839795663UL, 10, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create(d_); @@ -12147,7 +12147,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMoreStuff.Params_getEnormousString() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(15980754968839795663UL, 11, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return (r_.Str); @@ -12158,7 +12158,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMoreStuff.Params_methodWithNullDefault() {A = a, B = b}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(15980754968839795663UL, 12, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -12169,7 +12169,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestCallOrder.Params_getCallSequence() {Expected = expected}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(11594359141811814481UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return (r_.N); @@ -13867,7 +13867,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMembrane.Params_makeThing() {}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(13870398341137210380UL, 0, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create(d_); @@ -13882,7 +13882,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMembrane.Params_callPassThrough() {Thing = thing, TailCall = tailCall}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(13870398341137210380UL, 1, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return r_; @@ -13893,7 +13893,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMembrane.Params_callIntercept() {Thing = thing, TailCall = tailCall}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(13870398341137210380UL, 2, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return r_; @@ -13904,7 +13904,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMembrane.Params_loopback() {Thing = thing}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(13870398341137210380UL, 3, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create(d_); @@ -13919,7 +13919,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMembrane.Params_waitForever() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(13870398341137210380UL, 4, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -14011,7 +14011,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMembrane.Thing.Params_passThrough() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(10615798940090972439UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return r_; @@ -14022,7 +14022,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestMembrane.Thing.Params_intercept() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(10615798940090972439UL, 1, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return r_; @@ -14763,7 +14763,7 @@ namespace Capnproto_test.Capnp.Test void ICapnpSerializable.Deserialize(DeserializerState arg_) { var reader = READER.create(arg_); - List = reader.List.ToReadOnlyList(_ => CapnpSerializable.Create(_)); + List = reader.List?.ToReadOnlyList(_ => CapnpSerializable.Create(_)); applyDefaults(); } @@ -14907,7 +14907,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestKeywordMethods.Params_delete() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(11160837778045172988UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -14918,7 +14918,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestKeywordMethods.Params_class() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(11160837778045172988UL, 1, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -14929,7 +14929,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestKeywordMethods.Params_void() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(11160837778045172988UL, 2, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -14940,7 +14940,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestKeywordMethods.Params_return() {}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(11160837778045172988UL, 3, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; @@ -15360,7 +15360,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc.Params_getCallerId.WRITER>(); var arg_ = new Capnproto_test.Capnp.Test.TestAuthenticatedBootstrap.Params_getCallerId() {}; - arg_.serialize(in_); + arg_?.serialize(in_); return Impatient.MakePipelineAware(Call(16893789964317726925UL, 0, in_.Rewrap(), false, cancellationToken_), d_ => { var r_ = CapnpSerializable.Create.Result_getCallerId>(d_); @@ -16334,7 +16334,7 @@ namespace Capnproto_test.Capnp.Test var in_ = SerializerState.CreateForRpc(); var arg_ = new Capnproto_test.Capnp.Test.TestNameAnnotationInterface.Params_badlyNamedMethod() {BadlyNamedParam = badlyNamedParam}; - arg_.serialize(in_); + arg_?.serialize(in_); var d_ = await Call(15065286897585459595UL, 0, in_.Rewrap(), false, cancellationToken_).WhenReturned; var r_ = CapnpSerializable.Create(d_); return; diff --git a/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs b/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs index 8096b8e..8537a48 100644 --- a/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs +++ b/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs @@ -1,4 +1,5 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.CodeAnalysis; +using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Diagnostics; using System.IO; @@ -15,6 +16,8 @@ namespace CapnpC.CSharp.Generator.Tests string _inputSchemaFileName; string _inputSchema; string _referenceOutputContent; + bool _nullableGenEnable; + bool _nullableSupportEnable; GenerationResult _result; @@ -56,6 +59,7 @@ namespace CapnpC.CSharp.Generator.Tests public void GivenIHaveABinaryCodeGeneratorRequest(string binaryRequestFileName) { _inputStream = LoadResource(binaryRequestFileName); + _nullableGenEnable = false; // Assume false by default, may be enabled later } [Given(@"my reference output is ""(.*)""")] @@ -71,9 +75,14 @@ namespace CapnpC.CSharp.Generator.Tests [When(@"I invoke capnpc-csharp")] public void WhenIInvokeCapnpc_Csharp() { + Console.WriteLine($"Generate nullable reference types? {_nullableGenEnable}"); + using (_inputStream) { - _result = CapnpCompilation.GenerateFromStream(_inputStream); + _result = CapnpCompilation.GenerateFromStream(_inputStream, new CodeGen.GeneratorOptions() + { + NullableEnableDefault = _nullableGenEnable + }); } } @@ -113,13 +122,6 @@ namespace CapnpC.CSharp.Generator.Tests Assert.IsNotNull(_result.Exception, "Expected an exception"); } - [Then(@"the invocation must succeed and the generated code must compile")] - public void ThenTheInvocationMustSucceedAndTheGeneratedCodeMustCompile() - { - Assert.IsTrue(_result.IsSuccess, "Tool invocation was not successful"); - Assert.IsTrue(Util.InlineAssemblyCompiler.TryCompileCapnp(_result.GeneratedFiles[0].GeneratedContent), "Compilation was not successful"); - } - [Given(@"capnp\.exe is installed on my system")] public void GivenCapnp_ExeIsInstalledOnMySystem() { @@ -185,5 +187,69 @@ namespace CapnpC.CSharp.Generator.Tests { Assert.IsTrue(_result.Messages.Count >= 2); } + + [Given(@"I enable generation of nullable reference types according to (.*)")] + public void GivenIEnableGenerationOfNullableReferenceTypesAccordingTo(bool enable) + { + _nullableGenEnable = enable; + } + + [Given(@"I enable the compiler support of nullable reference types according to (.*)")] + public void GivenIEnableTheCompilerSupportOfNullableReferenceTypesAccordingTo(bool enable) + { + _nullableSupportEnable = enable; + } + + [Then(@"the invocation must succeed and attempting to compile the generated code gives (.*)")] + public void ThenTheInvocationMustSucceedAndAttemptingToCompileTheGeneratedCodeGives(string result) + { + Console.WriteLine($"Compiler supports nullable reference types? {_nullableSupportEnable}"); + + Assert.IsTrue(_result.IsSuccess, "Tool invocation was not successful"); + var summary = Util.InlineAssemblyCompiler.TryCompileCapnp( + _nullableSupportEnable ? NullableContextOptions.Enable : NullableContextOptions.Disable, + _result.GeneratedFiles[0].GeneratedContent); + + try + { + switch (result) + { + case "success": + Assert.AreEqual( + Util.InlineAssemblyCompiler.CompileSummary.Success, + summary, + "Compilation was expected to succeed"); + break; + + case "warnings": + Assert.AreEqual( + Util.InlineAssemblyCompiler.CompileSummary.SuccessWithWarnings, + summary, + "Compilation was expected to produce warnings"); + break; + + case "errors": + Assert.AreEqual( + Util.InlineAssemblyCompiler.CompileSummary.Error, + summary, + "Compilation was expected to fail"); + break; + + default: + Assert.Fail("Test case bug: unknown outcome specified"); + break; + + } + } + catch (AssertFailedException) + { + string generated = _result.GeneratedFiles.Single().GeneratedContent; + string path = Path.ChangeExtension(Path.GetTempFileName(), ".capnp.cs"); + File.WriteAllText(path, generated); + Console.WriteLine($"Generated code was saved to {path}"); + + throw; + } + } } } diff --git a/CapnpC.CSharp.Generator.Tests/No Resources/NullableDisable.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/NullableDisable.capnp new file mode 100644 index 0000000..c859c9d --- /dev/null +++ b/CapnpC.CSharp.Generator.Tests/No Resources/NullableDisable.capnp @@ -0,0 +1,9 @@ +@0xbbfd48ae4b99d016; + +using CSharp = import "/csharp.capnp"; + +$CSharp.nullableEnable(false); + +struct SomeStruct { + strings @0 : List(Text); +} diff --git a/CapnpC.CSharp.Generator.Tests/No Resources/NullableEnable.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/NullableEnable.capnp new file mode 100644 index 0000000..9e5833a --- /dev/null +++ b/CapnpC.CSharp.Generator.Tests/No Resources/NullableEnable.capnp @@ -0,0 +1,9 @@ +@0xbbfd48ae4b99d016; + +using CSharp = import "/csharp.capnp"; + +$CSharp.nullableEnable(true); + +struct SomeStruct { + strings @0 : List(Text); +} diff --git a/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest13.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest13.capnp new file mode 100644 index 0000000..36db615 --- /dev/null +++ b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest13.capnp @@ -0,0 +1,8 @@ +@0xbbfd48ae4b99d013; + +using CSharp = import "/csharp.capnp"; + +$CSharp.namespace("Foo.Bar.Baz"); + +struct SomeStruct { +} diff --git a/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest14.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest14.capnp new file mode 100644 index 0000000..4472e01 --- /dev/null +++ b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest14.capnp @@ -0,0 +1,10 @@ +@0xbbfd48ae4b99d014; + +using Cxx = import "/capnp/c++.capnp"; +using CSharp = import "/csharp.capnp"; + +$CSharp.namespace("Foo.Bar.Baz"); +$Cxx.namespace("X::Y::Z"); + +struct SomeStruct { +} diff --git a/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest15.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest15.capnp new file mode 100644 index 0000000..3968870 --- /dev/null +++ b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest15.capnp @@ -0,0 +1,25 @@ +@0xbbfd48ae4b99d013; + +using CSharp = import "/csharp.capnp"; + +struct SomeStruct $CSharp.name("CsStruct") { + someField @0 : Int32 $CSharp.name("CsField"); + + someUnion : union $CSharp.name("CsUnion") { + u0 @1 : Int32; + u1 @2 : Int32; + } + + someGroup : group $CSharp.name("CsGroup") { + g0 @3 : Int32; + g1 @4 : Int32; + } +} + +enum SomeEnum $CSharp.name("CsEnum") { + someEnumerant @0 $CSharp.name("CsEnumerant"); +} + +interface SomeInterface $CSharp.name("CsInterface") { + someMethod @0 () -> (someResult :Bool $CSharp.name("CsResult") ) $CSharp.name("CsMethod"); +} diff --git a/CapnpC.CSharp.Generator.Tests/Util/InlineAssemblyCompiler.cs b/CapnpC.CSharp.Generator.Tests/Util/InlineAssemblyCompiler.cs index 3194f0f..50422d6 100644 --- a/CapnpC.CSharp.Generator.Tests/Util/InlineAssemblyCompiler.cs +++ b/CapnpC.CSharp.Generator.Tests/Util/InlineAssemblyCompiler.cs @@ -1,25 +1,27 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using System; -using System.Collections.Generic; using System.IO; +using System.Linq; using System.Reflection; -using System.Text; namespace CapnpC.CSharp.Generator.Tests.Util { class InlineAssemblyCompiler { - public static bool TryCompileCapnp(string code) + public enum CompileSummary { - return TryCompileCapnp(new[] {code}); + Success, + SuccessWithWarnings, + Error } - public static bool TryCompileCapnp(string[] code) + public static CompileSummary TryCompileCapnp(NullableContextOptions nullableContextOptions, params string[] code) { var options = new CSharpCompilationOptions( OutputKind.DynamicallyLinkedLibrary, - optimizationLevel: OptimizationLevel.Debug); + optimizationLevel: OptimizationLevel.Debug, + nullableContextOptions: nullableContextOptions); string assemblyRoot = Path.GetDirectoryName(typeof(object).Assembly.Location); @@ -29,7 +31,7 @@ namespace CapnpC.CSharp.Generator.Tests.Util "Capnp.Net.Runtime", "bin", "Debug", - "netcoreapp2.1", + "netcoreapp3.0", "Capnp.Net.Runtime.dll")); var compilation = CSharpCompilation.Create( @@ -61,7 +63,17 @@ namespace CapnpC.CSharp.Generator.Tests.Util } } - return emitResult.Success; + if (emitResult.Success) + { + if (emitResult.Diagnostics.Any(diag => diag.Severity == DiagnosticSeverity.Warning)) + return CompileSummary.SuccessWithWarnings; + else + return CompileSummary.Success; + } + else + { + return CompileSummary.Error; + } } } } diff --git a/CapnpC.CSharp.Generator/CapnpCompilation.cs b/CapnpC.CSharp.Generator/CapnpCompilation.cs index 9e9f8d0..2bbf913 100644 --- a/CapnpC.CSharp.Generator/CapnpCompilation.cs +++ b/CapnpC.CSharp.Generator/CapnpCompilation.cs @@ -27,10 +27,11 @@ namespace CapnpC.CSharp.Generator /// /// Generates C# code from given input stream /// - /// input stream containing the binary code generation request, which the frontend capnpc emits + /// Input stream containing the binary code generation request, which the frontend capnpc emits + /// Configuration options for code generator. If null, default options will be used. /// generation result /// if is null - public static GenerationResult GenerateFromStream(Stream input) + public static GenerationResult GenerateFromStream(Stream input, CodeGen.GeneratorOptions options) { if (input == null) throw new ArgumentNullException(nameof(input)); @@ -41,7 +42,7 @@ namespace CapnpC.CSharp.Generator var dec = DeserializerState.CreateRoot(segments); var reader = Schema.CodeGeneratorRequest.Reader.Create(dec); var model = Model.SchemaModel.Create(reader); - var codeGen = new CodeGen.CodeGenerator(model, new CodeGen.GeneratorOptions()); + var codeGen = new CodeGen.CodeGenerator(model, options ?? new CodeGen.GeneratorOptions()); return new GenerationResult(codeGen.Generate()); } catch (Exception exception) @@ -50,6 +51,14 @@ namespace CapnpC.CSharp.Generator } } + /// + /// Generates C# code from given input stream + /// + /// input stream containing the binary code generation request, which the frontend capnpc emits + /// generation result + /// if is null + public static GenerationResult GenerateFromStream(Stream input) => GenerateFromStream(input, null); + /// /// Invokes "capnp.exe -o-" with given additional arguments and redirects the output to the C# generator backend. /// diff --git a/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs b/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs index 6482844..2f37b9b 100644 --- a/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs +++ b/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs @@ -14,6 +14,7 @@ internal class CodeGenerator { readonly SchemaModel _model; + readonly GeneratorOptions _options; readonly GenNames _names; readonly CommonSnippetGen _commonGen; readonly DomainClassSnippetGen _domClassGen; @@ -24,6 +25,7 @@ public CodeGenerator(SchemaModel model, GeneratorOptions options) { _model = model; + _options = options; _names = new GenNames(options); _commonGen = new CommonSnippetGen(_names); _domClassGen = new DomainClassSnippetGen(_names); @@ -184,7 +186,7 @@ internal string Transform(GenFile file) { - _names.NullableEnable = file.NullableEnable; + _names.NullableEnable = file.NullableEnable ?? _options.NullableEnableDefault; NameSyntax topNamespace = GenNames.NamespaceName(file.Namespace) ?? _names.TopNamespace; diff --git a/CapnpC.CSharp.Generator/CodeGen/CommonSnippetGen.cs b/CapnpC.CSharp.Generator/CodeGen/CommonSnippetGen.cs index a94bf8e..72de969 100644 --- a/CapnpC.CSharp.Generator/CodeGen/CommonSnippetGen.cs +++ b/CapnpC.CSharp.Generator/CodeGen/CommonSnippetGen.cs @@ -49,14 +49,14 @@ namespace CapnpC.CSharp.Generator.CodeGen public EnumDeclarationSyntax MakeEnum(TypeDefinition def) { - var decl = EnumDeclaration(def.Name) + var decl = EnumDeclaration(_names.GetCodeIdentifier(def)) .WithAttributeLists(MakeTypeIdAttributeLists(def.Id)) .AddModifiers(Public) .AddBaseListTypes(SimpleBaseType(_names.Type(Nullability.NonNullable))); foreach (var enumerant in def.Enumerants.OrderBy(e => e.CodeOrder)) { - var mdecl = EnumMemberDeclaration(enumerant.Literal); + var mdecl = EnumMemberDeclaration(enumerant.CsLiteral ?? enumerant.Literal); if (enumerant.Ordinal.HasValue) { diff --git a/CapnpC.CSharp.Generator/CodeGen/DomainClassSnippetGen.cs b/CapnpC.CSharp.Generator/CodeGen/DomainClassSnippetGen.cs index 7737ae7..17af353 100644 --- a/CapnpC.CSharp.Generator/CodeGen/DomainClassSnippetGen.cs +++ b/CapnpC.CSharp.Generator/CodeGen/DomainClassSnippetGen.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; using static CapnpC.CSharp.Generator.CodeGen.SyntaxHelpers; +using Microsoft.CodeAnalysis; namespace CapnpC.CSharp.Generator.CodeGen { @@ -452,13 +453,18 @@ namespace CapnpC.CSharp.Generator.CodeGen Argument(domain), Argument( ParenthesizedLambdaExpression( + ParameterList( + SeparatedList( + new SyntaxNodeOrToken[] + { + Parameter(Identifier(s)), + Token(SyntaxKind.CommaToken), + Parameter(Identifier(v)) + })), MakeComplexSerializeParticle( type.ElementType, IdentifierName(s), - IdentifierName(v))) - .AddParameterListParameters( - Parameter(Identifier(s)), - Parameter(Identifier(v))))); + IdentifierName(v))))); default: return InvocationExpression( diff --git a/CapnpC.CSharp.Generator/CodeGen/GenNames.cs b/CapnpC.CSharp.Generator/CodeGen/GenNames.cs index 1c9e42c..b16ff99 100644 --- a/CapnpC.CSharp.Generator/CodeGen/GenNames.cs +++ b/CapnpC.CSharp.Generator/CodeGen/GenNames.cs @@ -114,61 +114,54 @@ namespace CapnpC.CSharp.Generator.CodeGen public Name MakeTypeName(TypeDefinition def, NameUsage usage = NameUsage.Default) { - if (def.Tag == TypeTag.Group) + string name; + + switch (usage) { - return new Name(SyntaxHelpers.MakeAllLower(def.Name)); + case NameUsage.Default: + if (def.Tag == TypeTag.Interface) + goto case NameUsage.Interface; + + switch (def.SpecialName) + { + case SpecialName.NothingSpecial: + name = GetCodeIdentifier(def); + 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 = GetCodeIdentifier(def); + break; + + case NameUsage.Interface: + name = "I" + GetCodeIdentifier(def); + break; + + case NameUsage.Proxy: + name = string.Format(ProxyClassFormat, GetCodeIdentifier(def)); + break; + + case NameUsage.Skeleton: + name = string.Format(SkeletonClassFormat, GetCodeIdentifier(def)); + break; + + default: + throw new NotImplementedException(); } - 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 = string.Format(ProxyClassFormat, def.Name); - break; - - case NameUsage.Skeleton: - name = string.Format(SkeletonClassFormat, def.Name); - break; - - default: - throw new NotImplementedException(); - } - - return new Name(name); - } + return new Name(name); } public SimpleNameSyntax MakeGenericTypeName(TypeDefinition def, NameUsage usage = NameUsage.Default) @@ -231,10 +224,10 @@ namespace CapnpC.CSharp.Generator.CodeGen NameSyntax ident = null; if (@namespace != null) { - ident = IdentifierName(SyntaxHelpers.MakeCamel(@namespace[0])); + ident = IdentifierName(SyntaxHelpers.MakeUpperCamel(@namespace[0])); foreach (string name in @namespace.Skip(1)) { - var temp = IdentifierName(SyntaxHelpers.MakeCamel(name)); + var temp = IdentifierName(SyntaxHelpers.MakeUpperCamel(name)); ident = QualifiedName(ident, temp); } } @@ -380,6 +373,9 @@ namespace CapnpC.CSharp.Generator.CodeGen TypeSyntax MaybeNullableRefType(TypeSyntax typeSyntax, Nullability nullability) { + if (!NullableEnable) + return typeSyntax; + switch (nullability) { case Nullability.NullableRef: @@ -555,19 +551,22 @@ namespace CapnpC.CSharp.Generator.CodeGen public string MakeParamsStructName(Method method) { - return string.Format(ParamsStructFormat, method.Name); + return string.Format(ParamsStructFormat, GetCodeIdentifier(method)); } public string MakeResultStructName(Method method) { - return string.Format(ResultStructFormat, method.Name); + return string.Format(ResultStructFormat, GetCodeIdentifier(method)); } public Name GetCodeIdentifier(Method method) { - return new Name(SyntaxHelpers.MakeCamel(method.Name)); + return new Name(method.CsName ?? IdentifierRenamer.ToNonKeyword(SyntaxHelpers.MakeUpperCamel(method.Name))); } + string GetCodeIdentifierUpperCamel(Field field) => field.CsName ?? SyntaxHelpers.MakeUpperCamel(field.Name); + string GetCodeIdentifierLowerCamel(Field field) => field.CsName ?? IdentifierRenamer.ToNonKeyword(SyntaxHelpers.MakeLowerCamel(field.Name)); + public Name GetCodeIdentifier(Field field) { if (_fieldNameMap.TryGetValue(field, out var name)) @@ -581,7 +580,7 @@ namespace CapnpC.CSharp.Generator.CodeGen { // 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)); + return new Name(GetCodeIdentifierLowerCamel(field)); } var typeNames = new HashSet(def.NestedTypes.Select(t => MakeTypeName(t))); @@ -589,7 +588,7 @@ namespace CapnpC.CSharp.Generator.CodeGen foreach (var member in def.Fields) { - var memberName = new Name(SyntaxHelpers.MakeCamel(member.Name)); + var memberName = new Name(GetCodeIdentifierUpperCamel(member)); while (typeNames.Contains(memberName)) { @@ -602,6 +601,16 @@ namespace CapnpC.CSharp.Generator.CodeGen return _fieldNameMap[field]; } + public string GetCodeIdentifier(TypeDefinition def) + { + string id = def.CsName ?? def.Name; + if (def.Tag == TypeTag.Group) // special treatment for groups: Need to disambiguate between + { // the field name (use original name) and its type (make it start with a lower-case letter) + id = IdentifierRenamer.ToNonKeyword(SyntaxHelpers.MakeLowerCamel(id)); + } + return id; + } + public Name GetGenericTypeParameter(string name) { return new Name(string.Format(GenericTypeParameterFormat, name)); diff --git a/CapnpC.CSharp.Generator/CodeGen/GeneratorOptions.cs b/CapnpC.CSharp.Generator/CodeGen/GeneratorOptions.cs index 8357cee..3a3eccf 100644 --- a/CapnpC.CSharp.Generator/CodeGen/GeneratorOptions.cs +++ b/CapnpC.CSharp.Generator/CodeGen/GeneratorOptions.cs @@ -1,6 +1,6 @@ namespace CapnpC.CSharp.Generator.CodeGen { - class GeneratorOptions + public class GeneratorOptions { public string TopNamespaceName { get; set; } = "CapnpGen"; public string ReaderStructName { get; set; } = "READER"; @@ -37,5 +37,6 @@ public string TaskParameterName { get; set; } = "task"; public string EagerMethodName { get; set; } = "Eager"; public string TypeIdFieldName { get; set; } = "typeId"; + public bool NullableEnableDefault { get; set; } = false; } } diff --git a/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs b/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs index 3fe4350..c683f3b 100644 --- a/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs +++ b/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs @@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using System.Threading.Tasks; using System.Threading; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis; namespace CapnpC.CSharp.Generator.CodeGen { @@ -60,7 +61,7 @@ namespace CapnpC.CSharp.Generator.CodeGen { foreach (var arg in method.Params) { - list.Add(Parameter(Identifier(IdentifierRenamer.ToNonKeyword(arg.Name))) + list.Add(Parameter(_names.GetCodeIdentifier(arg).Identifier) .WithType(_names.MakeTypeSyntax(arg.Type, method.DeclaringInterface, TypeUsage.DomainClass, Nullability.NullableRef))); } } @@ -187,12 +188,15 @@ namespace CapnpC.CSharp.Generator.CodeGen IEnumerable MakeProxyCallInitializerAssignments(Method method) { - foreach (var methodParam in method.Params) + for (int i = 0; i < method.Params.Count; i++) { + var methodParam = method.Params[i]; + var field = method.ParamsStruct.Fields[i]; + yield return AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, - _names.GetCodeIdentifier(methodParam).IdentifierName, - IdentifierName(IdentifierRenamer.ToNonKeyword(methodParam.Name))); + _names.GetCodeIdentifier(field).IdentifierName, + _names.GetCodeIdentifier(methodParam).IdentifierName); } } @@ -650,10 +654,19 @@ namespace CapnpC.CSharp.Generator.CodeGen } else { + // CodeAnalysis.CSharp 3.2.1 has a bug which prevents us from using AddParameterListParameters. :-( + + var paramList = new List(); + foreach (var arg in method.Results) + { + if (paramList.Count > 0) + paramList.Add(Token(SyntaxKind.CommaToken)); + paramList.Add(Parameter(Identifier(arg.Name))); + } lambdaArg = ParenthesizedLambdaExpression( - MakeMaybeTailCallLambdaBody(method)) - .AddParameterListParameters( - method.Results.Select(arg => Parameter(Identifier(arg.Name))).ToArray()); + ParameterList( + SeparatedList(paramList)), + MakeMaybeTailCallLambdaBody(method)); } } else @@ -835,9 +848,7 @@ namespace CapnpC.CSharp.Generator.CodeGen .AddModifiers(Static, Readonly); - var methodDecl = MethodDeclaration( - capTypeSyntax, - methodName.Identifier) + var methodDecl = MethodDeclaration(capTypeSyntax, methodName.Identifier) .AddModifiers(Public, Static) .AddParameterListParameters( Parameter( diff --git a/CapnpC.CSharp.Generator/CodeGen/SyntaxHelpers.cs b/CapnpC.CSharp.Generator/CodeGen/SyntaxHelpers.cs index d532107..be46e5d 100644 --- a/CapnpC.CSharp.Generator/CodeGen/SyntaxHelpers.cs +++ b/CapnpC.CSharp.Generator/CodeGen/SyntaxHelpers.cs @@ -9,8 +9,8 @@ namespace CapnpC.CSharp.Generator.CodeGen { 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 string MakeUpperCamel(string name) => $"{char.ToUpperInvariant(name[0])}{name.Substring(1)}"; + public static string MakeLowerCamel(string name) => $"{char.ToLowerInvariant(name[0])}{name.Substring(1)}"; public static readonly SyntaxToken Async = Token(SyntaxKind.AsyncKeyword); public static readonly SyntaxToken Public = Token(SyntaxKind.PublicKeyword); diff --git a/CapnpC.CSharp.Generator/Model/Enumerant.cs b/CapnpC.CSharp.Generator/Model/Enumerant.cs index 4ba17f6..51eac1b 100644 --- a/CapnpC.CSharp.Generator/Model/Enumerant.cs +++ b/CapnpC.CSharp.Generator/Model/Enumerant.cs @@ -8,6 +8,7 @@ get => _literal; set => _literal = IdentifierRenamer.ToNonKeyword(value); } + public string CsLiteral { get; set; } public ushort? Ordinal { get; set; } public int CodeOrder { get; set; } } diff --git a/CapnpC.CSharp.Generator/Model/Field.cs b/CapnpC.CSharp.Generator/Model/Field.cs index 017112c..114652b 100644 --- a/CapnpC.CSharp.Generator/Model/Field.cs +++ b/CapnpC.CSharp.Generator/Model/Field.cs @@ -5,6 +5,7 @@ public TypeDefinition DeclaringType { get; set; } public Field Parent { get; set; } public string Name { get; set; } + public string CsName { get; set; } public Type Type { get; set; } public Value DefaultValue { get; set; } public bool DefaultValueIsExplicit { get; set; } diff --git a/CapnpC.CSharp.Generator/Model/GenFile.cs b/CapnpC.CSharp.Generator/Model/GenFile.cs index d111956..64cf51b 100644 --- a/CapnpC.CSharp.Generator/Model/GenFile.cs +++ b/CapnpC.CSharp.Generator/Model/GenFile.cs @@ -11,7 +11,7 @@ namespace CapnpC.CSharp.Generator.Model public string Name { get; set; } public string[] Namespace { get; set; } - public bool NullableEnable { get; set; } = true; + public bool? NullableEnable { get; set; } public IEnumerable NestedTypes { get => this.GetNestedTypes(); } public ICollection NestedDefinitions { get; } = new List(); diff --git a/CapnpC.CSharp.Generator/Model/Method.cs b/CapnpC.CSharp.Generator/Model/Method.cs index f7f2109..cfa65ff 100644 --- a/CapnpC.CSharp.Generator/Model/Method.cs +++ b/CapnpC.CSharp.Generator/Model/Method.cs @@ -8,6 +8,7 @@ namespace CapnpC.CSharp.Generator.Model public TypeDefinition DeclaringInterface { get; set; } public int Id { get; set; } public string Name { get; set; } + public string CsName { get; set; } public List Params { get; } = new List(); public List Results { get; } = new List(); public Type ParamsStruct { get; set; } @@ -21,6 +22,7 @@ namespace CapnpC.CSharp.Generator.Model DeclaringInterface = DeclaringInterface, Id = Id, Name = Name, + CsName = CsName, ParamsStruct = ParamsStruct, ResultStruct = ResultStruct }; diff --git a/CapnpC.CSharp.Generator/Model/SchemaModel.cs b/CapnpC.CSharp.Generator/Model/SchemaModel.cs index f0b9c88..515050d 100644 --- a/CapnpC.CSharp.Generator/Model/SchemaModel.cs +++ b/CapnpC.CSharp.Generator/Model/SchemaModel.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using System.Text; +using static CapnpC.CSharp.Generator.Model.SupportedAnnotations; namespace CapnpC.CSharp.Generator.Model { @@ -92,6 +92,7 @@ namespace CapnpC.CSharp.Generator.Model state.parent = null; file.Namespace = GetNamespaceAnnotation(node); file.Name = name; + file.NullableEnable = GetNullableEnable(node); return ProcessNodePass1(id, name, state) as GenFile; } @@ -145,6 +146,7 @@ namespace CapnpC.CSharp.Generator.Model 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; + typeDef.CsName = GetCsName(node); state.parent = typeDef; def = typeDef; } @@ -175,18 +177,6 @@ namespace CapnpC.CSharp.Generator.Model 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 @@ -492,6 +482,7 @@ namespace CapnpC.CSharp.Generator.Model { DeclaringType = declaringType, Name = fieldReader.Name, + CsName = GetCsName(fieldReader), CodeOrder = fieldReader.CodeOrder }; @@ -505,6 +496,8 @@ namespace CapnpC.CSharp.Generator.Model case 0 when fieldReader.IsGroup: var def = ProcessTypeDef(fieldReader.Group_TypeId, state, TypeTag.Group); field.Type = Types.FromDefinition(def); + def.CsName = field.CsName; // Type definitions for unions are artificially generated. + // Transfer the C# name of the using field. break; case 0 when fieldReader.IsSlot: @@ -549,7 +542,8 @@ namespace CapnpC.CSharp.Generator.Model { DeclaringInterface = def, Id = def.Methods.Count, - Name = methodReader.Name + Name = methodReader.Name, + CsName = GetCsName(methodReader) }; foreach (var implicitParameterReader in methodReader.ImplicitParameters) { @@ -664,6 +658,7 @@ namespace CapnpC.CSharp.Generator.Model { TypeDefinition = def, Literal = fieldReader.Name, + CsLiteral = GetCsName(fieldReader), CodeOrder = fieldReader.CodeOrder }; @@ -745,9 +740,6 @@ namespace CapnpC.CSharp.Generator.Model 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}"; diff --git a/CapnpC.CSharp.Generator/Model/SupportedAnnotations.cs b/CapnpC.CSharp.Generator/Model/SupportedAnnotations.cs new file mode 100644 index 0000000..3ef6eb1 --- /dev/null +++ b/CapnpC.CSharp.Generator/Model/SupportedAnnotations.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CapnpC.CSharp.Generator.Model +{ + static class SupportedAnnotations + { + static class AnnotationIds + { + public static class Cxx + { + public const ulong Namespace = 0xb9c6f99ebf805f2c; + } + + public static class Cs + { + public const ulong Namespace = 0xeb0d831668c6eda0; + public const ulong NullableEnable = 0xeb0d831668c6eda1; + public const ulong Name = 0xeb0d831668c6eda2; + } + } + + public static string[] GetNamespaceAnnotation(Schema.Node.Reader fileNode) + { + foreach (var annotation in fileNode.Annotations) + { + if (annotation.Id == AnnotationIds.Cs.Namespace) + { + return annotation.Value.Text.Split(new string[1] { "." }, default); + } + + if (annotation.Id == AnnotationIds.Cxx.Namespace) + { + return annotation.Value.Text.Split(new string[1] { "::" }, default); + } + } + return null; + } + + public static string GetCsName(Schema.Field.Reader node) + { + foreach (var annotation in node.Annotations) + { + if (annotation.Id == AnnotationIds.Cs.Name) + { + return annotation.Value.Text; + } + } + return null; + } + + public static string GetCsName(Schema.Node.Reader node) + { + foreach (var annotation in node.Annotations) + { + if (annotation.Id == AnnotationIds.Cs.Name) + { + return annotation.Value.Text; + } + } + return null; + } + + public static string GetCsName(Schema.Method.Reader node) + { + foreach (var annotation in node.Annotations) + { + if (annotation.Id == AnnotationIds.Cs.Name) + { + return annotation.Value.Text; + } + } + return null; + } + + public static bool? GetNullableEnable(Schema.Node.Reader node) + { + foreach (var annotation in node.Annotations) + { + if (annotation.Id == AnnotationIds.Cs.NullableEnable && annotation.Value.IsBool) + { + return annotation.Value.Bool; + } + } + return null; + } + } +} diff --git a/CapnpC.CSharp.Generator/Model/TypeDefinition.cs b/CapnpC.CSharp.Generator/Model/TypeDefinition.cs index 61e8e64..dd901f7 100644 --- a/CapnpC.CSharp.Generator/Model/TypeDefinition.cs +++ b/CapnpC.CSharp.Generator/Model/TypeDefinition.cs @@ -37,6 +37,7 @@ namespace CapnpC.CSharp.Generator.Model public Method UsingMethod { get; set; } public string Name { get; set; } + public string CsName { get; set; } public SpecialName SpecialName { get; set; } public DiscriminationInfo UnionInfo { get; set; } public List Fields { get; } = new List(); 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 index 8fc6607..4069eee 100644 --- a/CapnpC.CSharp.MsBuild.Generation.Tests/CapnpC.CSharp.MsBuild.Generation.Tests.csproj +++ b/CapnpC.CSharp.MsBuild.Generation.Tests/CapnpC.CSharp.MsBuild.Generation.Tests.csproj @@ -1,7 +1,7 @@  - netcoreapp2.1 + netcoreapp3.0 false diff --git a/include/csharp.capnp b/include/csharp.capnp index 67ac9a3..8465cbf 100644 --- a/include/csharp.capnp +++ b/include/csharp.capnp @@ -1,11 +1,11 @@ @0xeb0d831668c6edab; -$csNamespace("Capnp.Annotations"); +$namespace("Capnp.Annotations"); -annotation csNamespace @0xeb0d831668c6eda0 (file) : Text; +annotation namespace @0xeb0d831668c6eda0 (file) : Text; # C# namespace for code generation -annotation csNullableEnable @0xeb0d831668c6eda1 (file) : Bool; +annotation nullableEnable @0xeb0d831668c6eda1 (file) : Bool; # Whether to generate C# nullable reference types -annotation csName @0xeb0d831668c6eda2 (field, enumerant, struct, enum, interface, method, param, group, union) : Text; +annotation name @0xeb0d831668c6eda2 (field, enumerant, struct, enum, interface, method, param, group, union) : Text; # C# member name for code generation