From 4da57f9a28ca8e520f2a03f3b17ce9998a4e1aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6llner?= Date: Sun, 19 Jan 2020 14:35:43 +0100 Subject: [PATCH] wip --- .../CapnpC.CSharp.Generator.Tests.csproj | 4 +- .../CodeGen/CodeGenerator.cs | 2 +- .../CodeGen/CommonSnippetGen.cs | 4 +- .../CodeGen/DomainClassSnippetGen.cs | 20 +-- CapnpC.CSharp.Generator/CodeGen/GenNames.cs | 115 +++++++++++------- .../CodeGen/InterfaceSnippetGen.cs | 30 ++--- .../CodeGen/ReaderSnippetGen.cs | 22 ++-- .../CodeGen/SyntaxHelpers.cs | 23 ++-- .../CodeGen/WriterSnippetGen.cs | 8 +- CapnpC.CSharp.Generator/Model/GenFile.cs | 1 + .../MsBuildGenerationTest.csproj | 4 +- include/csharp.capnp | 11 ++ 12 files changed, 147 insertions(+), 97 deletions(-) create mode 100644 include/csharp.capnp diff --git a/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj b/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj index 55dba85..07457e7 100644 --- a/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj +++ b/CapnpC.CSharp.Generator.Tests/CapnpC.CSharp.Generator.Tests.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs b/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs index e3c5db6..8c0f19e 100644 --- a/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs +++ b/CapnpC.CSharp.Generator/CodeGen/CodeGenerator.cs @@ -61,7 +61,7 @@ { var topDecl = ClassDeclaration(_names.MakeTypeName(def).Identifier) .AddModifiers(Public) - .AddBaseListTypes(SimpleBaseType(Type())); + .AddBaseListTypes(SimpleBaseType(_names.Type(true))); if (def.GenericParameters.Count > 0) { diff --git a/CapnpC.CSharp.Generator/CodeGen/CommonSnippetGen.cs b/CapnpC.CSharp.Generator/CodeGen/CommonSnippetGen.cs index c214809..8221147 100644 --- a/CapnpC.CSharp.Generator/CodeGen/CommonSnippetGen.cs +++ b/CapnpC.CSharp.Generator/CodeGen/CommonSnippetGen.cs @@ -22,7 +22,7 @@ namespace CapnpC.CSharp.Generator.CodeGen { var whichEnum = EnumDeclaration(_names.UnionDiscriminatorEnum.ToString()) .AddModifiers(Public) - .AddBaseListTypes(SimpleBaseType(Type())); + .AddBaseListTypes(SimpleBaseType(_names.Type())); var discFields = def.Fields.Where(f => f.DiscValue.HasValue); @@ -52,7 +52,7 @@ namespace CapnpC.CSharp.Generator.CodeGen var decl = EnumDeclaration(def.Name) .WithAttributeLists(MakeTypeIdAttributeLists(def.Id)) .AddModifiers(Public) - .AddBaseListTypes(SimpleBaseType(Type())); + .AddBaseListTypes(SimpleBaseType(_names.Type())); foreach (var enumerant in def.Enumerants.OrderBy(e => e.CodeOrder)) { diff --git a/CapnpC.CSharp.Generator/CodeGen/DomainClassSnippetGen.cs b/CapnpC.CSharp.Generator/CodeGen/DomainClassSnippetGen.cs index a255b84..9701ff9 100644 --- a/CapnpC.CSharp.Generator/CodeGen/DomainClassSnippetGen.cs +++ b/CapnpC.CSharp.Generator/CodeGen/DomainClassSnippetGen.cs @@ -75,7 +75,7 @@ namespace CapnpC.CSharp.Generator.CodeGen 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) .AddModifiers(Public).AddAccessorListAccessors( AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) @@ -111,7 +111,7 @@ namespace CapnpC.CSharp.Generator.CodeGen MemberDeclarationSyntax MakeUnionContentField() { return FieldDeclaration( - VariableDeclaration(SyntaxHelpers.Type()) + VariableDeclaration(_names.Type()) .WithVariables( SingletonSeparatedList( VariableDeclarator(_names.UnionContentField.Identifier)))) @@ -282,7 +282,7 @@ namespace CapnpC.CSharp.Generator.CodeGen value.Decode(); return ArrayCreationExpression(ArrayType( - _names.MakeTypeSyntax(value.Type.ElementType, scope, TypeUsage.DomainClass)) + _names.MakeTypeSyntax(value.Type.ElementType, scope, TypeUsage.DomainClassNullable)) .WithRankSpecifiers( SingletonList( ArrayRankSpecifier( @@ -611,7 +611,7 @@ namespace CapnpC.CSharp.Generator.CodeGen SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(Capnp.CapnpSerializable)), GenericName(nameof(Capnp.CapnpSerializable.Create)) - .AddTypeArgumentListArguments(elementType))) + .AddTypeArgumentListArguments(MakeNonNullableType(elementType)))) .AddArgumentListArguments(Argument(IdentifierName("_")))))); } @@ -645,7 +645,7 @@ namespace CapnpC.CSharp.Generator.CodeGen .AddArgumentListArguments(Argument( SimpleLambdaExpression( Parameter(Identifier("_")), - CastExpression(Type(), IdentifierName("_"))))); + CastExpression(_names.Type(), IdentifierName("_"))))); } ExpressionSyntax MakeDeserializeMethodRightHandSide(Field field) @@ -662,10 +662,10 @@ namespace CapnpC.CSharp.Generator.CodeGen IdentifierName(nameof(Capnp.CapnpSerializable)), GenericName(nameof(Capnp.CapnpSerializable.Create)) .AddTypeArgumentListArguments( - _names.MakeTypeSyntax( + MakeNonNullableType(_names.MakeTypeSyntax( field.Type, field.DeclaringType, - TypeUsage.DomainClass)))) + TypeUsage.DomainClass))))) .AddArgumentListArguments(Argument(MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, _names.ReaderParameter.IdentifierName, @@ -684,7 +684,7 @@ namespace CapnpC.CSharp.Generator.CodeGen SyntaxKind.SimpleMemberAccessExpression, _names.ReaderParameter.IdentifierName, _names.GetCodeIdentifier(field).IdentifierName), - _names.MakeTypeSyntax(elementType, field.DeclaringType, TypeUsage.DomainClass), + _names.MakeTypeSyntax(elementType, field.DeclaringType, TypeUsage.DomainClassNullable), rank); case TypeTag.ListPointer: @@ -849,7 +849,7 @@ namespace CapnpC.CSharp.Generator.CodeGen ExplicitInterfaceSpecifier(IdentifierName(nameof(Capnp.ICapnpSerializable)))) .AddParameterListParameters( Parameter(_names.AnonymousParameter.Identifier) - .WithType(Type())) + .WithType(_names.Type(true))) .AddBodyStatements( ExpressionStatement( InvocationExpression(_names.SerializeMethod.IdentifierName) @@ -933,7 +933,7 @@ namespace CapnpC.CSharp.Generator.CodeGen ExplicitInterfaceSpecifier(IdentifierName(nameof(Capnp.ICapnpSerializable)))) .AddParameterListParameters( Parameter(_names.AnonymousParameter.Identifier) - .WithType(Type())) + .WithType(_names.Type())) .AddBodyStatements(stmts.ToArray()); } diff --git a/CapnpC.CSharp.Generator/CodeGen/GenNames.cs b/CapnpC.CSharp.Generator/CodeGen/GenNames.cs index 42c5938..8510c60 100644 --- a/CapnpC.CSharp.Generator/CodeGen/GenNames.cs +++ b/CapnpC.CSharp.Generator/CodeGen/GenNames.cs @@ -66,6 +66,7 @@ namespace CapnpC.CSharp.Generator.CodeGen public string PipeliningExtensionsClassFormat { get; } public string ProxyClassFormat { get; } public string SkeletonClassFormat { get; } + public bool NullableEnable { get; set; } public GenNames(GeneratorOptions options) { TopNamespace = new Name(options.TopNamespaceName).IdentifierName; @@ -288,14 +289,14 @@ namespace CapnpC.CSharp.Generator.CodeGen case TypeTag.AnyPointer: case TypeTag.StructPointer: case TypeTag.ListPointer: - return SyntaxHelpers.Type>(); + return Type>(true); case TypeTag.CapabilityPointer: - return SyntaxHelpers.Type>(); + return Type>(true); case TypeTag.Data: - return SyntaxHelpers.Type>>(); + return Type>>(true); case TypeTag.Enum: return GenericName("ListOfPrimitivesSerializer") @@ -315,44 +316,44 @@ namespace CapnpC.CSharp.Generator.CodeGen .AddTypeArgumentListArguments(MakeTypeSyntax(elementType, scope, TypeUsage.Writer)); case TypeTag.Text: - return SyntaxHelpers.Type(); + return Type(true); case TypeTag.Void: - return SyntaxHelpers.Type(); + return Type(true); case TypeTag.Bool: - return SyntaxHelpers.Type(); + return Type(true); case TypeTag.F32: - return SyntaxHelpers.Type>(); + return Type>(true); case TypeTag.F64: - return SyntaxHelpers.Type>(); + return Type>(true); case TypeTag.S8: - return SyntaxHelpers.Type>(); + return Type>(true); case TypeTag.U8: - return SyntaxHelpers.Type>(); + return Type>(true); case TypeTag.S16: - return SyntaxHelpers.Type>(); + return Type>(true); case TypeTag.U16: case TypeTag.AnyEnum: - return SyntaxHelpers.Type>(); + return Type>(true); case TypeTag.S32: - return SyntaxHelpers.Type>(); + return Type>(true); case TypeTag.U32: - return SyntaxHelpers.Type>(); + return Type>(true); case TypeTag.S64: - return SyntaxHelpers.Type>(); + return Type>(true); case TypeTag.U64: - return SyntaxHelpers.Type>(); + return Type>(true); default: 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) { + bool nonNullable = usage != TypeUsage.DomainClassNullable; + switch (type.Tag) { case TypeTag.AnyEnum: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); + return MaybeNullableValueType(Type(), usage); case TypeTag.CapabilityPointer: if (type.Parameter != null) { - return GetQName(type, scope); + return nonNullable ? GetQName(type, scope) : + MakeNullableType(GetQName(type, scope)); } else { - return SyntaxHelpers.Type(); + return Type(nonNullable); } case TypeTag.AnyPointer: @@ -393,20 +397,22 @@ namespace CapnpC.CSharp.Generator.CodeGen switch (usage) { case TypeUsage.Reader: - return SyntaxHelpers.Type(); + return Type(); case TypeUsage.Writer: - return SyntaxHelpers.Type(); + return Type(); case TypeUsage.DomainClass: case TypeUsage.DomainClassNullable: if (type.Parameter != null) { - return GetQName(type, scope); + return nonNullable ? + GetQName(type, scope) : + MakeNullableType(GetQName(type, scope)); } else { - return SyntaxHelpers.Type(); + return Type(nonNullable); } default: @@ -414,7 +420,7 @@ namespace CapnpC.CSharp.Generator.CodeGen } case TypeTag.Bool: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); + return MaybeNullableValueType(Type(), usage); case TypeTag.Data: switch (usage) @@ -422,10 +428,10 @@ namespace CapnpC.CSharp.Generator.CodeGen case TypeUsage.Reader: case TypeUsage.DomainClass: case TypeUsage.DomainClassNullable: - return SyntaxHelpers.Type>(); + return Type>(nonNullable); case TypeUsage.Writer: - return SyntaxHelpers.Type>(); + return Type>(true); default: throw new NotImplementedException(); @@ -448,21 +454,23 @@ namespace CapnpC.CSharp.Generator.CodeGen return QualifiedName(GetQName(type, scope), ReaderStruct.IdentifierName); case TypeUsage.DomainClass: - case TypeUsage.DomainClassNullable: return GetQName(type, scope); + case TypeUsage.DomainClassNullable: + return MakeNullableType(GetQName(type, scope)); + default: throw new NotImplementedException(); } case TypeTag.F32: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); + return MaybeNullableValueType(Type(), usage); case TypeTag.F64: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); + return MaybeNullableValueType(Type(), usage); case TypeTag.List when type.ElementType.Tag == TypeTag.Void && usage != TypeUsage.Writer: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); + return MaybeNullableValueType(Type(), usage); case TypeTag.List: switch (usage) @@ -477,7 +485,7 @@ namespace CapnpC.CSharp.Generator.CodeGen case TypeUsage.DomainClass: case TypeUsage.DomainClassNullable: return GenericName(Identifier("IReadOnlyList")) - .AddTypeArgumentListArguments(MakeTypeSyntax(type.ElementType, scope, TypeUsage.DomainClass)); + .AddTypeArgumentListArguments(MakeTypeSyntax(type.ElementType, scope, usage)); default: throw new NotImplementedException(); @@ -487,45 +495,47 @@ namespace CapnpC.CSharp.Generator.CodeGen switch (usage) { case TypeUsage.Writer: - return SyntaxHelpers.Type(); + return Type(); case TypeUsage.Reader: - return SyntaxHelpers.Type>(); + return Type>(); case TypeUsage.DomainClass: + return Type>(false); + case TypeUsage.DomainClassNullable: - return SyntaxHelpers.Type>(); + return Type>(true); default: throw new NotImplementedException(); } case TypeTag.S16: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); + return MaybeNullableValueType(Type(), usage); case TypeTag.S32: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); + return MaybeNullableValueType(Type(), usage); case TypeTag.S64: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); + return MaybeNullableValueType(Type(), usage); case TypeTag.S8: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); + return MaybeNullableValueType(Type(), usage); case TypeTag.Text: - return SyntaxHelpers.Type(); + return Type(nonNullable); case TypeTag.U16: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); + return MaybeNullableValueType(Type(), usage); case TypeTag.U32: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); + return MaybeNullableValueType(Type(), usage); case TypeTag.U64: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); + return MaybeNullableValueType(Type(), usage); case TypeTag.U8: - return MaybeNullableValueType(SyntaxHelpers.Type(), usage); + return MaybeNullableValueType(Type(), usage); case TypeTag.Void: return PredefinedType(Token(SyntaxKind.VoidKeyword)); @@ -637,5 +647,22 @@ namespace CapnpC.CSharp.Generator.CodeGen method.Name, MakePipeliningSupportExtensionMethodName(path))); } + + public TypeSyntax MakeNullableType(TypeSyntax type) + { + return NullableEnable ? + NullableType(type) : + type; + + } + + public TypeSyntax Type(bool nonNullable = false) + { + return NullableEnable && !typeof(T).IsValueType && !nonNullable ? + NullableType(SyntaxHelpers.NonNullableType()) : + SyntaxHelpers.NonNullableType(); + } + + public ClassOrStructConstraintSyntax MakeNullableClassConstraint() => ClassOrStructConstraint(SyntaxKind.ClassConstraint); } } diff --git a/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs b/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs index 6344b85..d24b9f8 100644 --- a/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs +++ b/CapnpC.CSharp.Generator/CodeGen/InterfaceSnippetGen.cs @@ -29,13 +29,13 @@ namespace CapnpC.CSharp.Generator.CodeGen case 1: 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: return GenericName(nameof(Task)).AddTypeArgumentListArguments( TupleType(SeparatedList( 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) { 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 { foreach (var arg in method.Params) { 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( _names.GetGenericTypeParameter(name).IdentifierName) - .AddConstraints(ClassOrStructConstraint(SyntaxKind.ClassConstraint)); + .AddConstraints(_names.MakeNullableClassConstraint()); } } @@ -233,7 +233,7 @@ namespace CapnpC.CSharp.Generator.CodeGen SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(Capnp.CapnpSerializable)), GenericName(nameof(Capnp.CapnpSerializable.Create)) - .AddTypeArgumentListArguments(domainType))) + .AddTypeArgumentListArguments(MakeNonNullableType(domainType)))) .AddArgumentListArguments( Argument(_names.DeserializerLocal.IdentifierName)); @@ -262,7 +262,7 @@ namespace CapnpC.CSharp.Generator.CodeGen { yield return TypeParameterConstraintClause( _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) .AddModifiers(Public) .AddBaseListTypes( - SimpleBaseType(Type()), + SimpleBaseType(_names.Type(true)), SimpleBaseType(_names.MakeGenericTypeName(type, NameUsage.Interface))); if (type.GenericParameters.Count > 0) @@ -361,7 +361,7 @@ namespace CapnpC.CSharp.Generator.CodeGen SyntaxKind.SimpleMemberAccessExpression, _names.ParamsLocal.IdentifierName, GenericName(nameof(Capnp.SerializerState.Rewrap)) - .AddTypeArgumentListArguments(Type()))) + .AddTypeArgumentListArguments(_names.Type()))) .AddArgumentListArguments()), Argument( LiteralExpression(SyntaxKind.FalseLiteralExpression)), @@ -446,7 +446,7 @@ namespace CapnpC.CSharp.Generator.CodeGen GenericName(_names.GetCodeIdentifier(method).ToString()) .AddTypeArgumentListArguments( Enumerable.Repeat( - Type(), + _names.Type(), method.GenericParameters.Count).ToArray())); } else @@ -582,7 +582,7 @@ namespace CapnpC.CSharp.Generator.CodeGen SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(Capnp.CapnpSerializable)), GenericName(nameof(Capnp.CapnpSerializable.Create)) - .AddTypeArgumentListArguments(domainType))) + .AddTypeArgumentListArguments(MakeNonNullableType(domainType)))) .AddArgumentListArguments( Argument(_names.DeserializerLocal.IdentifierName)); @@ -662,13 +662,13 @@ namespace CapnpC.CSharp.Generator.CodeGen foreach (var method in def.Methods) { var methodDecl = MethodDeclaration( - Type>(), + _names.Type>(), _names.GetCodeIdentifier(method).Identifier) .AddParameterListParameters( Parameter(_names.DeserializerLocal.Identifier) - .WithType(Type()), + .WithType(_names.Type()), Parameter(_names.CancellationTokenParameter.Identifier) - .WithType(Type())) + .WithType(_names.Type())) .AddBodyStatements( MakeSkeletonMethodBody(method).ToArray()); @@ -709,7 +709,7 @@ namespace CapnpC.CSharp.Generator.CodeGen .AddArgumentListArguments( MakeSkeletonSetMethodTableArguments(type).ToArray()))), // InterfaceId - PropertyDeclaration(Type(), nameof(Capnp.Rpc.Skeleton.InterfaceId)) + PropertyDeclaration(_names.Type(), nameof(Capnp.Rpc.Skeleton.InterfaceId)) .AddModifiers(Public, Override) .WithExpressionBody( ArrowExpressionClause( diff --git a/CapnpC.CSharp.Generator/CodeGen/ReaderSnippetGen.cs b/CapnpC.CSharp.Generator/CodeGen/ReaderSnippetGen.cs index 869acf1..8052dde 100644 --- a/CapnpC.CSharp.Generator/CodeGen/ReaderSnippetGen.cs +++ b/CapnpC.CSharp.Generator/CodeGen/ReaderSnippetGen.cs @@ -57,7 +57,7 @@ namespace CapnpC.CSharp.Generator.CodeGen ParameterList( SingletonSeparatedList( Parameter(_names.ReaderContextField.Identifier) - .WithType(Type())))) + .WithType(_names.Type())))) .WithExpressionBody( ArrowExpressionClause( ObjectCreationExpression(_names.ReaderStruct.IdentifierName) @@ -78,7 +78,7 @@ namespace CapnpC.CSharp.Generator.CodeGen SingletonSeparatedList( Parameter(_names.ContextParameter.Identifier) .WithType( - Type())))) + _names.Type())))) .WithExpressionBody( ArrowExpressionClause( ObjectCreationExpression(_names.ReaderStruct.IdentifierName) @@ -90,7 +90,7 @@ namespace CapnpC.CSharp.Generator.CodeGen { yield return FieldDeclaration( VariableDeclaration( - Type()) + _names.Type()) .AddVariables(_names.ReaderContextField.VariableDeclarator)) .AddModifiers(Readonly); @@ -100,7 +100,7 @@ namespace CapnpC.CSharp.Generator.CodeGen ParameterList( SingletonSeparatedList( Parameter(_names.ContextParameter.Identifier) - .WithType(Type())))) + .WithType(_names.Type())))) .WithBody( Block( SingletonList( @@ -122,7 +122,7 @@ namespace CapnpC.CSharp.Generator.CodeGen { yield return FieldDeclaration( VariableDeclaration( - Type()) + _names.Type()) .AddVariables(_names.ReaderContextField.VariableDeclarator)) .AddModifiers(Readonly); @@ -131,7 +131,7 @@ namespace CapnpC.CSharp.Generator.CodeGen .WithParameterList( ParameterList( SingletonSeparatedList(Parameter(_names.GroupReaderContextArg.Identifier) - .WithType(Type())))) + .WithType(_names.Type())))) .WithBody( Block( SingletonList( @@ -261,7 +261,7 @@ namespace CapnpC.CSharp.Generator.CodeGen PropertyDeclarationSyntax MakeReadPrimitiveProperty(Field field, string readName) { - return MakeReadProperty(Type(), _names.GetCodeIdentifier(field).ToString(), readName, field.BitOffset.Value, + return MakeReadProperty(_names.Type(), _names.GetCodeIdentifier(field).ToString(), readName, field.BitOffset.Value, ValueOf(field.DefaultValue.ScalarValue), null, field.DiscValue.HasValue); } @@ -278,7 +278,7 @@ namespace CapnpC.CSharp.Generator.CodeGen PropertyDeclarationSyntax MakeReadTextProperty(Field field) { - return MakeReadProperty(Type(), _names.GetCodeIdentifier(field).ToString(), + return MakeReadProperty(_names.Type(), _names.GetCodeIdentifier(field).ToString(), nameof(Capnp.DeserializerState.ReadText), (int)field.Offset, ValueOf(field.DefaultValue.ScalarValue), null, field.DiscValue.HasValue); } @@ -396,7 +396,7 @@ namespace CapnpC.CSharp.Generator.CodeGen case TypeTag.ListPointer: { - listType = Type>(); + listType = _names.Type>(); context = InvocationExpression(MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, @@ -445,14 +445,14 @@ namespace CapnpC.CSharp.Generator.CodeGen case TypeTag.AnyPointer: case TypeTag.StructPointer: { - listType = Type>(); + listType = _names.Type>(); impl = context; return; } case TypeTag.Void: { - listType = Type(); + listType = _names.Type(); impl = MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, context, diff --git a/CapnpC.CSharp.Generator/CodeGen/SyntaxHelpers.cs b/CapnpC.CSharp.Generator/CodeGen/SyntaxHelpers.cs index 56f258e..d532107 100644 --- a/CapnpC.CSharp.Generator/CodeGen/SyntaxHelpers.cs +++ b/CapnpC.CSharp.Generator/CodeGen/SyntaxHelpers.cs @@ -21,7 +21,7 @@ namespace CapnpC.CSharp.Generator.CodeGen public static readonly SyntaxToken Partial = Token(SyntaxKind.PartialKeyword); public static readonly SyntaxToken This = Token(SyntaxKind.ThisKeyword); - public static TypeSyntax Type(Type type) + public static TypeSyntax NonNullableType(Type type) { switch (0) { @@ -66,14 +66,14 @@ namespace CapnpC.CSharp.Generator.CodeGen case 0 when type.IsGenericType: return GenericName(type.Name.Substring(0, type.Name.IndexOf('`'))) - .AddTypeArgumentListArguments(type.GetGenericArguments().Select(Type).ToArray()); + .AddTypeArgumentListArguments(type.GetGenericArguments().Select(NonNullableType).ToArray()); default: return ParseTypeName(type.Name); } } - public static TypeSyntax Type() => Type(typeof(T)); + public static TypeSyntax NonNullableType() => NonNullableType(typeof(T)); public static ExpressionSyntax ValueOf(object value) { @@ -83,16 +83,16 @@ namespace CapnpC.CSharp.Generator.CodeGen return LiteralExpression(x ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression); case sbyte x: - return CastExpression(Type(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); + return CastExpression(NonNullableType(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); case byte x: - return CastExpression(Type(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); + return CastExpression(NonNullableType(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); case short x: - return CastExpression(Type(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); + return CastExpression(NonNullableType(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); case ushort x: - return CastExpression(Type(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); + return CastExpression(NonNullableType(), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x))); case int x: return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(x)); @@ -122,5 +122,14 @@ namespace CapnpC.CSharp.Generator.CodeGen throw new NotImplementedException(); } } + + public static TypeSyntax MakeNonNullableType(TypeSyntax type) + { + if (type is NullableTypeSyntax nts) + { + type = nts.ElementType; + } + return type; + } } } diff --git a/CapnpC.CSharp.Generator/CodeGen/WriterSnippetGen.cs b/CapnpC.CSharp.Generator/CodeGen/WriterSnippetGen.cs index 262b8eb..ffbd93b 100644 --- a/CapnpC.CSharp.Generator/CodeGen/WriterSnippetGen.cs +++ b/CapnpC.CSharp.Generator/CodeGen/WriterSnippetGen.cs @@ -195,7 +195,7 @@ namespace CapnpC.CSharp.Generator.CodeGen PropertyDeclarationSyntax MakePrimitiveProperty(Field field, string readName) { - return MakeProperty(Type(), null, _names.GetCodeIdentifier(field).ToString(), + return MakeProperty(_names.Type(), null, _names.GetCodeIdentifier(field).ToString(), readName, nameof(Capnp.SerializerExtensions.WriteData), field.BitOffset.Value, @@ -207,7 +207,7 @@ namespace CapnpC.CSharp.Generator.CodeGen PropertyDeclarationSyntax MakeEnumProperty(Field field, string readName) { - return MakeProperty(_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.NotRelevant), Type(), + return MakeProperty(_names.MakeTypeSyntax(field.Type, field.DeclaringType, TypeUsage.NotRelevant), _names.Type(), _names.GetCodeIdentifier(field).ToString(), readName, nameof(Capnp.SerializerExtensions.WriteData), @@ -220,7 +220,7 @@ namespace CapnpC.CSharp.Generator.CodeGen PropertyDeclarationSyntax MakeTextProperty(Field field) { - return MakeProperty(Type(), null, + return MakeProperty(_names.Type(), null, _names.GetCodeIdentifier(field).ToString(), nameof(Capnp.SerializerState.ReadText), nameof(Capnp.SerializerState.WriteText), @@ -282,7 +282,7 @@ namespace CapnpC.CSharp.Generator.CodeGen { return MakeProperty( _names.UnionDiscriminatorEnum.IdentifierName, - Type(), + _names.Type(), _names.UnionDiscriminatorProp.ToString(), nameof(Capnp.SerializerExtensions.ReadDataUShort), nameof(Capnp.SerializerExtensions.WriteData), diff --git a/CapnpC.CSharp.Generator/Model/GenFile.cs b/CapnpC.CSharp.Generator/Model/GenFile.cs index 217a760..d111956 100644 --- a/CapnpC.CSharp.Generator/Model/GenFile.cs +++ b/CapnpC.CSharp.Generator/Model/GenFile.cs @@ -11,6 +11,7 @@ namespace CapnpC.CSharp.Generator.Model public string Name { get; set; } public string[] Namespace { get; set; } + public bool NullableEnable { get; set; } = true; public IEnumerable NestedTypes { get => this.GetNestedTypes(); } public ICollection NestedDefinitions { get; } = new List(); diff --git a/MsBuildGenerationTest/MsBuildGenerationTest.csproj b/MsBuildGenerationTest/MsBuildGenerationTest.csproj index c415422..5585778 100644 --- a/MsBuildGenerationTest/MsBuildGenerationTest.csproj +++ b/MsBuildGenerationTest/MsBuildGenerationTest.csproj @@ -2,7 +2,9 @@ Exe - netcoreapp2.2 + netcoreapp3.0 + 8.0 + Enable 1.3-local Debug;Release $(Version)* diff --git a/include/csharp.capnp b/include/csharp.capnp new file mode 100644 index 0000000..67ac9a3 --- /dev/null +++ b/include/csharp.capnp @@ -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