This commit is contained in:
Christian Köllner 2020-01-19 14:35:43 +01:00
parent 5b8f6722ec
commit 4da57f9a28
12 changed files with 147 additions and 97 deletions

View File

@ -10,8 +10,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.3.1" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.4.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.3.1" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.4.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="Mono.Cecil" Version="0.11.0" /> <PackageReference Include="Mono.Cecil" Version="0.11.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> <PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />

View File

@ -61,7 +61,7 @@
{ {
var topDecl = ClassDeclaration(_names.MakeTypeName(def).Identifier) var topDecl = ClassDeclaration(_names.MakeTypeName(def).Identifier)
.AddModifiers(Public) .AddModifiers(Public)
.AddBaseListTypes(SimpleBaseType(Type<Capnp.ICapnpSerializable>())); .AddBaseListTypes(SimpleBaseType(_names.Type<Capnp.ICapnpSerializable>(true)));
if (def.GenericParameters.Count > 0) if (def.GenericParameters.Count > 0)
{ {

View File

@ -22,7 +22,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
{ {
var whichEnum = EnumDeclaration(_names.UnionDiscriminatorEnum.ToString()) var whichEnum = EnumDeclaration(_names.UnionDiscriminatorEnum.ToString())
.AddModifiers(Public) .AddModifiers(Public)
.AddBaseListTypes(SimpleBaseType(Type<ushort>())); .AddBaseListTypes(SimpleBaseType(_names.Type<ushort>()));
var discFields = def.Fields.Where(f => f.DiscValue.HasValue); var discFields = def.Fields.Where(f => f.DiscValue.HasValue);
@ -52,7 +52,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
var decl = EnumDeclaration(def.Name) var decl = EnumDeclaration(def.Name)
.WithAttributeLists(MakeTypeIdAttributeLists(def.Id)) .WithAttributeLists(MakeTypeIdAttributeLists(def.Id))
.AddModifiers(Public) .AddModifiers(Public)
.AddBaseListTypes(SimpleBaseType(Type<ushort>())); .AddBaseListTypes(SimpleBaseType(_names.Type<ushort>()));
foreach (var enumerant in def.Enumerants.OrderBy(e => e.CodeOrder)) foreach (var enumerant in def.Enumerants.OrderBy(e => e.CodeOrder))
{ {

View File

@ -75,7 +75,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
return null; return null;
} }
var prop = PropertyDeclaration(_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.DomainClass), var prop = PropertyDeclaration(_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.DomainClassNullable),
_names.GetCodeIdentifier(field).Identifier) _names.GetCodeIdentifier(field).Identifier)
.AddModifiers(Public).AddAccessorListAccessors( .AddModifiers(Public).AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
@ -111,7 +111,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
MemberDeclarationSyntax MakeUnionContentField() MemberDeclarationSyntax MakeUnionContentField()
{ {
return FieldDeclaration( return FieldDeclaration(
VariableDeclaration(SyntaxHelpers.Type<object>()) VariableDeclaration(_names.Type<object>())
.WithVariables( .WithVariables(
SingletonSeparatedList<VariableDeclaratorSyntax>( SingletonSeparatedList<VariableDeclaratorSyntax>(
VariableDeclarator(_names.UnionContentField.Identifier)))) VariableDeclarator(_names.UnionContentField.Identifier))))
@ -282,7 +282,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
value.Decode(); value.Decode();
return ArrayCreationExpression(ArrayType( return ArrayCreationExpression(ArrayType(
_names.MakeTypeSyntax(value.Type.ElementType, scope, TypeUsage.DomainClass)) _names.MakeTypeSyntax(value.Type.ElementType, scope, TypeUsage.DomainClassNullable))
.WithRankSpecifiers( .WithRankSpecifiers(
SingletonList<ArrayRankSpecifierSyntax>( SingletonList<ArrayRankSpecifierSyntax>(
ArrayRankSpecifier( ArrayRankSpecifier(
@ -611,7 +611,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.SimpleMemberAccessExpression,
IdentifierName(nameof(Capnp.CapnpSerializable)), IdentifierName(nameof(Capnp.CapnpSerializable)),
GenericName(nameof(Capnp.CapnpSerializable.Create)) GenericName(nameof(Capnp.CapnpSerializable.Create))
.AddTypeArgumentListArguments(elementType))) .AddTypeArgumentListArguments(MakeNonNullableType(elementType))))
.AddArgumentListArguments(Argument(IdentifierName("_")))))); .AddArgumentListArguments(Argument(IdentifierName("_"))))));
} }
@ -645,7 +645,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
.AddArgumentListArguments(Argument( .AddArgumentListArguments(Argument(
SimpleLambdaExpression( SimpleLambdaExpression(
Parameter(Identifier("_")), Parameter(Identifier("_")),
CastExpression(Type<object>(), IdentifierName("_"))))); CastExpression(_names.Type<object>(), IdentifierName("_")))));
} }
ExpressionSyntax MakeDeserializeMethodRightHandSide(Field field) ExpressionSyntax MakeDeserializeMethodRightHandSide(Field field)
@ -662,10 +662,10 @@ namespace CapnpC.CSharp.Generator.CodeGen
IdentifierName(nameof(Capnp.CapnpSerializable)), IdentifierName(nameof(Capnp.CapnpSerializable)),
GenericName(nameof(Capnp.CapnpSerializable.Create)) GenericName(nameof(Capnp.CapnpSerializable.Create))
.AddTypeArgumentListArguments( .AddTypeArgumentListArguments(
_names.MakeTypeSyntax( MakeNonNullableType(_names.MakeTypeSyntax(
field.Type, field.Type,
field.DeclaringType, field.DeclaringType,
TypeUsage.DomainClass)))) TypeUsage.DomainClass)))))
.AddArgumentListArguments(Argument(MemberAccessExpression( .AddArgumentListArguments(Argument(MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.SimpleMemberAccessExpression,
_names.ReaderParameter.IdentifierName, _names.ReaderParameter.IdentifierName,
@ -684,7 +684,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.SimpleMemberAccessExpression,
_names.ReaderParameter.IdentifierName, _names.ReaderParameter.IdentifierName,
_names.GetCodeIdentifier(field).IdentifierName), _names.GetCodeIdentifier(field).IdentifierName),
_names.MakeTypeSyntax(elementType, field.DeclaringType, TypeUsage.DomainClass), _names.MakeTypeSyntax(elementType, field.DeclaringType, TypeUsage.DomainClassNullable),
rank); rank);
case TypeTag.ListPointer: case TypeTag.ListPointer:
@ -849,7 +849,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
ExplicitInterfaceSpecifier(IdentifierName(nameof(Capnp.ICapnpSerializable)))) ExplicitInterfaceSpecifier(IdentifierName(nameof(Capnp.ICapnpSerializable))))
.AddParameterListParameters( .AddParameterListParameters(
Parameter(_names.AnonymousParameter.Identifier) Parameter(_names.AnonymousParameter.Identifier)
.WithType(Type<Capnp.SerializerState>())) .WithType(_names.Type<Capnp.SerializerState>(true)))
.AddBodyStatements( .AddBodyStatements(
ExpressionStatement( ExpressionStatement(
InvocationExpression(_names.SerializeMethod.IdentifierName) InvocationExpression(_names.SerializeMethod.IdentifierName)
@ -933,7 +933,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
ExplicitInterfaceSpecifier(IdentifierName(nameof(Capnp.ICapnpSerializable)))) ExplicitInterfaceSpecifier(IdentifierName(nameof(Capnp.ICapnpSerializable))))
.AddParameterListParameters( .AddParameterListParameters(
Parameter(_names.AnonymousParameter.Identifier) Parameter(_names.AnonymousParameter.Identifier)
.WithType(Type<Capnp.DeserializerState>())) .WithType(_names.Type<Capnp.DeserializerState>()))
.AddBodyStatements(stmts.ToArray()); .AddBodyStatements(stmts.ToArray());
} }

View File

@ -66,6 +66,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
public string PipeliningExtensionsClassFormat { get; } public string PipeliningExtensionsClassFormat { get; }
public string ProxyClassFormat { get; } public string ProxyClassFormat { get; }
public string SkeletonClassFormat { get; } public string SkeletonClassFormat { get; }
public bool NullableEnable { get; set; }
public GenNames(GeneratorOptions options) public GenNames(GeneratorOptions options)
{ {
TopNamespace = new Name(options.TopNamespaceName).IdentifierName; TopNamespace = new Name(options.TopNamespaceName).IdentifierName;
@ -288,14 +289,14 @@ namespace CapnpC.CSharp.Generator.CodeGen
case TypeTag.AnyPointer: case TypeTag.AnyPointer:
case TypeTag.StructPointer: case TypeTag.StructPointer:
case TypeTag.ListPointer: case TypeTag.ListPointer:
return SyntaxHelpers.Type<Capnp.ListOfPointersSerializer<Capnp.DynamicSerializerState>>(); return Type<Capnp.ListOfPointersSerializer<Capnp.DynamicSerializerState>>(true);
case TypeTag.CapabilityPointer: case TypeTag.CapabilityPointer:
return SyntaxHelpers.Type<Capnp.ListOfCapsSerializer<Capnp.Rpc.BareProxy>>(); return Type<Capnp.ListOfCapsSerializer<Capnp.Rpc.BareProxy>>(true);
case TypeTag.Data: case TypeTag.Data:
return SyntaxHelpers.Type<Capnp.ListOfPointersSerializer< return Type<Capnp.ListOfPointersSerializer<
Capnp.ListOfPrimitivesSerializer<byte>>>(); Capnp.ListOfPrimitivesSerializer<byte>>>(true);
case TypeTag.Enum: case TypeTag.Enum:
return GenericName("ListOfPrimitivesSerializer") return GenericName("ListOfPrimitivesSerializer")
@ -315,44 +316,44 @@ namespace CapnpC.CSharp.Generator.CodeGen
.AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer)); .AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer));
case TypeTag.Text: case TypeTag.Text:
return SyntaxHelpers.Type<Capnp.ListOfTextSerializer>(); return Type<Capnp.ListOfTextSerializer>(true);
case TypeTag.Void: case TypeTag.Void:
return SyntaxHelpers.Type<Capnp.ListOfEmptySerializer>(); return Type<Capnp.ListOfEmptySerializer>(true);
case TypeTag.Bool: case TypeTag.Bool:
return SyntaxHelpers.Type<Capnp.ListOfBitsSerializer>(); return Type<Capnp.ListOfBitsSerializer>(true);
case TypeTag.F32: case TypeTag.F32:
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<float>>(); return Type<Capnp.ListOfPrimitivesSerializer<float>>(true);
case TypeTag.F64: case TypeTag.F64:
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<double>>(); return Type<Capnp.ListOfPrimitivesSerializer<double>>(true);
case TypeTag.S8: case TypeTag.S8:
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<sbyte>>(); return Type<Capnp.ListOfPrimitivesSerializer<sbyte>>(true);
case TypeTag.U8: case TypeTag.U8:
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<byte>>(); return Type<Capnp.ListOfPrimitivesSerializer<byte>>(true);
case TypeTag.S16: case TypeTag.S16:
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<short>>(); return Type<Capnp.ListOfPrimitivesSerializer<short>>(true);
case TypeTag.U16: case TypeTag.U16:
case TypeTag.AnyEnum: case TypeTag.AnyEnum:
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<ushort>>(); return Type<Capnp.ListOfPrimitivesSerializer<ushort>>(true);
case TypeTag.S32: case TypeTag.S32:
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<int>>(); return Type<Capnp.ListOfPrimitivesSerializer<int>>(true);
case TypeTag.U32: case TypeTag.U32:
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<uint>>(); return Type<Capnp.ListOfPrimitivesSerializer<uint>>(true);
case TypeTag.S64: case TypeTag.S64:
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<long>>(); return Type<Capnp.ListOfPrimitivesSerializer<long>>(true);
case TypeTag.U64: case TypeTag.U64:
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<ulong>>(); return Type<Capnp.ListOfPrimitivesSerializer<ulong>>(true);
default: default:
throw new NotImplementedException("Unexpected type tag, don't know how to deal with this"); throw new NotImplementedException("Unexpected type tag, don't know how to deal with this");
@ -373,19 +374,22 @@ namespace CapnpC.CSharp.Generator.CodeGen
public TypeSyntax MakeTypeSyntax(Model.Type type, TypeDefinition scope, TypeUsage usage) public TypeSyntax MakeTypeSyntax(Model.Type type, TypeDefinition scope, TypeUsage usage)
{ {
bool nonNullable = usage != TypeUsage.DomainClassNullable;
switch (type.Tag) switch (type.Tag)
{ {
case TypeTag.AnyEnum: case TypeTag.AnyEnum:
return MaybeNullableValueType(SyntaxHelpers.Type<ushort>(), usage); return MaybeNullableValueType(Type<ushort>(), usage);
case TypeTag.CapabilityPointer: case TypeTag.CapabilityPointer:
if (type.Parameter != null) if (type.Parameter != null)
{ {
return GetQName(type, scope); return nonNullable ? GetQName(type, scope) :
MakeNullableType(GetQName(type, scope));
} }
else else
{ {
return SyntaxHelpers.Type<Capnp.Rpc.BareProxy>(); return Type<Capnp.Rpc.BareProxy>(nonNullable);
} }
case TypeTag.AnyPointer: case TypeTag.AnyPointer:
@ -393,20 +397,22 @@ namespace CapnpC.CSharp.Generator.CodeGen
switch (usage) switch (usage)
{ {
case TypeUsage.Reader: case TypeUsage.Reader:
return SyntaxHelpers.Type<Capnp.DeserializerState>(); return Type<Capnp.DeserializerState>();
case TypeUsage.Writer: case TypeUsage.Writer:
return SyntaxHelpers.Type<Capnp.DynamicSerializerState>(); return Type<Capnp.DynamicSerializerState>();
case TypeUsage.DomainClass: case TypeUsage.DomainClass:
case TypeUsage.DomainClassNullable: case TypeUsage.DomainClassNullable:
if (type.Parameter != null) if (type.Parameter != null)
{ {
return GetQName(type, scope); return nonNullable ?
GetQName(type, scope) :
MakeNullableType(GetQName(type, scope));
} }
else else
{ {
return SyntaxHelpers.Type<object>(); return Type<object>(nonNullable);
} }
default: default:
@ -414,7 +420,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
} }
case TypeTag.Bool: case TypeTag.Bool:
return MaybeNullableValueType(SyntaxHelpers.Type<bool>(), usage); return MaybeNullableValueType(Type<bool>(), usage);
case TypeTag.Data: case TypeTag.Data:
switch (usage) switch (usage)
@ -422,10 +428,10 @@ namespace CapnpC.CSharp.Generator.CodeGen
case TypeUsage.Reader: case TypeUsage.Reader:
case TypeUsage.DomainClass: case TypeUsage.DomainClass:
case TypeUsage.DomainClassNullable: case TypeUsage.DomainClassNullable:
return SyntaxHelpers.Type<IReadOnlyList<byte>>(); return Type<IReadOnlyList<byte>>(nonNullable);
case TypeUsage.Writer: case TypeUsage.Writer:
return SyntaxHelpers.Type<Capnp.ListOfPrimitivesSerializer<byte>>(); return Type<Capnp.ListOfPrimitivesSerializer<byte>>(true);
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
@ -448,21 +454,23 @@ namespace CapnpC.CSharp.Generator.CodeGen
return QualifiedName(GetQName(type, scope), ReaderStruct.IdentifierName); return QualifiedName(GetQName(type, scope), ReaderStruct.IdentifierName);
case TypeUsage.DomainClass: case TypeUsage.DomainClass:
case TypeUsage.DomainClassNullable:
return GetQName(type, scope); return GetQName(type, scope);
case TypeUsage.DomainClassNullable:
return MakeNullableType(GetQName(type, scope));
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
} }
case TypeTag.F32: case TypeTag.F32:
return MaybeNullableValueType(SyntaxHelpers.Type<float>(), usage); return MaybeNullableValueType(Type<float>(), usage);
case TypeTag.F64: case TypeTag.F64:
return MaybeNullableValueType(SyntaxHelpers.Type<double>(), usage); return MaybeNullableValueType(Type<double>(), usage);
case TypeTag.List when type.ElementType.Tag == TypeTag.Void && usage != TypeUsage.Writer: case TypeTag.List when type.ElementType.Tag == TypeTag.Void && usage != TypeUsage.Writer:
return MaybeNullableValueType(SyntaxHelpers.Type<int>(), usage); return MaybeNullableValueType(Type<int>(), usage);
case TypeTag.List: case TypeTag.List:
switch (usage) switch (usage)
@ -477,7 +485,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
case TypeUsage.DomainClass: case TypeUsage.DomainClass:
case TypeUsage.DomainClassNullable: case TypeUsage.DomainClassNullable:
return GenericName(Identifier("IReadOnlyList")) return GenericName(Identifier("IReadOnlyList"))
.AddTypeArgumentListArguments(MakeTypeSyntax(type.ElementType, scope, TypeUsage.DomainClass)); .AddTypeArgumentListArguments(MakeTypeSyntax(type.ElementType, scope, usage));
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
@ -487,45 +495,47 @@ namespace CapnpC.CSharp.Generator.CodeGen
switch (usage) switch (usage)
{ {
case TypeUsage.Writer: case TypeUsage.Writer:
return SyntaxHelpers.Type<Capnp.SerializerState>(); return Type<Capnp.SerializerState>();
case TypeUsage.Reader: case TypeUsage.Reader:
return SyntaxHelpers.Type<IReadOnlyList<Capnp.DeserializerState>>(); return Type<IReadOnlyList<Capnp.DeserializerState>>();
case TypeUsage.DomainClass: case TypeUsage.DomainClass:
return Type<IReadOnlyList<object>>(false);
case TypeUsage.DomainClassNullable: case TypeUsage.DomainClassNullable:
return SyntaxHelpers.Type<IReadOnlyList<object>>(); return Type<IReadOnlyList<object>>(true);
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
} }
case TypeTag.S16: case TypeTag.S16:
return MaybeNullableValueType(SyntaxHelpers.Type<short>(), usage); return MaybeNullableValueType(Type<short>(), usage);
case TypeTag.S32: case TypeTag.S32:
return MaybeNullableValueType(SyntaxHelpers.Type<int>(), usage); return MaybeNullableValueType(Type<int>(), usage);
case TypeTag.S64: case TypeTag.S64:
return MaybeNullableValueType(SyntaxHelpers.Type<long>(), usage); return MaybeNullableValueType(Type<long>(), usage);
case TypeTag.S8: case TypeTag.S8:
return MaybeNullableValueType(SyntaxHelpers.Type<sbyte>(), usage); return MaybeNullableValueType(Type<sbyte>(), usage);
case TypeTag.Text: case TypeTag.Text:
return SyntaxHelpers.Type<string>(); return Type<string>(nonNullable);
case TypeTag.U16: case TypeTag.U16:
return MaybeNullableValueType(SyntaxHelpers.Type<ushort>(), usage); return MaybeNullableValueType(Type<ushort>(), usage);
case TypeTag.U32: case TypeTag.U32:
return MaybeNullableValueType(SyntaxHelpers.Type<uint>(), usage); return MaybeNullableValueType(Type<uint>(), usage);
case TypeTag.U64: case TypeTag.U64:
return MaybeNullableValueType(SyntaxHelpers.Type<ulong>(), usage); return MaybeNullableValueType(Type<ulong>(), usage);
case TypeTag.U8: case TypeTag.U8:
return MaybeNullableValueType(SyntaxHelpers.Type<byte>(), usage); return MaybeNullableValueType(Type<byte>(), usage);
case TypeTag.Void: case TypeTag.Void:
return PredefinedType(Token(SyntaxKind.VoidKeyword)); return PredefinedType(Token(SyntaxKind.VoidKeyword));
@ -637,5 +647,22 @@ namespace CapnpC.CSharp.Generator.CodeGen
method.Name, method.Name,
MakePipeliningSupportExtensionMethodName(path))); MakePipeliningSupportExtensionMethodName(path)));
} }
public TypeSyntax MakeNullableType(TypeSyntax type)
{
return NullableEnable ?
NullableType(type) :
type;
}
public TypeSyntax Type<T>(bool nonNullable = false)
{
return NullableEnable && !typeof(T).IsValueType && !nonNullable ?
NullableType(SyntaxHelpers.NonNullableType<T>()) :
SyntaxHelpers.NonNullableType<T>();
}
public ClassOrStructConstraintSyntax MakeNullableClassConstraint() => ClassOrStructConstraint(SyntaxKind.ClassConstraint);
} }
} }

View File

@ -29,13 +29,13 @@ namespace CapnpC.CSharp.Generator.CodeGen
case 1: case 1:
return GenericName(nameof(Task)).AddTypeArgumentListArguments( return GenericName(nameof(Task)).AddTypeArgumentListArguments(
_names.MakeTypeSyntax(method.Results[0].Type, method.DeclaringInterface, TypeUsage.DomainClass)); _names.MakeTypeSyntax(method.Results[0].Type, method.DeclaringInterface, TypeUsage.DomainClassNullable));
default: default:
return GenericName(nameof(Task)).AddTypeArgumentListArguments( return GenericName(nameof(Task)).AddTypeArgumentListArguments(
TupleType(SeparatedList( TupleType(SeparatedList(
method.Results.Select( method.Results.Select(
f => TupleElement(_names.MakeTypeSyntax(f.Type, method.DeclaringInterface, TypeUsage.DomainClass)))))); f => TupleElement(_names.MakeTypeSyntax(f.Type, method.DeclaringInterface, TypeUsage.DomainClassNullable))))));
} }
} }
@ -50,14 +50,14 @@ namespace CapnpC.CSharp.Generator.CodeGen
if (arg0.Name == null) if (arg0.Name == null)
{ {
list.Add(Parameter(_names.AnonymousParameter.Identifier) list.Add(Parameter(_names.AnonymousParameter.Identifier)
.WithType(_names.MakeTypeSyntax(arg0.Type, method.DeclaringInterface, TypeUsage.DomainClass))); .WithType(_names.MakeTypeSyntax(arg0.Type, method.DeclaringInterface, TypeUsage.DomainClassNullable)));
} }
else else
{ {
foreach (var arg in method.Params) foreach (var arg in method.Params)
{ {
list.Add(Parameter(Identifier(IdentifierRenamer.ToNonKeyword(arg.Name))) list.Add(Parameter(Identifier(IdentifierRenamer.ToNonKeyword(arg.Name)))
.WithType(_names.MakeTypeSyntax(arg.Type, method.DeclaringInterface, TypeUsage.DomainClass))); .WithType(_names.MakeTypeSyntax(arg.Type, method.DeclaringInterface, TypeUsage.DomainClassNullable)));
} }
} }
} }
@ -85,7 +85,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
{ {
yield return TypeParameterConstraintClause( yield return TypeParameterConstraintClause(
_names.GetGenericTypeParameter(name).IdentifierName) _names.GetGenericTypeParameter(name).IdentifierName)
.AddConstraints(ClassOrStructConstraint(SyntaxKind.ClassConstraint)); .AddConstraints(_names.MakeNullableClassConstraint());
} }
} }
@ -233,7 +233,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.SimpleMemberAccessExpression,
IdentifierName(nameof(Capnp.CapnpSerializable)), IdentifierName(nameof(Capnp.CapnpSerializable)),
GenericName(nameof(Capnp.CapnpSerializable.Create)) GenericName(nameof(Capnp.CapnpSerializable.Create))
.AddTypeArgumentListArguments(domainType))) .AddTypeArgumentListArguments(MakeNonNullableType(domainType))))
.AddArgumentListArguments( .AddArgumentListArguments(
Argument(_names.DeserializerLocal.IdentifierName)); Argument(_names.DeserializerLocal.IdentifierName));
@ -262,7 +262,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
{ {
yield return TypeParameterConstraintClause( yield return TypeParameterConstraintClause(
_names.GetGenericTypeParameter(name).IdentifierName) _names.GetGenericTypeParameter(name).IdentifierName)
.AddConstraints(ClassOrStructConstraint(SyntaxKind.ClassConstraint)); .AddConstraints(_names.MakeNullableClassConstraint());
} }
} }
@ -271,7 +271,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
var classDecl = ClassDeclaration(_names.MakeTypeName(type, NameUsage.Proxy).Identifier) var classDecl = ClassDeclaration(_names.MakeTypeName(type, NameUsage.Proxy).Identifier)
.AddModifiers(Public) .AddModifiers(Public)
.AddBaseListTypes( .AddBaseListTypes(
SimpleBaseType(Type<Capnp.Rpc.Proxy>()), SimpleBaseType(_names.Type<Capnp.Rpc.Proxy>(true)),
SimpleBaseType(_names.MakeGenericTypeName(type, NameUsage.Interface))); SimpleBaseType(_names.MakeGenericTypeName(type, NameUsage.Interface)));
if (type.GenericParameters.Count > 0) if (type.GenericParameters.Count > 0)
@ -361,7 +361,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.SimpleMemberAccessExpression,
_names.ParamsLocal.IdentifierName, _names.ParamsLocal.IdentifierName,
GenericName(nameof(Capnp.SerializerState.Rewrap)) GenericName(nameof(Capnp.SerializerState.Rewrap))
.AddTypeArgumentListArguments(Type<Capnp.DynamicSerializerState>()))) .AddTypeArgumentListArguments(_names.Type<Capnp.DynamicSerializerState>())))
.AddArgumentListArguments()), .AddArgumentListArguments()),
Argument( Argument(
LiteralExpression(SyntaxKind.FalseLiteralExpression)), LiteralExpression(SyntaxKind.FalseLiteralExpression)),
@ -446,7 +446,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
GenericName(_names.GetCodeIdentifier(method).ToString()) GenericName(_names.GetCodeIdentifier(method).ToString())
.AddTypeArgumentListArguments( .AddTypeArgumentListArguments(
Enumerable.Repeat( Enumerable.Repeat(
Type<Capnp.AnyPointer>(), _names.Type<Capnp.AnyPointer>(),
method.GenericParameters.Count).ToArray())); method.GenericParameters.Count).ToArray()));
} }
else else
@ -582,7 +582,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.SimpleMemberAccessExpression,
IdentifierName(nameof(Capnp.CapnpSerializable)), IdentifierName(nameof(Capnp.CapnpSerializable)),
GenericName(nameof(Capnp.CapnpSerializable.Create)) GenericName(nameof(Capnp.CapnpSerializable.Create))
.AddTypeArgumentListArguments(domainType))) .AddTypeArgumentListArguments(MakeNonNullableType(domainType))))
.AddArgumentListArguments( .AddArgumentListArguments(
Argument(_names.DeserializerLocal.IdentifierName)); Argument(_names.DeserializerLocal.IdentifierName));
@ -662,13 +662,13 @@ namespace CapnpC.CSharp.Generator.CodeGen
foreach (var method in def.Methods) foreach (var method in def.Methods)
{ {
var methodDecl = MethodDeclaration( var methodDecl = MethodDeclaration(
Type<Task<Capnp.Rpc.AnswerOrCounterquestion>>(), _names.Type<Task<Capnp.Rpc.AnswerOrCounterquestion>>(),
_names.GetCodeIdentifier(method).Identifier) _names.GetCodeIdentifier(method).Identifier)
.AddParameterListParameters( .AddParameterListParameters(
Parameter(_names.DeserializerLocal.Identifier) Parameter(_names.DeserializerLocal.Identifier)
.WithType(Type<Capnp.DeserializerState>()), .WithType(_names.Type<Capnp.DeserializerState>()),
Parameter(_names.CancellationTokenParameter.Identifier) Parameter(_names.CancellationTokenParameter.Identifier)
.WithType(Type<CancellationToken>())) .WithType(_names.Type<CancellationToken>()))
.AddBodyStatements( .AddBodyStatements(
MakeSkeletonMethodBody(method).ToArray()); MakeSkeletonMethodBody(method).ToArray());
@ -709,7 +709,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
.AddArgumentListArguments( .AddArgumentListArguments(
MakeSkeletonSetMethodTableArguments(type).ToArray()))), MakeSkeletonSetMethodTableArguments(type).ToArray()))),
// InterfaceId // InterfaceId
PropertyDeclaration(Type<ulong>(), nameof(Capnp.Rpc.Skeleton<object>.InterfaceId)) PropertyDeclaration(_names.Type<ulong>(), nameof(Capnp.Rpc.Skeleton<object>.InterfaceId))
.AddModifiers(Public, Override) .AddModifiers(Public, Override)
.WithExpressionBody( .WithExpressionBody(
ArrowExpressionClause( ArrowExpressionClause(

View File

@ -57,7 +57,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
ParameterList( ParameterList(
SingletonSeparatedList<ParameterSyntax>( SingletonSeparatedList<ParameterSyntax>(
Parameter(_names.ReaderContextField.Identifier) Parameter(_names.ReaderContextField.Identifier)
.WithType(Type<Capnp.DeserializerState>())))) .WithType(_names.Type<Capnp.DeserializerState>()))))
.WithExpressionBody( .WithExpressionBody(
ArrowExpressionClause( ArrowExpressionClause(
ObjectCreationExpression(_names.ReaderStruct.IdentifierName) ObjectCreationExpression(_names.ReaderStruct.IdentifierName)
@ -78,7 +78,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
SingletonSeparatedList( SingletonSeparatedList(
Parameter(_names.ContextParameter.Identifier) Parameter(_names.ContextParameter.Identifier)
.WithType( .WithType(
Type<Capnp.DeserializerState>())))) _names.Type<Capnp.DeserializerState>()))))
.WithExpressionBody( .WithExpressionBody(
ArrowExpressionClause( ArrowExpressionClause(
ObjectCreationExpression(_names.ReaderStruct.IdentifierName) ObjectCreationExpression(_names.ReaderStruct.IdentifierName)
@ -90,7 +90,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
{ {
yield return FieldDeclaration( yield return FieldDeclaration(
VariableDeclaration( VariableDeclaration(
Type<Capnp.DeserializerState>()) _names.Type<Capnp.DeserializerState>())
.AddVariables(_names.ReaderContextField.VariableDeclarator)) .AddVariables(_names.ReaderContextField.VariableDeclarator))
.AddModifiers(Readonly); .AddModifiers(Readonly);
@ -100,7 +100,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
ParameterList( ParameterList(
SingletonSeparatedList( SingletonSeparatedList(
Parameter(_names.ContextParameter.Identifier) Parameter(_names.ContextParameter.Identifier)
.WithType(Type<Capnp.DeserializerState>())))) .WithType(_names.Type<Capnp.DeserializerState>()))))
.WithBody( .WithBody(
Block( Block(
SingletonList<StatementSyntax>( SingletonList<StatementSyntax>(
@ -122,7 +122,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
{ {
yield return FieldDeclaration( yield return FieldDeclaration(
VariableDeclaration( VariableDeclaration(
Type<Capnp.DeserializerState>()) _names.Type<Capnp.DeserializerState>())
.AddVariables(_names.ReaderContextField.VariableDeclarator)) .AddVariables(_names.ReaderContextField.VariableDeclarator))
.AddModifiers(Readonly); .AddModifiers(Readonly);
@ -131,7 +131,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
.WithParameterList( .WithParameterList(
ParameterList( ParameterList(
SingletonSeparatedList(Parameter(_names.GroupReaderContextArg.Identifier) SingletonSeparatedList(Parameter(_names.GroupReaderContextArg.Identifier)
.WithType(Type<Capnp.DeserializerState>())))) .WithType(_names.Type<Capnp.DeserializerState>()))))
.WithBody( .WithBody(
Block( Block(
SingletonList<StatementSyntax>( SingletonList<StatementSyntax>(
@ -261,7 +261,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
PropertyDeclarationSyntax MakeReadPrimitiveProperty<T>(Field field, string readName) PropertyDeclarationSyntax MakeReadPrimitiveProperty<T>(Field field, string readName)
{ {
return MakeReadProperty(Type<T>(), _names.GetCodeIdentifier(field).ToString(), readName, field.BitOffset.Value, return MakeReadProperty(_names.Type<T>(), _names.GetCodeIdentifier(field).ToString(), readName, field.BitOffset.Value,
ValueOf(field.DefaultValue.ScalarValue), null, field.DiscValue.HasValue); ValueOf(field.DefaultValue.ScalarValue), null, field.DiscValue.HasValue);
} }
@ -278,7 +278,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
PropertyDeclarationSyntax MakeReadTextProperty(Field field) PropertyDeclarationSyntax MakeReadTextProperty(Field field)
{ {
return MakeReadProperty(Type<string>(), _names.GetCodeIdentifier(field).ToString(), return MakeReadProperty(_names.Type<string>(), _names.GetCodeIdentifier(field).ToString(),
nameof(Capnp.DeserializerState.ReadText), (int)field.Offset, nameof(Capnp.DeserializerState.ReadText), (int)field.Offset,
ValueOf(field.DefaultValue.ScalarValue), null, field.DiscValue.HasValue); ValueOf(field.DefaultValue.ScalarValue), null, field.DiscValue.HasValue);
} }
@ -396,7 +396,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
case TypeTag.ListPointer: case TypeTag.ListPointer:
{ {
listType = Type<IReadOnlyList<object>>(); listType = _names.Type<IReadOnlyList<object>>();
context = InvocationExpression(MemberAccessExpression( context = InvocationExpression(MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.SimpleMemberAccessExpression,
@ -445,14 +445,14 @@ namespace CapnpC.CSharp.Generator.CodeGen
case TypeTag.AnyPointer: case TypeTag.AnyPointer:
case TypeTag.StructPointer: case TypeTag.StructPointer:
{ {
listType = Type<IReadOnlyList<Capnp.DeserializerState>>(); listType = _names.Type<IReadOnlyList<Capnp.DeserializerState>>();
impl = context; impl = context;
return; return;
} }
case TypeTag.Void: case TypeTag.Void:
{ {
listType = Type<int>(); listType = _names.Type<int>();
impl = MemberAccessExpression( impl = MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.SimpleMemberAccessExpression,
context, context,

View File

@ -21,7 +21,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
public static readonly SyntaxToken Partial = Token(SyntaxKind.PartialKeyword); public static readonly SyntaxToken Partial = Token(SyntaxKind.PartialKeyword);
public static readonly SyntaxToken This = Token(SyntaxKind.ThisKeyword); public static readonly SyntaxToken This = Token(SyntaxKind.ThisKeyword);
public static TypeSyntax Type(Type type) public static TypeSyntax NonNullableType(Type type)
{ {
switch (0) switch (0)
{ {
@ -66,14 +66,14 @@ namespace CapnpC.CSharp.Generator.CodeGen
case 0 when type.IsGenericType: case 0 when type.IsGenericType:
return GenericName(type.Name.Substring(0, type.Name.IndexOf('`'))) return GenericName(type.Name.Substring(0, type.Name.IndexOf('`')))
.AddTypeArgumentListArguments(type.GetGenericArguments().Select(Type).ToArray()); .AddTypeArgumentListArguments(type.GetGenericArguments().Select(NonNullableType).ToArray());
default: default:
return ParseTypeName(type.Name); return ParseTypeName(type.Name);
} }
} }
public static TypeSyntax Type<T>() => Type(typeof(T)); public static TypeSyntax NonNullableType<T>() => NonNullableType(typeof(T));
public static ExpressionSyntax ValueOf(object value) public static ExpressionSyntax ValueOf(object value)
{ {
@ -83,16 +83,16 @@ namespace CapnpC.CSharp.Generator.CodeGen
return LiteralExpression(x ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression); return LiteralExpression(x ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression);
case sbyte x: case sbyte x:
return CastExpression(Type<sbyte>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); return CastExpression(NonNullableType<sbyte>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)));
case byte x: case byte x:
return CastExpression(Type<byte>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); return CastExpression(NonNullableType<byte>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)));
case short x: case short x:
return CastExpression(Type<short>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); return CastExpression(NonNullableType<short>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)));
case ushort x: case ushort x:
return CastExpression(Type<ushort>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); return CastExpression(NonNullableType<ushort>(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)));
case int x: case int x:
return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x));
@ -122,5 +122,14 @@ namespace CapnpC.CSharp.Generator.CodeGen
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
public static TypeSyntax MakeNonNullableType(TypeSyntax type)
{
if (type is NullableTypeSyntax nts)
{
type = nts.ElementType;
}
return type;
}
} }
} }

View File

@ -195,7 +195,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
PropertyDeclarationSyntax MakePrimitiveProperty<T>(Field field, string readName) PropertyDeclarationSyntax MakePrimitiveProperty<T>(Field field, string readName)
{ {
return MakeProperty(Type<T>(), null, _names.GetCodeIdentifier(field).ToString(), return MakeProperty(_names.Type<T>(), null, _names.GetCodeIdentifier(field).ToString(),
readName, readName,
nameof(Capnp.SerializerExtensions.WriteData), nameof(Capnp.SerializerExtensions.WriteData),
field.BitOffset.Value, field.BitOffset.Value,
@ -207,7 +207,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
PropertyDeclarationSyntax MakeEnumProperty(Field field, string readName) PropertyDeclarationSyntax MakeEnumProperty(Field field, string readName)
{ {
return MakeProperty(_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.NotRelevant), Type<ushort>(), return MakeProperty(_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.NotRelevant), _names.Type<ushort>(),
_names.GetCodeIdentifier(field).ToString(), _names.GetCodeIdentifier(field).ToString(),
readName, readName,
nameof(Capnp.SerializerExtensions.WriteData), nameof(Capnp.SerializerExtensions.WriteData),
@ -220,7 +220,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
PropertyDeclarationSyntax MakeTextProperty(Field field) PropertyDeclarationSyntax MakeTextProperty(Field field)
{ {
return MakeProperty(Type<string>(), null, return MakeProperty(_names.Type<string>(), null,
_names.GetCodeIdentifier(field).ToString(), _names.GetCodeIdentifier(field).ToString(),
nameof(Capnp.SerializerState.ReadText), nameof(Capnp.SerializerState.ReadText),
nameof(Capnp.SerializerState.WriteText), nameof(Capnp.SerializerState.WriteText),
@ -282,7 +282,7 @@ namespace CapnpC.CSharp.Generator.CodeGen
{ {
return MakeProperty( return MakeProperty(
_names.UnionDiscriminatorEnum.IdentifierName, _names.UnionDiscriminatorEnum.IdentifierName,
Type<ushort>(), _names.Type<ushort>(),
_names.UnionDiscriminatorProp.ToString(), _names.UnionDiscriminatorProp.ToString(),
nameof(Capnp.SerializerExtensions.ReadDataUShort), nameof(Capnp.SerializerExtensions.ReadDataUShort),
nameof(Capnp.SerializerExtensions.WriteData), nameof(Capnp.SerializerExtensions.WriteData),

View File

@ -11,6 +11,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; } = true;
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

@ -2,7 +2,9 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp3.0</TargetFramework>
<LangVersion>8.0</LangVersion>
<Nullable>Enable</Nullable>
<Version>1.3-local</Version> <Version>1.3-local</Version>
<Configurations>Debug;Release</Configurations> <Configurations>Debug;Release</Configurations>
<PackageReferenceVersion Condition="'$(PackageReferenceVersion)'==''">$(Version)*</PackageReferenceVersion> <PackageReferenceVersion Condition="'$(PackageReferenceVersion)'==''">$(Version)*</PackageReferenceVersion>

11
include/csharp.capnp Normal file
View File

@ -0,0 +1,11 @@
@0xeb0d831668c6edab;
$csNamespace("Capnp.Annotations");
annotation csNamespace @0xeb0d831668c6eda0 (file) : Text;
# C# namespace for code generation
annotation csNullableEnable @0xeb0d831668c6eda1 (file) : Bool;
# Whether to generate C# nullable reference types
annotation csName @0xeb0d831668c6eda2 (field, enumerant, struct, enum, interface, method, param, group, union) : Text;
# C# member name for code generation