SharpGen/Generator/PropertyCodeGenerator.cs (168 lines of code) (raw):

using System.Collections.Generic; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using SharpGen.Model; using SharpGen.Transform; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace SharpGen.Generator { internal sealed class PropertyCodeGenerator : MemberCodeGeneratorBase<CsProperty> { public override IEnumerable<MemberDeclarationSyntax> GenerateCode(CsProperty csElement) { var accessors = new List<AccessorDeclarationSyntax>(); if (csElement.IsPropertyParam) { if (csElement.Getter != null) { if (csElement.IsPersistent) { if (csElement.IsValueType) { accessors.Add(AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithBody(Block( IfStatement( BinaryExpression(SyntaxKind.EqualsExpression, IdentifierName($"{csElement.Name}__"), LiteralExpression(SyntaxKind.NullLiteralExpression)), Block( LocalDeclarationStatement( VariableDeclaration( ParseTypeName(csElement.PublicType.QualifiedName)) .WithVariables( SingletonSeparatedList( VariableDeclarator(Identifier("temp"))))), ExpressionStatement( InvocationExpression(IdentifierName(csElement.Getter.Name)) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument(IdentifierName("temp")) .WithRefOrOutKeyword( Token(SyntaxKind.OutKeyword)))))), ExpressionStatement( AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName($"{csElement.Name}__"), IdentifierName("temp"))))), ReturnStatement( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName($"{csElement.Name}__")), IdentifierName("Value"))) ))); } else { accessors.Add(AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithBody(Block( IfStatement(BinaryExpression(SyntaxKind.EqualsExpression, MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName($"{csElement.Name}__")), LiteralExpression(SyntaxKind.NullLiteralExpression)), ExpressionStatement( InvocationExpression(IdentifierName(csElement.Getter.Name)) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument(IdentifierName($"{csElement.Name}__")) .WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword))))))), ReturnStatement( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName($"{csElement.Name}__"))) ))); } } else { accessors.Add(AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithBody(Block( ExpressionStatement( InvocationExpression(ParseExpression(csElement.Getter.Name)) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( DeclarationExpression( IdentifierName("var"), SingleVariableDesignation( Identifier("__output__")))) .WithRefOrOutKeyword( Token(SyntaxKind.OutKeyword)))))), ReturnStatement(IdentifierName("__output__"))))); } } } else { if (csElement.Getter != null) { if (csElement.IsPersistent) { ExpressionSyntax initializer = BinaryExpression(SyntaxKind.CoalesceExpression, IdentifierName($"{csElement.Name}__"), ParenthesizedExpression( AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName($"{csElement.Name}__"), InvocationExpression(ParseExpression(csElement.Getter.Name))))); if (csElement.IsValueType) { initializer = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ParenthesizedExpression(initializer), IdentifierName("Value")); } accessors.Add(AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithExpressionBody(ArrowExpressionClause(initializer)) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))); } else { accessors.Add(AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithExpressionBody(ArrowExpressionClause( InvocationExpression(ParseExpression(csElement.Getter.Name)))) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))); } } } if (csElement.Setter != null) { var paramByRef = GetMarshaller(csElement.Setter.Parameters[0]) .GenerateManagedArgument(csElement.Setter.Parameters[0]) .RefOrOutKeyword.Kind() == SyntaxKind.RefKeyword; accessors.Add(AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) .WithExpressionBody(ArrowExpressionClause( InvocationExpression(ParseExpression(csElement.Setter.Name)) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument(IdentifierName("value")) .WithRefOrOutKeyword( paramByRef ? Token(SyntaxKind.RefKeyword) : default)))))) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))); } yield return AddDocumentationTrivia( PropertyDeclaration(ParseTypeName(csElement.PublicType.QualifiedName), Identifier(csElement.Name)) .WithModifiers(csElement.VisibilityTokenList) .WithAccessorList(AccessorList(List(accessors))), csElement ); if (csElement.IsPersistent) { yield return FieldDeclaration( VariableDeclaration( csElement.IsValueType ? NullableType(ParseTypeName(csElement.PublicType.QualifiedName)) : ParseTypeName(csElement.PublicType.QualifiedName) ) .WithVariables(SingletonSeparatedList(VariableDeclarator(Identifier($"{csElement.Name}__"))))) .WithModifiers(TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.InternalKeyword))); } } public PropertyCodeGenerator(Ioc ioc) : base(ioc) { } } }