support emitting a #nullable directive

This commit is contained in:
Christian Köllner 2020-02-08 17:23:07 +01:00
parent fd7ada499f
commit fc1735ab67
15 changed files with 639 additions and 519 deletions

View File

@ -372,7 +372,7 @@ namespace Capnp.Rpc
} }
IProvidedCapability? cap; IProvidedCapability? cap;
PendingAnswer? pendingAnswer = null; PendingAnswer pendingAnswer;
bool releaseParamCaps = false; bool releaseParamCaps = false;
void AwaitAnswerAndReply() void AwaitAnswerAndReply()

View File

@ -55,15 +55,19 @@ Scenario Outline: Valid generator output
Then the invocation must succeed and attempting to compile the generated code gives <outcome> Then the invocation must succeed and attempting to compile the generated code gives <outcome>
Examples: Examples:
| bin | nullablegen | nullablesupp | outcome | | bin | nullablegen | nullablesupp | outcome |
| test.capnp.bin | false | false | success | | test.capnp.bin | false | false | success |
| test.capnp.bin | true | false | success | | test.capnp.bin | true | false | errors |
| test.capnp.bin | false | true | warnings | | test.capnp.bin | false | true | warnings |
| test.capnp.bin | true | true | success | | test.capnp.bin | true | true | success |
| Issue19.capnp.bin | false | false | success | | Issue19.capnp.bin | false | false | success |
| Issue21.capnp.bin | false | false | success | | Issue21.capnp.bin | false | false | success |
| Issue22.capnp.bin | false | false | success | | Issue22.capnp.bin | false | false | success |
| NullableDisable.capnp.bin | true | false | success | | NullableDisable.capnp.bin | true | false | success |
| NullableDisable.capnp.bin | true | true | warnings | | NullableDisable.capnp.bin | true | true | warnings |
| NullableEnable.capnp.bin | false | true | success | | NullableEnable.capnp.bin | false | true | success |
| NullableEnable.capnp.bin | false | false | errors | | NullableEnable.capnp.bin | false | false | errors |
| NullableDisable2.capnp.bin | false | false | errors |
| NullableDisable2.capnp.bin | false | true | success |
| NullableEnable2.capnp.bin | false | false | errors |
| NullableEnable2.capnp.bin | false | true | success |

View File

@ -447,11 +447,11 @@ this.ValidGeneratorOutput("test.capnp.bin", "false", "false", "success", ((strin
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "test.capnp.bin")] [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "test.capnp.bin")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "true")] [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablegen", "true")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")] [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:nullablesupp", "false")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "success")] [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:outcome", "errors")]
public virtual void ValidGeneratorOutput_Variant1() public virtual void ValidGeneratorOutput_Variant1()
{ {
#line 50 #line 50
this.ValidGeneratorOutput("test.capnp.bin", "true", "false", "success", ((string[])(null))); this.ValidGeneratorOutput("test.capnp.bin", "true", "false", "errors", ((string[])(null)));
#line hidden #line hidden
} }
@ -587,6 +587,66 @@ this.ValidGeneratorOutput("NullableEnable.capnp.bin", "false", "true", "success"
{ {
#line 50 #line 50
this.ValidGeneratorOutput("NullableEnable.capnp.bin", "false", "false", "errors", ((string[])(null))); this.ValidGeneratorOutput("NullableEnable.capnp.bin", "false", "false", "errors", ((string[])(null)));
#line hidden
}
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 11")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 11")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableDisable2.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_Variant11()
{
#line 50
this.ValidGeneratorOutput("NullableDisable2.capnp.bin", "false", "false", "errors", ((string[])(null)));
#line hidden
}
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 12")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 12")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableDisable2.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_Variant12()
{
#line 50
this.ValidGeneratorOutput("NullableDisable2.capnp.bin", "false", "true", "success", ((string[])(null)));
#line hidden
}
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 13")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 13")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableEnable2.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_Variant13()
{
#line 50
this.ValidGeneratorOutput("NullableEnable2.capnp.bin", "false", "false", "errors", ((string[])(null)));
#line hidden
}
[Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()]
[Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("Valid generator output: Variant 14")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "CodeGenerator")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("VariantName", "Variant 14")]
[Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("Parameter:bin", "NullableEnable2.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_Variant14()
{
#line 50
this.ValidGeneratorOutput("NullableEnable2.capnp.bin", "false", "true", "success", ((string[])(null)));
#line hidden #line hidden
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
@0xbbfd48ae4b99d016;
using CSharp = import "/csharp.capnp";
$CSharp.nullableEnable(false);
$CSharp.emitNullableDirective(true);
struct SomeStruct {
strings @0 : List(Text);
}

View File

@ -0,0 +1,10 @@
@0xbbfd48ae4b99d016;
using CSharp = import "/csharp.capnp";
$CSharp.nullableEnable(true);
$CSharp.emitNullableDirective(true);
struct SomeStruct {
strings @0 : List(Text);
}

View File

@ -34,6 +34,10 @@ namespace CapnpC.CSharp.Generator.Tests.Util
"netcoreapp3.0", "netcoreapp3.0",
"Capnp.Net.Runtime.dll")); "Capnp.Net.Runtime.dll"));
var parseOptions = CSharpParseOptions.Default;
if (nullableContextOptions == NullableContextOptions.Disable)
parseOptions = parseOptions.WithLanguageVersion(LanguageVersion.CSharp7_1);
var compilation = CSharpCompilation.Create( var compilation = CSharpCompilation.Create(
"CompilationTestAssembly", "CompilationTestAssembly",
options: options, options: options,
@ -44,7 +48,7 @@ namespace CapnpC.CSharp.Generator.Tests.Util
MetadataReference.CreateFromFile(Path.Combine(assemblyRoot, "System.Runtime.dll")), MetadataReference.CreateFromFile(Path.Combine(assemblyRoot, "System.Runtime.dll")),
MetadataReference.CreateFromFile(Path.Combine(assemblyRoot, "System.Private.CoreLib.dll")), MetadataReference.CreateFromFile(Path.Combine(assemblyRoot, "System.Private.CoreLib.dll")),
MetadataReference.CreateFromFile(capnpRuntimePath) }, MetadataReference.CreateFromFile(capnpRuntimePath) },
syntaxTrees: Array.ConvertAll(code, new Converter<string, SyntaxTree>(c => CSharpSyntaxTree.ParseText(c)))); syntaxTrees: Array.ConvertAll(code, new Converter<string, SyntaxTree>(c => CSharpSyntaxTree.ParseText(c, parseOptions))));
using (var stream = new MemoryStream()) using (var stream = new MemoryStream())
{ {

View File

@ -191,6 +191,20 @@
NameSyntax topNamespace = GenNames.NamespaceName(file.Namespace) ?? _names.TopNamespace; NameSyntax topNamespace = GenNames.NamespaceName(file.Namespace) ?? _names.TopNamespace;
var ns = NamespaceDeclaration(topNamespace); var ns = NamespaceDeclaration(topNamespace);
if (file.EmitNullableDirective)
{
ns = ns.WithLeadingTrivia(
Trivia(
NullableDirectiveTrivia(
Token(_names.NullableEnable ? SyntaxKind.EnableKeyword : SyntaxKind.DisableKeyword),
true)))
.WithTrailingTrivia(
Trivia(
NullableDirectiveTrivia(
Token(SyntaxKind.RestoreKeyword),
true)));
}
foreach (var def in file.NestedTypes) foreach (var def in file.NestedTypes)
{ {

View File

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

View File

@ -93,6 +93,7 @@ namespace CapnpC.CSharp.Generator.Model
file.Namespace = GetNamespaceAnnotation(node); file.Namespace = GetNamespaceAnnotation(node);
file.Name = name; file.Name = name;
file.NullableEnable = GetNullableEnable(node); file.NullableEnable = GetNullableEnable(node);
file.EmitNullableDirective = GetEmitNullableDirective(node) ?? false;
return ProcessNodePass1(id, name, state) as GenFile; return ProcessNodePass1(id, name, state) as GenFile;
} }

View File

@ -18,6 +18,7 @@ namespace CapnpC.CSharp.Generator.Model
public const ulong Namespace = 0xeb0d831668c6eda0; public const ulong Namespace = 0xeb0d831668c6eda0;
public const ulong NullableEnable = 0xeb0d831668c6eda1; public const ulong NullableEnable = 0xeb0d831668c6eda1;
public const ulong Name = 0xeb0d831668c6eda2; public const ulong Name = 0xeb0d831668c6eda2;
public const ulong EmitNullableDirective = 0xeb0d831668c6eda3;
} }
} }
@ -85,5 +86,17 @@ namespace CapnpC.CSharp.Generator.Model
} }
return null; return null;
} }
public static bool? GetEmitNullableDirective(Schema.Node.Reader node)
{
foreach (var annotation in node.Annotations)
{
if (annotation.Id == AnnotationIds.Cs.EmitNullableDirective && annotation.Value.IsBool)
{
return annotation.Value.Bool;
}
}
return null;
}
} }
} }

View File

@ -9,7 +9,7 @@ namespace MsBuildGenerationTest
// Instantiate some generated classes ensures that they are really present. // Instantiate some generated classes ensures that they are really present.
// Note that this code is not supposed to test runtime behavior, we have plenty of other test cases for that purpose. // Note that this code is not supposed to test runtime behavior, we have plenty of other test cases for that purpose.
void use(object x) void use(object y)
{ {
} }

View File

@ -7,5 +7,8 @@ annotation namespace @0xeb0d831668c6eda0 (file) : Text;
annotation nullableEnable @0xeb0d831668c6eda1 (file) : Bool; annotation nullableEnable @0xeb0d831668c6eda1 (file) : Bool;
# Whether to generate C# nullable reference types # Whether to generate C# nullable reference types
annotation emitNullableDirective @0xeb0d831668c6eda3 (file) : Bool;
# Whether to surround the generated with with #nullable enable/disable ... #nullable restore
annotation name @0xeb0d831668c6eda2 (field, enumerant, struct, enum, interface, method, param, group, union) : Text; annotation name @0xeb0d831668c6eda2 (field, enumerant, struct, enum, interface, method, param, group, union) : Text;
# C# member name for code generation # C# member name for code generation