diff --git a/.gitignore b/.gitignore
index cc27174..64fa334 100644
--- a/.gitignore
+++ b/.gitignore
@@ -332,3 +332,7 @@ ASALocalRun/
.mfractor/
.vscode/tasks.json
.vscode/launch.json
+
+# Capnp code behind
+*.capnp.cs
+/globalPackages
diff --git a/Capnp.Net.Runtime.Tests.Core21/Capnp.Net.Runtime.Tests.Core21.csproj b/Capnp.Net.Runtime.Tests.Core21/Capnp.Net.Runtime.Tests.Core21.csproj
index d72aa67..d4a9e68 100644
--- a/Capnp.Net.Runtime.Tests.Core21/Capnp.Net.Runtime.Tests.Core21.csproj
+++ b/Capnp.Net.Runtime.Tests.Core21/Capnp.Net.Runtime.Tests.Core21.csproj
@@ -4,6 +4,8 @@
netcoreapp2.2
false
+
+ Debug;Release
@@ -31,6 +33,7 @@
+
diff --git a/Capnp.Net.Runtime.Tests/Capnp.Net.Runtime.Tests.Std20.csproj b/Capnp.Net.Runtime.Tests/Capnp.Net.Runtime.Tests.Std20.csproj
index 5048b1c..d722dd3 100644
--- a/Capnp.Net.Runtime.Tests/Capnp.Net.Runtime.Tests.Std20.csproj
+++ b/Capnp.Net.Runtime.Tests/Capnp.Net.Runtime.Tests.Std20.csproj
@@ -8,6 +8,8 @@
7.1
Library
+
+ Debug;Release
@@ -15,6 +17,7 @@
+
diff --git a/Capnp.Net.Runtime/Capnp.Net.Runtime.csproj b/Capnp.Net.Runtime/Capnp.Net.Runtime.csproj
index ae162a8..90555c9 100644
--- a/Capnp.Net.Runtime/Capnp.Net.Runtime.csproj
+++ b/Capnp.Net.Runtime/Capnp.Net.Runtime.csproj
@@ -7,6 +7,7 @@
Capnp.Net.Runtime
Capnp.Net.Runtime
true
+ ..\bin\$(Configuration)
Christian Köllner and contributors
A Cap'n Proto implementation for .NET Standard & Core
capnproto-dotnetcore
@@ -17,17 +18,14 @@
MIT
Git
capnp "Cap'n Proto" RPC serialization cerealization
- 1.0.0
+ 1.0-local$([System.DateTime]::UtcNow.ToString(yyMMddHHmm))
+ Debug;Release
TRACE
-
-
-
-
-
+
diff --git a/Capnp.Net.sln b/Capnp.Net.sln
index 41f5968..ff53c1c 100644
--- a/Capnp.Net.sln
+++ b/Capnp.Net.sln
@@ -11,7 +11,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnp.Net.Runtime.Tests.Std
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnp.Net.Runtime.Tests.Core21", "Capnp.Net.Runtime.Tests.Core21\Capnp.Net.Runtime.Tests.Core21.csproj", "{58E8FFC8-D207-4B0F-842A-58ED9D3D9EEF}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "capnpc-csharp.tests", "capnpc-csharp.tests\capnpc-csharp.tests.csproj", "{B77AC567-E232-4072-85C3-8689566BF3D4}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CapnpC.CSharp.Generator.Tests", "CapnpC.CSharp.Generator.Tests\CapnpC.CSharp.Generator.Tests.csproj", "{B77AC567-E232-4072-85C3-8689566BF3D4}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CapnpC.CSharp.MsBuild.Generation", "CapnpC.CSharp.MsBuild.Generation\CapnpC.CSharp.MsBuild.Generation.csproj", "{1EFC1F20-C7BB-4F44-8BF9-DBB123AACCF4}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CapnpC.CSharp.Generator", "CapnpC.CSharp.Generator\CapnpC.CSharp.Generator.csproj", "{C3A3BB49-356E-4762-A190-76D877BE18F7}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CapnpC.CSharp.MsBuild.Generation.Tests", "CapnpC.CSharp.MsBuild.Generation.Tests\CapnpC.CSharp.MsBuild.Generation.Tests.csproj", "{EF05AD68-DE31-448E-B88D-4144F928ED5D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -39,6 +45,18 @@ Global
{B77AC567-E232-4072-85C3-8689566BF3D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B77AC567-E232-4072-85C3-8689566BF3D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B77AC567-E232-4072-85C3-8689566BF3D4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1EFC1F20-C7BB-4F44-8BF9-DBB123AACCF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1EFC1F20-C7BB-4F44-8BF9-DBB123AACCF4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1EFC1F20-C7BB-4F44-8BF9-DBB123AACCF4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1EFC1F20-C7BB-4F44-8BF9-DBB123AACCF4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C3A3BB49-356E-4762-A190-76D877BE18F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C3A3BB49-356E-4762-A190-76D877BE18F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C3A3BB49-356E-4762-A190-76D877BE18F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C3A3BB49-356E-4762-A190-76D877BE18F7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EF05AD68-DE31-448E-B88D-4144F928ED5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EF05AD68-DE31-448E-B88D-4144F928ED5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EF05AD68-DE31-448E-B88D-4144F928ED5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EF05AD68-DE31-448E-B88D-4144F928ED5D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/capnpc-csharp.tests/capnpc-csharp.tests.csproj b/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj
similarity index 70%
rename from capnpc-csharp.tests/capnpc-csharp.tests.csproj
rename to CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj
index ce9a24e..0f3fa11 100644
--- a/capnpc-csharp.tests/capnpc-csharp.tests.csproj
+++ b/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj
@@ -2,9 +2,11 @@
netcoreapp2.2
- capnpc_csharp.Tests
+ CapnpC.CSharp.Generator.Tests
false
+
+ Debug;Release
@@ -16,17 +18,18 @@
-
-
-
-
+
+
+
-
+
+
+
@@ -34,9 +37,13 @@
+
+
+
+
@@ -47,11 +54,16 @@
+
+
+
+
SpecFlowSingleFileGenerator
CodeGenerator.feature.cs
+
diff --git a/CapnpC.CSharp.Generator.Tests/CapnpMessageUnitTests.cs b/CapnpC.CSharp.Generator.Tests/CapnpMessageUnitTests.cs
new file mode 100644
index 0000000..ce21560
--- /dev/null
+++ b/CapnpC.CSharp.Generator.Tests/CapnpMessageUnitTests.cs
@@ -0,0 +1,107 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CapnpC.CSharp.Generator.Tests
+{
+ [TestClass]
+ public class CapnpMessageUnitTests
+ {
+ [TestMethod]
+ public void ParseError()
+ {
+ var msg = new CapnpMessage(@"f:\code\invalid.capnp:5:1: error: Parse error.");
+ Assert.AreEqual(@"f:\code\invalid.capnp:5:1: error: Parse error.", msg.FullMessage);
+ Assert.IsTrue(msg.IsParseSuccess);
+ Assert.AreEqual(@"f:\code\invalid.capnp", msg.FileName);
+ Assert.AreEqual(5, msg.Line);
+ Assert.AreEqual(1, msg.Column);
+ Assert.AreEqual(0, msg.EndColumn);
+ Assert.AreEqual("error", msg.Category);
+ Assert.AreEqual("Parse error.", msg.MessageText);
+ }
+
+ [TestMethod]
+ public void ColumnSpan()
+ {
+ var msg = new CapnpMessage(@"f:\code\invalid.capnp:10:7-8: error: Duplicate ordinal number.");
+ Assert.IsTrue(msg.IsParseSuccess);
+ Assert.AreEqual(@"f:\code\invalid.capnp", msg.FileName);
+ Assert.AreEqual(10, msg.Line);
+ Assert.AreEqual(7, msg.Column);
+ Assert.AreEqual(8, msg.EndColumn);
+ Assert.AreEqual("error", msg.Category);
+ Assert.AreEqual("Duplicate ordinal number.", msg.MessageText);
+ }
+
+ [TestMethod]
+ public void NoSuchFile()
+ {
+ var msg = new CapnpMessage(@"C:\ProgramData\chocolatey\lib\capnproto\tools\capnproto-tools-win32-0.7.0\capnp.exe compile: doesnotexist.capnp: no such file");
+ Assert.IsFalse(msg.IsParseSuccess);
+ Assert.AreEqual(@"C:\ProgramData\chocolatey\lib\capnproto\tools\capnproto-tools-win32-0.7.0\capnp.exe compile: doesnotexist.capnp: no such file", msg.FullMessage);
+ }
+
+ [TestMethod]
+ public void NoId()
+ {
+ var msg = new CapnpMessage(@"empty.capnp:1:1: error: File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;");
+ Assert.IsTrue(msg.IsParseSuccess);
+ Assert.AreEqual("empty.capnp", msg.FileName);
+ Assert.AreEqual(1, msg.Line);
+ Assert.AreEqual(1, msg.Column);
+ Assert.AreEqual("error", msg.Category);
+ Assert.AreEqual("File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;", msg.MessageText);
+ }
+
+ [TestMethod]
+ public void AnnoyingNTFSAlternateDataStream1()
+ {
+ var msg = new CapnpMessage(@"3:2:1:1: error: File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;");
+ Assert.IsTrue(msg.IsParseSuccess);
+ Assert.AreEqual("3:2", msg.FileName);
+ Assert.AreEqual(1, msg.Line);
+ Assert.AreEqual(1, msg.Column);
+ Assert.AreEqual("error", msg.Category);
+ Assert.AreEqual("File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;", msg.MessageText);
+ }
+
+ [TestMethod]
+ public void AnnoyingNTFSAlternateDataStream2()
+ {
+ var msg = new CapnpMessage(@"c:\3:2:1:1: error: File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;");
+ Assert.IsTrue(msg.IsParseSuccess);
+ Assert.AreEqual(@"c:\3:2", msg.FileName);
+ Assert.AreEqual(1, msg.Line);
+ Assert.AreEqual(1, msg.Column);
+ Assert.AreEqual("error", msg.Category);
+ Assert.AreEqual("File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;", msg.MessageText);
+ }
+
+ [TestMethod]
+ public void AnnoyingNTFSAlternateDataStream3()
+ {
+ var msg = new CapnpMessage(@"\\?\c:\3:2:1:1: error: File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;");
+ Assert.IsTrue(msg.IsParseSuccess);
+ Assert.AreEqual(@"\\?\c:\3:2", msg.FileName);
+ Assert.AreEqual(1, msg.Line);
+ Assert.AreEqual(1, msg.Column);
+ Assert.AreEqual("error", msg.Category);
+ Assert.AreEqual("File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;", msg.MessageText);
+ }
+
+ [TestMethod]
+ public void AnnoyingNTFSAlternateDataStream4()
+ {
+ var msg = new CapnpMessage(@"1:2-3:10:7-8: error: Duplicate ordinal number.");
+ Assert.IsTrue(msg.IsParseSuccess);
+ Assert.AreEqual(@"1:2-3", msg.FileName);
+ Assert.AreEqual(10, msg.Line);
+ Assert.AreEqual(7, msg.Column);
+ Assert.AreEqual(8, msg.EndColumn);
+ Assert.AreEqual("error", msg.Category);
+ Assert.AreEqual("Duplicate ordinal number.", msg.MessageText);
+ }
+ }
+}
diff --git a/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature
new file mode 100644
index 0000000..239fd3d
--- /dev/null
+++ b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature
@@ -0,0 +1,48 @@
+Feature: CodeGenerator
+ In order to ensure that the generator backend produces valid output
+ As a contributor
+ I want to get notified when there is any deviation from reference output
+
+Scenario: Comparing backend output with reference
+ Given I have a binary code generator request "test.capnp.bin"
+ And my reference output is "test.cs"
+ When I invoke capnpc-csharp
+ Then the generated output must match the reference
+
+Scenario Outline: Invalid binary code generator requests
+ Given I have a binary code generator request
+ When I invoke capnpc-csharp
+ Then the invocation must fail
+
+Examples:
+ | bin |
+ | null.bin |
+ | test.cs |
+
+Scenario: Combining frontend and backend
+ Given capnp.exe is installed on my system
+ And I have a schema "UnitTest1.capnp"
+ When I try to generate code from that schema
+ Then code generation must succeed
+
+Scenario: Missing frontend
+ Given capnp.exe is not installed on my system
+ And I have a schema "UnitTest1.capnp"
+ When I try to generate code from that schema
+ Then the invocation must fail
+
+Scenario: Schema without ID
+ Given capnp.exe is installed on my system
+ And I have a schema "Empty1.capnp"
+ When I try to generate code from that schema
+ Then the invocation must fail
+ And the reason must be bad input
+ And the error output must contain "File does not declare an ID"
+
+Scenario: Multiple errors
+ Given capnp.exe is installed on my system
+ And I have a schema "invalid.capnp"
+ When I try to generate code from that schema
+ Then the invocation must fail
+ And the reason must be bad input
+ And the error output must contain multiple messages
diff --git a/capnpc-csharp.tests/CodeGenerator.feature.cs b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs
similarity index 57%
rename from capnpc-csharp.tests/CodeGenerator.feature.cs
rename to CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs
index 74bf043..c01b9e3 100644
--- a/capnpc-csharp.tests/CodeGenerator.feature.cs
+++ b/CapnpC.CSharp.Generator.Tests/CodeGenerator.feature.cs
@@ -10,7 +10,7 @@
// ------------------------------------------------------------------------------
#region Designer generated code
#pragma warning disable
-namespace capnpc_csharp.Tests
+namespace CapnpC.CSharp.Generator.Tests
{
using TechTalk.SpecFlow;
@@ -63,7 +63,7 @@ namespace capnpc_csharp.Tests
if (((testRunner.FeatureContext != null)
&& (testRunner.FeatureContext.FeatureInfo.Title != "CodeGenerator")))
{
- global::capnpc_csharp.Tests.CodeGeneratorFeature.FeatureSetup(null);
+ global::CapnpC.CSharp.Generator.Tests.CodeGeneratorFeature.FeatureSetup(null);
}
}
@@ -149,6 +149,98 @@ this.InvalidBinaryCodeGeneratorRequests("null.bin", ((string[])(null)));
this.InvalidBinaryCodeGeneratorRequests("test.cs", ((string[])(null)));
#line hidden
}
+
+ [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
+ [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Combining frontend and backend")]
+ [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
+ public virtual void CombiningFrontendAndBackend()
+ {
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Combining frontend and backend", null, ((string[])(null)));
+#line 22
+this.ScenarioInitialize(scenarioInfo);
+ this.ScenarioStart();
+#line 23
+ testRunner.Given("capnp.exe is installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
+#line 24
+ testRunner.And("I have a schema \"UnitTest1.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
+#line 25
+ testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
+#line 26
+ testRunner.Then("code generation must succeed", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
+#line hidden
+ this.ScenarioCleanup();
+ }
+
+ [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
+ [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Missing frontend")]
+ [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
+ public virtual void MissingFrontend()
+ {
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Missing frontend", null, ((string[])(null)));
+#line 28
+this.ScenarioInitialize(scenarioInfo);
+ this.ScenarioStart();
+#line 29
+ testRunner.Given("capnp.exe is not installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
+#line 30
+ testRunner.And("I have a schema \"UnitTest1.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
+#line 31
+ testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
+#line 32
+ testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
+#line hidden
+ this.ScenarioCleanup();
+ }
+
+ [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
+ [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Schema without ID")]
+ [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
+ public virtual void SchemaWithoutID()
+ {
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Schema without ID", null, ((string[])(null)));
+#line 34
+this.ScenarioInitialize(scenarioInfo);
+ this.ScenarioStart();
+#line 35
+ testRunner.Given("capnp.exe is installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
+#line 36
+ testRunner.And("I have a schema \"Empty1.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
+#line 37
+ testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
+#line 38
+ testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
+#line 39
+ testRunner.And("the reason must be bad input", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
+#line 40
+ testRunner.And("the error output must contain \"File does not declare an ID\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
+#line hidden
+ this.ScenarioCleanup();
+ }
+
+ [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
+ [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Multiple errors")]
+ [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
+ public virtual void MultipleErrors()
+ {
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Multiple errors", null, ((string[])(null)));
+#line 42
+this.ScenarioInitialize(scenarioInfo);
+ this.ScenarioStart();
+#line 43
+ testRunner.Given("capnp.exe is installed on my system", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
+#line 44
+ testRunner.And("I have a schema \"invalid.capnp\"", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
+#line 45
+ testRunner.When("I try to generate code from that schema", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
+#line 46
+ testRunner.Then("the invocation must fail", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
+#line 47
+ testRunner.And("the reason must be bad input", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
+#line 48
+ testRunner.And("the error output must contain multiple messages", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
+#line hidden
+ this.ScenarioCleanup();
+ }
}
}
#pragma warning restore
diff --git a/capnpc-csharp.tests/UnitTests.cs b/CapnpC.CSharp.Generator.Tests/CodeGeneratorUnitTests.cs
similarity index 92%
rename from capnpc-csharp.tests/UnitTests.cs
rename to CapnpC.CSharp.Generator.Tests/CodeGeneratorUnitTests.cs
index e2b80d5..bfec1b7 100644
--- a/capnpc-csharp.tests/UnitTests.cs
+++ b/CapnpC.CSharp.Generator.Tests/CodeGeneratorUnitTests.cs
@@ -1,13 +1,13 @@
using Capnp;
-using Model = CapnpC.Model;
-using Generator = CapnpC.Generator;
-using CodeGeneratorRequest = CapnpC.Schema.CodeGeneratorRequest;
+using Model = CapnpC.CSharp.Generator.Model;
+using CodeGen = CapnpC.CSharp.Generator.CodeGen;
+using CodeGeneratorRequest = CapnpC.CSharp.Generator.Schema.CodeGeneratorRequest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
-namespace capnpc_csharp.Tests
+namespace CapnpC.CSharp.Generator.Tests
{
[TestClass]
public class CodeGeneratorUnitTests
@@ -98,13 +98,13 @@ namespace capnpc_csharp.Tests
struct Run
{
public Model.SchemaModel Model;
- public Generator.CodeGenerator CodeGen;
+ public CodeGen.CodeGenerator CodeGen;
public Model.GenFile FirstFile;
public string Code;
}
- static Generator.CodeGenerator NewGeneratorFor(Model.SchemaModel model)
- => new Generator.CodeGenerator(model, new Generator.GeneratorOptions());
+ static CodeGen.CodeGenerator NewGeneratorFor(Model.SchemaModel model)
+ => new CodeGen.CodeGenerator(model, new CodeGen.GeneratorOptions());
Run LoadAndGenerate(string inputName, int? testNum = null)
{
diff --git a/CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty.capnp b/CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty.capnp
new file mode 100644
index 0000000..5f28270
--- /dev/null
+++ b/CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty.capnp
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty1.capnp b/CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty1.capnp
new file mode 100644
index 0000000..e02abfc
--- /dev/null
+++ b/CapnpC.CSharp.Generator.Tests/Embedded Resources/Empty1.capnp
@@ -0,0 +1 @@
+
diff --git a/capnpc-csharp.tests/No Resources/UnitTest1.capnp b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest1.capnp
similarity index 100%
rename from capnpc-csharp.tests/No Resources/UnitTest1.capnp
rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest1.capnp
diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest1.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest1.capnp.bin
similarity index 100%
rename from capnpc-csharp.tests/Embedded Resources/UnitTest1.capnp.bin
rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest1.capnp.bin
diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest10.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest10.capnp.bin
similarity index 100%
rename from capnpc-csharp.tests/Embedded Resources/UnitTest10.capnp.bin
rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest10.capnp.bin
diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest11.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest11.capnp.bin
similarity index 100%
rename from capnpc-csharp.tests/Embedded Resources/UnitTest11.capnp.bin
rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest11.capnp.bin
diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest2.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest2.capnp.bin
similarity index 100%
rename from capnpc-csharp.tests/Embedded Resources/UnitTest2.capnp.bin
rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest2.capnp.bin
diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest20.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest20.capnp.bin
similarity index 100%
rename from capnpc-csharp.tests/Embedded Resources/UnitTest20.capnp.bin
rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest20.capnp.bin
diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest3.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest3.capnp.bin
similarity index 100%
rename from capnpc-csharp.tests/Embedded Resources/UnitTest3.capnp.bin
rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest3.capnp.bin
diff --git a/capnpc-csharp.tests/Embedded Resources/UnitTest4.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest4.capnp.bin
similarity index 100%
rename from capnpc-csharp.tests/Embedded Resources/UnitTest4.capnp.bin
rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/UnitTest4.capnp.bin
diff --git a/CapnpC.CSharp.Generator.Tests/Embedded Resources/invalid.capnp b/CapnpC.CSharp.Generator.Tests/Embedded Resources/invalid.capnp
new file mode 100644
index 0000000..b56b978
--- /dev/null
+++ b/CapnpC.CSharp.Generator.Tests/Embedded Resources/invalid.capnp
@@ -0,0 +1,11 @@
+@0xa5ac546b7bf6fbbc
+
+enum Enumerant {
+ byte @0;
+ bit @1;
+}
+
+struct Foo {
+ foo @0: UInt8;
+ bar @0: UInt8;
+}
diff --git a/capnpc-csharp.tests/Embedded Resources/null.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/null.bin
similarity index 100%
rename from capnpc-csharp.tests/Embedded Resources/null.bin
rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/null.bin
diff --git a/capnpc-csharp.tests/Embedded Resources/schema-with-offsets.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/schema-with-offsets.capnp.bin
similarity index 100%
rename from capnpc-csharp.tests/Embedded Resources/schema-with-offsets.capnp.bin
rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/schema-with-offsets.capnp.bin
diff --git a/capnpc-csharp.tests/Embedded Resources/test.capnp.bin b/CapnpC.CSharp.Generator.Tests/Embedded Resources/test.capnp.bin
similarity index 100%
rename from capnpc-csharp.tests/Embedded Resources/test.capnp.bin
rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/test.capnp.bin
diff --git a/capnpc-csharp.tests/Embedded Resources/test.cs b/CapnpC.CSharp.Generator.Tests/Embedded Resources/test.cs
similarity index 100%
rename from capnpc-csharp.tests/Embedded Resources/test.cs
rename to CapnpC.CSharp.Generator.Tests/Embedded Resources/test.cs
diff --git a/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs b/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs
new file mode 100644
index 0000000..83fc17a
--- /dev/null
+++ b/CapnpC.CSharp.Generator.Tests/FeatureSteps/CodeGeneratorSteps.cs
@@ -0,0 +1,149 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using TechTalk.SpecFlow;
+
+namespace CapnpC.CSharp.Generator.Tests
+{
+ [Binding]
+ public class CodeGeneratorSteps
+ {
+ Stream _inputStream;
+ string _inputSchemaFileName;
+ string _inputSchema;
+ string _referenceOutputContent;
+
+ GenerationResult _result;
+
+ public static Stream LoadResource(string name)
+ {
+ var assembly = Assembly.GetExecutingAssembly();
+ string[] names = assembly.GetManifestResourceNames();
+ string urn = Array.Find(names, n => n.EndsWith(name, StringComparison.OrdinalIgnoreCase));
+ Assert.IsNotNull(urn, $"Test specification error: {name} does not exist");
+ return assembly.GetManifestResourceStream(urn);
+ }
+
+ internal static bool IsCapnpExeInstalled()
+ {
+ using (var process = Process.Start("where", "capnp.exe"))
+ {
+ if (process == null)
+ Assert.Fail("Unable to start 'where'");
+
+ process.WaitForExit();
+
+ return process.ExitCode == 0;
+ }
+ }
+
+ [Given(@"I have a binary code generator request ""(.*)""")]
+ [Given(@"I have a binary code generator request (.*)")]
+ public void GivenIHaveABinaryCodeGeneratorRequest(string binaryRequestFileName)
+ {
+ _inputStream = LoadResource(binaryRequestFileName);
+ }
+
+ [Given(@"my reference output is ""(.*)""")]
+ public void GivenMyReferenceOutputIs(string expectedOutputFileName)
+ {
+ using (var stream = LoadResource(expectedOutputFileName))
+ using (var reader = new StreamReader(stream))
+ {
+ _referenceOutputContent = reader.ReadToEnd();
+ }
+ }
+
+ [When(@"I invoke capnpc-csharp")]
+ public void WhenIInvokeCapnpc_Csharp()
+ {
+ using (_inputStream)
+ {
+ _result = CapnpCompilation.GenerateFromStream(_inputStream);
+ }
+ }
+
+ [Then(@"the generated output must match the reference")]
+ public void ThenTheGeneratedOutputMustMatchTheReference()
+ {
+ Assert.IsTrue(_result.IsSuccess, $"Tool invocation failed: {_result.Exception?.Message}");
+ Assert.AreEqual(_referenceOutputContent, _result.GeneratedFiles.Single().GeneratedContent);
+ }
+
+ [Then(@"the invocation must fail")]
+ public void ThenTheInvocationMustFail()
+ {
+ Assert.IsFalse(_result.IsSuccess, "Tool invocation was supposed to fail, but it didn't");
+ Assert.IsNotNull(_result.Exception, "Expected an exception");
+ }
+
+ [Given(@"capnp\.exe is installed on my system")]
+ public void GivenCapnp_ExeIsInstalledOnMySystem()
+ {
+ if (!IsCapnpExeInstalled())
+ {
+ Assert.Inconclusive("capnp.exe not found. Precondition of this test is not met.");
+ }
+ }
+
+ [Given(@"I have a schema ""(.*)""")]
+ public void GivenIHaveASchema(string capnpFileName)
+ {
+ _inputSchemaFileName = capnpFileName;
+
+ using (var stream = LoadResource(capnpFileName))
+ using (var reader = new StreamReader(stream))
+ {
+ _inputSchema = reader.ReadToEnd();
+ }
+ }
+
+ [When(@"I try to generate code from that schema")]
+ public void WhenIWantToGenerateCodeFromThatSchema()
+ {
+ string path = Path.Combine(Path.GetTempPath(), _inputSchemaFileName);
+ File.WriteAllText(path, _inputSchema);
+ _result = CapnpCompilation.InvokeCapnpAndGenerate(new string[] { path });
+ }
+
+ [Then(@"code generation must succeed")]
+ public void ThenCodeGenerationMustSucceed()
+ {
+ Assert.IsNotNull(_result, "expected generation result");
+ Assert.IsTrue(_result.IsSuccess, $"Tool invocation failed: {_result.Exception?.Message}");
+ Assert.IsTrue(_result.GeneratedFiles.Count == 1, "Expected exactly one file");
+ Assert.IsTrue(_result.GeneratedFiles[0].IsSuccess, $"Code generation failed: {_result.GeneratedFiles[0].Exception?.Message}");
+ Assert.IsFalse(string.IsNullOrEmpty(_result.GeneratedFiles[0].GeneratedContent), "Expected non-empty generated content");
+ }
+
+ [Given(@"capnp\.exe is not installed on my system")]
+ public void GivenCapnp_ExeIsNotInstalledOnMySystem()
+ {
+ if (IsCapnpExeInstalled())
+ {
+ Assert.Inconclusive("capnp.exe found. Precondition of this test is not met.");
+ }
+ }
+
+ [Then(@"the reason must be bad input")]
+ public void ThenTheReasonMustBeBadInput()
+ {
+ Assert.IsTrue(_result.ErrorCategory == CapnpProcessFailure.BadInput);
+ }
+
+ [Then(@"the error output must contain ""(.*)""")]
+ public void ThenTheErrorOutputMustContain(string p0)
+ {
+ Assert.IsTrue(_result.Messages.Any(m => m.FullMessage.Contains(p0)));
+ }
+
+ [Then(@"the error output must contain multiple messages")]
+ public void ThenTheErrorOutputMustContainMultipleMessages()
+ {
+ Assert.IsTrue(_result.Messages.Count >= 2);
+ }
+ }
+}
diff --git a/capnpc-csharp.tests/No Resources/UnitTest10.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest10.capnp
similarity index 100%
rename from capnpc-csharp.tests/No Resources/UnitTest10.capnp
rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest10.capnp
diff --git a/capnpc-csharp.tests/No Resources/UnitTest10b.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest10b.capnp
similarity index 100%
rename from capnpc-csharp.tests/No Resources/UnitTest10b.capnp
rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest10b.capnp
diff --git a/capnpc-csharp.tests/No Resources/UnitTest11.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest11.capnp
similarity index 100%
rename from capnpc-csharp.tests/No Resources/UnitTest11.capnp
rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest11.capnp
diff --git a/capnpc-csharp.tests/No Resources/UnitTest11b.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest11b.capnp
similarity index 100%
rename from capnpc-csharp.tests/No Resources/UnitTest11b.capnp
rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest11b.capnp
diff --git a/capnpc-csharp.tests/No Resources/UnitTest2.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest2.capnp
similarity index 100%
rename from capnpc-csharp.tests/No Resources/UnitTest2.capnp
rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest2.capnp
diff --git a/capnpc-csharp.tests/No Resources/UnitTest20.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest20.capnp
similarity index 100%
rename from capnpc-csharp.tests/No Resources/UnitTest20.capnp
rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest20.capnp
diff --git a/capnpc-csharp.tests/No Resources/UnitTest3.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest3.capnp
similarity index 100%
rename from capnpc-csharp.tests/No Resources/UnitTest3.capnp
rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest3.capnp
diff --git a/capnpc-csharp.tests/No Resources/UnitTest4.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest4.capnp
similarity index 100%
rename from capnpc-csharp.tests/No Resources/UnitTest4.capnp
rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest4.capnp
diff --git a/capnpc-csharp.tests/No Resources/UnitTest4b.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/UnitTest4b.capnp
similarity index 100%
rename from capnpc-csharp.tests/No Resources/UnitTest4b.capnp
rename to CapnpC.CSharp.Generator.Tests/No Resources/UnitTest4b.capnp
diff --git a/capnpc-csharp.tests/No Resources/test.capnp b/CapnpC.CSharp.Generator.Tests/No Resources/test.capnp
similarity index 100%
rename from capnpc-csharp.tests/No Resources/test.capnp
rename to CapnpC.CSharp.Generator.Tests/No Resources/test.capnp
diff --git a/CapnpC.CSharp.Generator/CapnpC.CSharp.Generator.csproj b/CapnpC.CSharp.Generator/CapnpC.CSharp.Generator.csproj
new file mode 100644
index 0000000..e752fdf
--- /dev/null
+++ b/CapnpC.CSharp.Generator/CapnpC.CSharp.Generator.csproj
@@ -0,0 +1,16 @@
+
+
+
+ netstandard2.0;netcoreapp2.1
+ Debug;Release
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CapnpC.CSharp.Generator/CapnpCompilation.cs b/CapnpC.CSharp.Generator/CapnpCompilation.cs
new file mode 100644
index 0000000..3c01261
--- /dev/null
+++ b/CapnpC.CSharp.Generator/CapnpCompilation.cs
@@ -0,0 +1,111 @@
+using Capnp;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Text.RegularExpressions;
+
+[assembly: InternalsVisibleTo("CapnpC.CSharp.Generator.Tests")]
+
+namespace CapnpC.CSharp.Generator
+{
+ ///
+ /// Provides methods for controlling both the C# code generator backend and the frontend "capnpc"
+ ///
+ public static class CapnpCompilation
+ {
+ ///
+ /// 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)
+ {
+ if (input == null)
+ throw new ArgumentNullException(nameof(input));
+
+ try
+ {
+ var segments = Framing.ReadSegments(input);
+ var dec = DeserializerState.CreateRoot(segments);
+ var reader = Schema.CodeGeneratorRequest.Reader.Create(dec);
+ var model = Model.SchemaModel.Create(reader);
+ var codeGen = new CodeGen.CodeGenerator(model, new CodeGen.GeneratorOptions());
+ return new GenerationResult(codeGen.Generate());
+ }
+ catch (Exception exception)
+ {
+ return new GenerationResult(exception);
+ }
+ }
+
+ ///
+ /// Invokes "capnp.exe -o-" with given additional arguments and redirects the output to the C# generator backend.
+ ///
+ /// additional command line arguments
+ /// optional working directory
+ /// generation result
+ /// is null
+ public static GenerationResult InvokeCapnpAndGenerate(IEnumerable arguments, string workingDirectory = null)
+ {
+ if (arguments == null)
+ throw new ArgumentNullException(nameof(arguments));
+
+ using (var compiler = new Process())
+ {
+ var argList = new List();
+ argList.Add("compile");
+ argList.Add($"-o-");
+ argList.AddRange(arguments);
+
+ compiler.StartInfo.FileName = "capnp.exe";
+ compiler.StartInfo.Arguments = string.Join(" ", argList);
+ compiler.StartInfo.UseShellExecute = false;
+ compiler.StartInfo.RedirectStandardOutput = true;
+ compiler.StartInfo.RedirectStandardError = true;
+ if (!string.IsNullOrWhiteSpace(workingDirectory))
+ {
+ compiler.StartInfo.WorkingDirectory = workingDirectory;
+ }
+
+ try
+ {
+ compiler.Start();
+ }
+ catch (Exception exception)
+ {
+ return new GenerationResult(exception)
+ {
+ ErrorCategory = CapnpProcessFailure.NotFound
+ };
+ }
+
+ var result = GenerateFromStream(compiler.StandardOutput.BaseStream);
+
+ var messageList = new List();
+
+ while (!compiler.StandardError.EndOfStream)
+ {
+ messageList.Add(new CapnpMessage(compiler.StandardError.ReadLine()));
+ }
+
+ result.Messages = messageList;
+
+ if (!result.IsSuccess)
+ {
+ compiler.WaitForExit();
+ int exitCode = compiler.ExitCode;
+
+ if (exitCode == 0)
+ result.ErrorCategory = CapnpProcessFailure.BadOutput;
+ else
+ result.ErrorCategory = CapnpProcessFailure.BadInput;
+ }
+
+ return result;
+ }
+ }
+ }
+}
diff --git a/CapnpC.CSharp.Generator/CapnpMessage.cs b/CapnpC.CSharp.Generator/CapnpMessage.cs
new file mode 100644
index 0000000..0cc60b8
--- /dev/null
+++ b/CapnpC.CSharp.Generator/CapnpMessage.cs
@@ -0,0 +1,116 @@
+using System.Runtime.CompilerServices;
+using System.Text.RegularExpressions;
+
+[assembly: InternalsVisibleTo("CapnpC.CSharp.Generator.Tests")]
+
+namespace CapnpC.CSharp.Generator
+{
+ ///
+ /// Represents a capnp.exe output message
+ ///
+ public class CapnpMessage
+ {
+ // capnp outputs look like this:
+ // empty.capnp:1:1: error: File does not declare an ID. I've generated one for you. Add this line to your file: @0xc82955a0c779197d;
+ // f:\code\invalid.capnp:9:7-8: error: Ordinal @0 originally used here.
+ // Parsing them is harder than it seems because the colon may be part of the file name (as in the example above).
+ // And it becomes even worse! NTFS has a rarely used feature called "alternate data streams", identified by a colon:
+ // f:\code\somefile:stream.capnp:9:7-8: error: Ordinal @0 originally used here.
+ // What about a name which looks like a line number? (Hint: the 10 denotes the alternate data stream)
+ // f:\code\somefile:10:9:7-8: error: Ordinal @0 originally used here.
+ // Watching for the *last* colon as message separator does not work either, either. See first example.
+ // Strategy: Watch out for the *last* occurence of pattern :[line]:[column]
+
+ static readonly Regex LineColumnRegex = new Regex(@":(?\d+):(?\d+)(-(?\d+))?:", RegexOptions.Compiled | RegexOptions.RightToLeft);
+
+ ///
+ /// Constructs an instance from given message
+ ///
+ /// output message (one line)
+ public CapnpMessage(string fullMessage)
+ {
+ FullMessage = fullMessage;
+
+ var match = LineColumnRegex.Match(fullMessage);
+
+ if (match.Success)
+ {
+ IsParseSuccess = true;
+ FileName = fullMessage.Substring(0, match.Index);
+ var lineMatch = match.Groups["Line"];
+ if (lineMatch.Success)
+ {
+ int.TryParse(lineMatch.Value, out int value);
+ Line = value;
+ }
+ var columnMatch = match.Groups["Column"];
+ if (columnMatch.Success)
+ {
+ int.TryParse(columnMatch.Value, out int value);
+ Column = value;
+ }
+ var endColumnMatch = match.Groups["EndColumn"];
+ if (endColumnMatch.Success)
+ {
+ int.TryParse(endColumnMatch.Value, out int value);
+ EndColumn = value;
+ }
+
+ int restIndex = match.Index + match.Length;
+ int bodyIndex = fullMessage.IndexOf(':', restIndex);
+
+ if (bodyIndex >= 0)
+ {
+ Category = fullMessage.Substring(restIndex, bodyIndex - restIndex).Trim();
+ MessageText = fullMessage.Substring(bodyIndex + 1).Trim();
+ }
+ else
+ {
+ // Never observed "in the wild", just in case...
+ Category = string.Empty;
+ MessageText = fullMessage.Substring(restIndex).Trim();
+ }
+ }
+ }
+
+ ///
+ /// The original message
+ ///
+ public string FullMessage { get; }
+
+ ///
+ /// Whether the message could be decompsed into [filename]:[line]:[column]: [category]: [text]
+ ///
+ public bool IsParseSuccess { get; }
+
+ ///
+ /// Parsed file name (null iff not IsParseSuccess)
+ ///
+ public string FileName { get; }
+
+ ///
+ /// Parsed line (0 if not IsParseSuccess)
+ ///
+ public int Line { get; }
+
+ ///
+ /// Parsed column (0 if not IsParseSuccess)
+ ///
+ public int Column { get; }
+
+ ///
+ /// Parsed end column (0 if there is none)
+ ///
+ public int EndColumn { get; }
+
+ ///
+ /// Parsed category (e.g. "error", null iff not IsParseSuccess)
+ ///
+ public string Category { get; }
+
+ ///
+ /// Parsed message body text (0 if not IsParseSuccess)
+ ///
+ public string MessageText { get; }
+ }
+}
diff --git a/CapnpC.CSharp.Generator/CapnpProcessFailure.cs b/CapnpC.CSharp.Generator/CapnpProcessFailure.cs
new file mode 100644
index 0000000..1d51c0f
--- /dev/null
+++ b/CapnpC.CSharp.Generator/CapnpProcessFailure.cs
@@ -0,0 +1,23 @@
+namespace CapnpC.CSharp.Generator
+{
+ ///
+ /// Why did invocation of capnpc.exe fail?
+ ///
+ public enum CapnpProcessFailure
+ {
+ ///
+ /// Because capnpc.exe was not found. It is probably not installed.
+ ///
+ NotFound,
+
+ ///
+ /// Because it exited with an error. Probably invalid .capnp file input.
+ ///
+ BadInput,
+
+ ///
+ /// Because it produced an apparently bad code generation request.
+ ///
+ BadOutput
+ }
+}
diff --git a/capnpc-csharp/Generator/CodeGenerator.cs b/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs
similarity index 91%
rename from capnpc-csharp/Generator/CodeGenerator.cs
rename to CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs
index e401b3a..d873108 100644
--- a/capnpc-csharp/Generator/CodeGenerator.cs
+++ b/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs
@@ -1,18 +1,17 @@
-namespace CapnpC.Generator
+namespace CapnpC.CSharp.Generator.CodeGen
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
- using System.Text;
- using CapnpC.Model;
+ using CapnpC.CSharp.Generator.Model;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using static SyntaxHelpers;
- class CodeGenerator
+ internal class CodeGenerator
{
readonly SchemaModel _model;
readonly GenNames _names;
@@ -169,14 +168,23 @@
return cu.NormalizeWhitespace().ToFullString();
}
- public void Generate()
+ public IReadOnlyList Generate()
{
+ var result = new List();
+
foreach (var file in _model.FilesToGenerate)
{
- string content = Transform(file);
- string path = Path.ChangeExtension(file.Name, ".cs");
- File.WriteAllText(path, content);
+ try
+ {
+ result.Add(new FileGenerationResult(file.Name, Transform(file)));
+ }
+ catch (System.Exception exception)
+ {
+ result.Add(new FileGenerationResult(file.Name, exception));
+ }
}
+
+ return result;
}
}
}
diff --git a/capnpc-csharp/Generator/CommonSnippetGen.cs b/CapnpC.CSharp.Generator/CodeGen/CommonSnippetGen.cs
similarity index 94%
rename from capnpc-csharp/Generator/CommonSnippetGen.cs
rename to CapnpC.CSharp.Generator/CodeGen/CommonSnippetGen.cs
index 2e1797d..d89b873 100644
--- a/capnpc-csharp/Generator/CommonSnippetGen.cs
+++ b/CapnpC.CSharp.Generator/CodeGen/CommonSnippetGen.cs
@@ -1,15 +1,13 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using CapnpC.Model;
+using CapnpC.CSharp.Generator.Model;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-using static CapnpC.Generator.SyntaxHelpers;
+using static CapnpC.CSharp.Generator.CodeGen.SyntaxHelpers;
-namespace CapnpC.Generator
+namespace CapnpC.CSharp.Generator.CodeGen
{
class CommonSnippetGen
{
diff --git a/capnpc-csharp/Generator/DomainClassSnippetGen.cs b/CapnpC.CSharp.Generator/CodeGen/DomainClassSnippetGen.cs
similarity index 99%
rename from capnpc-csharp/Generator/DomainClassSnippetGen.cs
rename to CapnpC.CSharp.Generator/CodeGen/DomainClassSnippetGen.cs
index 5b27495..fb41086 100644
--- a/capnpc-csharp/Generator/DomainClassSnippetGen.cs
+++ b/CapnpC.CSharp.Generator/CodeGen/DomainClassSnippetGen.cs
@@ -1,15 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using CapnpC.Model;
-using Microsoft.CodeAnalysis;
+using CapnpC.CSharp.Generator.Model;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-using static CapnpC.Generator.SyntaxHelpers;
+using static CapnpC.CSharp.Generator.CodeGen.SyntaxHelpers;
-namespace CapnpC.Generator
+namespace CapnpC.CSharp.Generator.CodeGen
{
class DomainClassSnippetGen
{
diff --git a/capnpc-csharp/Generator/GenNames.cs b/CapnpC.CSharp.Generator/CodeGen/GenNames.cs
similarity index 99%
rename from capnpc-csharp/Generator/GenNames.cs
rename to CapnpC.CSharp.Generator/CodeGen/GenNames.cs
index f842413..b9282ab 100644
--- a/capnpc-csharp/Generator/GenNames.cs
+++ b/CapnpC.CSharp.Generator/CodeGen/GenNames.cs
@@ -1,13 +1,12 @@
-using CapnpC.Model;
+using CapnpC.CSharp.Generator.Model;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-namespace CapnpC.Generator
+namespace CapnpC.CSharp.Generator.CodeGen
{
enum NameUsage
{
diff --git a/capnpc-csharp/Generator/GeneratorOptions.cs b/CapnpC.CSharp.Generator/CodeGen/GeneratorOptions.cs
similarity index 95%
rename from capnpc-csharp/Generator/GeneratorOptions.cs
rename to CapnpC.CSharp.Generator/CodeGen/GeneratorOptions.cs
index 76faf93..e534f2b 100644
--- a/capnpc-csharp/Generator/GeneratorOptions.cs
+++ b/CapnpC.CSharp.Generator/CodeGen/GeneratorOptions.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace CapnpC.Generator
+namespace CapnpC.CSharp.Generator.CodeGen
{
class GeneratorOptions
{
diff --git a/capnpc-csharp/Generator/InterfaceSnippetGen.cs b/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs
similarity index 99%
rename from capnpc-csharp/Generator/InterfaceSnippetGen.cs
rename to CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs
index f0adfaa..11d6d36 100644
--- a/capnpc-csharp/Generator/InterfaceSnippetGen.cs
+++ b/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs
@@ -1,16 +1,15 @@
-using CapnpC.Model;
+using CapnpC.CSharp.Generator.Model;
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-using static CapnpC.Generator.SyntaxHelpers;
+using static CapnpC.CSharp.Generator.CodeGen.SyntaxHelpers;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Threading.Tasks;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp;
-namespace CapnpC.Generator
+namespace CapnpC.CSharp.Generator.CodeGen
{
class InterfaceSnippetGen
{
diff --git a/capnpc-csharp/Generator/Name.cs b/CapnpC.CSharp.Generator/CodeGen/Name.cs
similarity index 92%
rename from capnpc-csharp/Generator/Name.cs
rename to CapnpC.CSharp.Generator/CodeGen/Name.cs
index f85f324..5b8e877 100644
--- a/capnpc-csharp/Generator/Name.cs
+++ b/CapnpC.CSharp.Generator/CodeGen/Name.cs
@@ -2,10 +2,8 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
-using System.Collections.Generic;
-using System.Text;
-namespace CapnpC.Generator
+namespace CapnpC.CSharp.Generator.CodeGen
{
class Name
{
diff --git a/capnpc-csharp/Generator/ReaderSnippetGen.cs b/CapnpC.CSharp.Generator/CodeGen/ReaderSnippetGen.cs
similarity index 99%
rename from capnpc-csharp/Generator/ReaderSnippetGen.cs
rename to CapnpC.CSharp.Generator/CodeGen/ReaderSnippetGen.cs
index 9d57038..869acf1 100644
--- a/capnpc-csharp/Generator/ReaderSnippetGen.cs
+++ b/CapnpC.CSharp.Generator/CodeGen/ReaderSnippetGen.cs
@@ -1,15 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using CapnpC.Model;
-using Microsoft.CodeAnalysis;
+using CapnpC.CSharp.Generator.Model;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-using static CapnpC.Generator.SyntaxHelpers;
+using static CapnpC.CSharp.Generator.CodeGen.SyntaxHelpers;
-namespace CapnpC.Generator
+namespace CapnpC.CSharp.Generator.CodeGen
{
class ReaderSnippetGen
{
diff --git a/capnpc-csharp/Generator/SerializerStateWorder.cs b/CapnpC.CSharp.Generator/CodeGen/SerializerStateWorder.cs
similarity index 75%
rename from capnpc-csharp/Generator/SerializerStateWorder.cs
rename to CapnpC.CSharp.Generator/CodeGen/SerializerStateWorder.cs
index 8f64689..29cb72a 100644
--- a/capnpc-csharp/Generator/SerializerStateWorder.cs
+++ b/CapnpC.CSharp.Generator/CodeGen/SerializerStateWorder.cs
@@ -1,8 +1,6 @@
using Capnp;
-using System.Collections.Generic;
-using System.Text;
-namespace CapnpC.Generator
+namespace CapnpC.CSharp.Generator.CodeGen
{
class SerializerStateWorder: SerializerState
{
diff --git a/capnpc-csharp/Generator/SkeletonWorder.cs b/CapnpC.CSharp.Generator/CodeGen/SkeletonWorder.cs
similarity index 88%
rename from capnpc-csharp/Generator/SkeletonWorder.cs
rename to CapnpC.CSharp.Generator/CodeGen/SkeletonWorder.cs
index 0d34191..703ee3b 100644
--- a/capnpc-csharp/Generator/SkeletonWorder.cs
+++ b/CapnpC.CSharp.Generator/CodeGen/SkeletonWorder.cs
@@ -1,6 +1,6 @@
using System;
-namespace CapnpC.Generator
+namespace CapnpC.CSharp.Generator.CodeGen
{
class SkeletonWorder : Capnp.Rpc.Skeleton