private async Task <CSharpSyntaxNode> GetInitializerFromNameAndTypeAsync(ITypeSymbol typeSymbol, VBSyntax.ModifiedIdentifierSyntax name, CSharpSyntaxNode initializer) { if (!SyntaxTokenExtensions.IsKind(name.Nullable, SyntaxKind.None)) { if (typeSymbol.IsArrayType()) { initializer = null; } } var rankSpecifiers = await ConvertArrayRankSpecifierSyntaxesAsync(name.ArrayRankSpecifiers, name.ArrayBounds, false); if (rankSpecifiers.Count > 0) { var rankSpecifiersWithSizes = await ConvertArrayRankSpecifierSyntaxesAsync(name.ArrayRankSpecifiers, name.ArrayBounds); var arrayTypeSyntax = ((ArrayTypeSyntax)GetTypeSyntax(typeSymbol)).WithRankSpecifiers(rankSpecifiersWithSizes); if (rankSpecifiersWithSizes.SelectMany(ars => ars.Sizes).Any(e => !e.IsKind(CSSyntaxKind.OmittedArraySizeExpression))) { initializer = SyntaxFactory.ArrayCreationExpression(arrayTypeSyntax); } else if (initializer is ImplicitArrayCreationExpressionSyntax iaces && iaces.Initializer != null) { initializer = SyntaxFactory.ArrayCreationExpression(arrayTypeSyntax, iaces.Initializer); } } return(initializer); }
private async Task <CSharpSyntaxNode> GetInitializerFromNameAndType(ITypeSymbol typeSymbol, ModifiedIdentifierSyntax name, CSharpSyntaxNode initializer) { if (!SyntaxTokenExtensions.IsKind(name.Nullable, SyntaxKind.None)) { if (typeSymbol.IsArrayType()) { initializer = null; } } var rankSpecifiers = await ConvertArrayRankSpecifierSyntaxes(name.ArrayRankSpecifiers, name.ArrayBounds, false); if (rankSpecifiers.Count > 0) { var rankSpecifiersWithSizes = await ConvertArrayRankSpecifierSyntaxes(name.ArrayRankSpecifiers, name.ArrayBounds); if (!rankSpecifiersWithSizes.SelectMany(ars => ars.Sizes).OfType <OmittedArraySizeExpressionSyntax>().Any()) { var arrayTypeSyntax = (ArrayTypeSyntax)GetTypeSyntax(typeSymbol); arrayTypeSyntax = arrayTypeSyntax.WithRankSpecifiers(rankSpecifiersWithSizes); initializer = SyntaxFactory.ArrayCreationExpression(arrayTypeSyntax); } } return(initializer); }
static Dictionary <string, VariableDeclarationSyntax> SplitVariableDeclarations(VBSyntax.VariableDeclaratorSyntax declarator, VBasic.VisualBasicSyntaxVisitor <CSharpSyntaxNode> nodesVisitor, SemanticModel semanticModel) { var rawType = (TypeSyntax)declarator.AsClause?.TypeSwitch( (VBSyntax.SimpleAsClauseSyntax c) => c.Type, (VBSyntax.AsNewClauseSyntax c) => VBasic.SyntaxExtensions.Type(c.NewExpression), _ => { throw new NotImplementedException($"{_.GetType().FullName} not implemented!"); } )?.Accept(nodesVisitor) ?? SyntaxFactory.ParseTypeName("var"); var initializer = (ExpressionSyntax)declarator.AsClause?.TypeSwitch( (VBSyntax.SimpleAsClauseSyntax _) => declarator.Initializer?.Value, (VBSyntax.AsNewClauseSyntax c) => c.NewExpression )?.Accept(nodesVisitor) ?? (ExpressionSyntax)declarator.Initializer?.Value.Accept(nodesVisitor); var newDecls = new Dictionary <string, VariableDeclarationSyntax>(); foreach (var name in declarator.Names) { var type = rawType; if (!SyntaxTokenExtensions.IsKind(name.Nullable, VBasic.SyntaxKind.None)) { if (type is ArrayTypeSyntax) { type = ((ArrayTypeSyntax)type).WithElementType( SyntaxFactory.NullableType(((ArrayTypeSyntax)type).ElementType)); initializer = null; } else { type = SyntaxFactory.NullableType(type); } } var rankSpecifiers = NodesVisitor.ConvertArrayRankSpecifierSyntaxes(name.ArrayRankSpecifiers, name.ArrayBounds, nodesVisitor, semanticModel, false); if (rankSpecifiers.Count > 0) { var rankSpecifiersWithSizes = NodesVisitor.ConvertArrayRankSpecifierSyntaxes(name.ArrayRankSpecifiers, name.ArrayBounds, nodesVisitor, semanticModel); if (!rankSpecifiersWithSizes.SelectMany(ars => ars.Sizes).OfType <OmittedArraySizeExpressionSyntax>().Any()) { initializer = SyntaxFactory.ArrayCreationExpression( SyntaxFactory.ArrayType(type, rankSpecifiersWithSizes)); } type = SyntaxFactory.ArrayType(type, rankSpecifiers); } VariableDeclarationSyntax decl; var v = SyntaxFactory.VariableDeclarator(ConvertIdentifier(name.Identifier, semanticModel), null, initializer == null ? null : SyntaxFactory.EqualsValueClause(initializer)); string k = type.ToString(); if (newDecls.TryGetValue(k, out decl)) { newDecls[k] = decl.AddVariables(v); } else { newDecls[k] = SyntaxFactory.VariableDeclaration(type, SyntaxFactory.SingletonSeparatedList(v)); } } return(newDecls); }
public static ArrowExpressionClauseSyntax GenerateSpanNameValues(MemberDeclarationMeta memberdecl) //=> { byte, byte, byte, byte} { SeparatedSyntaxList <ExpressionSyntax> ArrayInitExpr(MemberDeclarationMeta memberdecl) { SeparatedSyntaxList <ExpressionSyntax> expr = new SeparatedSyntaxList <ExpressionSyntax>(); foreach (var byteItem in Encoding.UTF8.GetBytes(memberdecl.StringFieldNameAlias)) { expr = expr.Add(Basics.NumberLiteral(byteItem)); } return(expr); } ArrayRankSpecifierSyntax ArrayRank(MemberDeclarationMeta memberdecl) { return(SF.ArrayRankSpecifier().AddSizes(Basics.NumberLiteral(memberdecl.StringFieldNameAlias.Length))); } return(SF.ArrowExpressionClause( SF.ArrayCreationExpression( SF.ArrayType( SF.PredefinedType(SF.Token(SyntaxKind.ByteKeyword)), SF.SingletonList <ArrayRankSpecifierSyntax>(ArrayRank(memberdecl))), SF.InitializerExpression(SyntaxKind.ArrayInitializerExpression, ArrayInitExpr(memberdecl)) ) )); }
private static ExpressionSyntax EmptyCharArrayExpression() { var literalExpressionSyntax = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(0)); var arrayRankSpecifierSyntax = ArrayRankSpecifier(literalExpressionSyntax); var arrayTypeSyntax = CharArrayType().WithRankSpecifiers(arrayRankSpecifierSyntax); return(SyntaxFactory.ArrayCreationExpression(arrayTypeSyntax)); }
private ExpressionStatementSyntax CreateNewArrayAssignment(VBSyntax.ExpressionSyntax vbArrayExpression, ExpressionSyntax csArrayExpression, List <ExpressionSyntax> convertedBounds, int nodeSpanStart) { var arrayRankSpecifierSyntax = SyntaxFactory.ArrayRankSpecifier(SyntaxFactory.SeparatedList(convertedBounds)); var convertedType = (IArrayTypeSymbol)_semanticModel.GetTypeInfo(vbArrayExpression).ConvertedType; var typeSyntax = GetTypeSyntaxFromTypeSymbol(convertedType.ElementType, nodeSpanStart); var arrayCreation = SyntaxFactory.ArrayCreationExpression(SyntaxFactory.ArrayType(typeSyntax, SyntaxFactory.SingletonList(arrayRankSpecifierSyntax))); var assignmentExpressionSyntax = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, csArrayExpression, arrayCreation); var newArrayAssignment = SyntaxFactory.ExpressionStatement(assignmentExpressionSyntax); return(newArrayAssignment); }
/// <summary> /// Returns syntax for individual switch cases within the <see cref="IEventInvoker{T}.GetArgumentTypes"/> method. /// </summary> /// <param name="methodDescription"> /// The method description. /// </param> /// <returns> /// Syntax for individual switch cases within the <see cref="IEventInvoker{T}.GetArgumentTypes"/> method. /// </returns> private static StatementSyntax GenerateGetTypeArgumentsSwitchBlock(ActorMethodDescription methodDescription) { var method = methodDescription.MethodInfo; var parameters = method.GetParameters().ToList(); var argumentTypes = parameters.Select(p => SF.TypeOfExpression(p.ParameterType.GetTypeSyntax())) .Cast <ExpressionSyntax>() .ToArray(); var argumentTypeArray = SF.ArrayCreationExpression(typeof(Type).GetArrayTypeSyntax()) .WithInitializer( SF.InitializerExpression(SyntaxKind.ArrayInitializerExpression).AddExpressions(argumentTypes)); return(SF.ReturnStatement(argumentTypeArray)); }
ArgumentListSyntax GetArgumentListSyntax() { var arguments = GetArgumentExpressions().Select(e => SF.Argument(e)); return(SF.ArgumentList(SF.SeparatedList(arguments))); IEnumerable <ExpressionSyntax> GetArgumentExpressions() { if (Method.IsStatic) { yield return(SF.TypeOfExpression(Symbols.GetNameSyntax(Type))); } yield return(CreateArgumentsArray()); } ArrayCreationExpressionSyntax CreateArgumentsArray() { return(SF.ArrayCreationExpression( SF.Token(SyntaxKind.NewKeyword), SF.ArrayType(SF.ParseTypeName("object[]")), SF.InitializerExpression( SyntaxKind.ArrayInitializerExpression, SF.Token(SyntaxKind.OpenBraceToken), SF.SeparatedList(GetArguments()), SF.Token(SyntaxKind.CloseBraceToken) ) )); IEnumerable <ExpressionSyntax> GetArguments() { if (Method.Parameters == null) { yield break; } foreach (Parameter parameter in Method.Parameters) { yield return(Symbols.GetNameSyntax(parameter)); } } } }
private (TypeSyntax, ExpressionSyntax) AdjustFromName(TypeSyntax rawType, ModifiedIdentifierSyntax name, ExpressionSyntax initializer) { var type = rawType; if (!SyntaxTokenExtensions.IsKind(name.Nullable, SyntaxKind.None)) { if (type is ArrayTypeSyntax) { type = ((ArrayTypeSyntax)type).WithElementType( SyntaxFactory.NullableType(((ArrayTypeSyntax)type).ElementType)); initializer = null; } else { type = SyntaxFactory.NullableType(type); } } var rankSpecifiers = ConvertArrayRankSpecifierSyntaxes(name.ArrayRankSpecifiers, name.ArrayBounds, false); if (rankSpecifiers.Count > 0) { var rankSpecifiersWithSizes = ConvertArrayRankSpecifierSyntaxes(name.ArrayRankSpecifiers, name.ArrayBounds); if (!rankSpecifiersWithSizes.SelectMany(ars => ars.Sizes).OfType <OmittedArraySizeExpressionSyntax>().Any()) { initializer = SyntaxFactory.ArrayCreationExpression( SyntaxFactory.ArrayType(type, rankSpecifiersWithSizes)); } type = SyntaxFactory.ArrayType(type, rankSpecifiers); } return(type, initializer); }
/// <summary> /// Generates invoker methods. /// </summary> /// <param name="grainType">The grain type.</param> /// <param name="onEncounteredType"> /// The callback which is invoked when a type is encountered. /// </param> /// <returns>Invoker methods for the provided grain type.</returns> private static MemberDeclarationSyntax[] GenerateInvokeMethods(Type grainType, Action <Type> onEncounteredType) { var baseReference = SF.BaseExpression(); var methods = GrainInterfaceUtils.GetMethods(grainType); var members = new List <MemberDeclarationSyntax>(); foreach (var method in methods) { onEncounteredType(method.ReturnType); var methodId = GrainInterfaceUtils.ComputeMethodId(method); var methodIdArgument = SF.Argument(SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(methodId))); // Construct a new object array from all method arguments. var parameters = method.GetParameters(); var body = new List <StatementSyntax>(); foreach (var parameter in parameters) { onEncounteredType(parameter.ParameterType); if (typeof(IGrainObserver).GetTypeInfo().IsAssignableFrom(parameter.ParameterType)) { body.Add( SF.ExpressionStatement( CheckGrainObserverParamInternalExpression.Invoke() .AddArgumentListArguments(SF.Argument(parameter.Name.ToIdentifierName())))); } } // Get the parameters argument value. ExpressionSyntax args; if (parameters.Length == 0) { args = SF.LiteralExpression(SyntaxKind.NullLiteralExpression); } else { args = SF.ArrayCreationExpression(typeof(object).GetArrayTypeSyntax()) .WithInitializer( SF.InitializerExpression(SyntaxKind.ArrayInitializerExpression) .AddExpressions(parameters.Select(GetParameterForInvocation).ToArray())); } var options = GetInvokeOptions(method); // Construct the invocation call. if (method.ReturnType == typeof(void)) { var invocation = SF.InvocationExpression(baseReference.Member("InvokeOneWayMethod")) .AddArgumentListArguments(methodIdArgument) .AddArgumentListArguments(SF.Argument(args)); if (options != null) { invocation = invocation.AddArgumentListArguments(options); } body.Add(SF.ExpressionStatement(invocation)); } else { var returnType = method.ReturnType == typeof(Task) ? typeof(object) : method.ReturnType.GenericTypeArguments[0]; var invocation = SF.InvocationExpression(baseReference.Member("InvokeMethodAsync", returnType)) .AddArgumentListArguments(methodIdArgument) .AddArgumentListArguments(SF.Argument(args)); if (options != null) { invocation = invocation.AddArgumentListArguments(options); } body.Add(SF.ReturnStatement(invocation)); } members.Add(method.GetDeclarationSyntax().AddBodyStatements(body.ToArray())); } return(members.ToArray()); }
/// <summary> /// Generates invoker methods. /// </summary> /// <param name="grainType">The grain type.</param> /// <param name="onEncounteredType"> /// The callback which is invoked when a type is encountered. /// </param> /// <returns>Invoker methods for the provided grain type.</returns> private static MemberDeclarationSyntax[] GenerateInvokeMethods(Type grainType, Action <Type> onEncounteredType) { var baseReference = SF.BaseExpression(); var methods = GrainInterfaceUtils.GetMethods(grainType); var members = new List <MemberDeclarationSyntax>(); foreach (var method in methods) { onEncounteredType(method.ReturnType); var methodId = GrainInterfaceUtils.ComputeMethodId(method); var methodIdArgument = SF.Argument(SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(methodId))); // Construct a new object array from all method arguments. var parameters = method.GetParameters(); var body = new List <StatementSyntax>(); foreach (var parameter in parameters) { onEncounteredType(parameter.ParameterType); if (typeof(IGrainObserver).IsAssignableFrom(parameter.ParameterType)) { body.Add( SF.ExpressionStatement( CheckGrainObserverParamInternalExpression.Invoke() .AddArgumentListArguments(SF.Argument(parameter.Name.ToIdentifierName())))); } } // Get the parameters argument value. ExpressionSyntax args; if (method.IsGenericMethodDefinition) { // Create an arguments array which includes the method's type parameters followed by the method's parameter list. var allParameters = new List <ExpressionSyntax>(); foreach (var typeParameter in method.GetGenericArguments()) { allParameters.Add(SF.TypeOfExpression(typeParameter.GetTypeSyntax())); } allParameters.AddRange(parameters.Select(GetParameterForInvocation)); args = SF.ArrayCreationExpression(typeof(object).GetArrayTypeSyntax()) .WithInitializer( SF.InitializerExpression(SyntaxKind.ArrayInitializerExpression) .AddExpressions(allParameters.ToArray())); } else if (parameters.Length == 0) { args = SF.LiteralExpression(SyntaxKind.NullLiteralExpression); } else { args = SF.ArrayCreationExpression(typeof(object).GetArrayTypeSyntax()) .WithInitializer( SF.InitializerExpression(SyntaxKind.ArrayInitializerExpression) .AddExpressions(parameters.Select(GetParameterForInvocation).ToArray())); } var options = GetInvokeOptions(method); // Construct the invocation call. var isOneWayTask = method.GetCustomAttribute <OneWayAttribute>() != null; if (method.ReturnType == typeof(void) || isOneWayTask) { var invocation = SF.InvocationExpression(baseReference.Member("InvokeOneWayMethod")) .AddArgumentListArguments(methodIdArgument) .AddArgumentListArguments(SF.Argument(args)); if (options != null) { invocation = invocation.AddArgumentListArguments(options); } body.Add(SF.ExpressionStatement(invocation)); if (isOneWayTask) { if (method.ReturnType != typeof(Task)) { throw new CodeGenerationException( $"Method {grainType.GetParseableName()}.{method.Name} is marked with [{nameof(OneWayAttribute)}], " + $"but has a return type which is not assignable from {typeof(Task)}"); } var done = typeof(Task).GetNameSyntax(true).Member((object _) => Task.CompletedTask); body.Add(SF.ReturnStatement(done)); } } else { var returnType = method.ReturnType == typeof(Task) ? typeof(object) : method.ReturnType.GenericTypeArguments[0]; var invocation = SF.InvocationExpression(baseReference.Member("InvokeMethodAsync", returnType)) .AddArgumentListArguments(methodIdArgument) .AddArgumentListArguments(SF.Argument(args)); if (options != null) { invocation = invocation.AddArgumentListArguments(options); } ExpressionSyntax returnContent = invocation; if (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition().FullName == "System.Threading.Tasks.ValueTask`1") { // Wrapping invocation expression with initialization of ValueTask (e.g. new ValueTask<int>(base.InvokeMethod())) returnContent = SF.ObjectCreationExpression(method.ReturnType.GetTypeSyntax()) .AddArgumentListArguments(SF.Argument(SF.ExpressionStatement(invocation).Expression)); } body.Add(SF.ReturnStatement(returnContent)); } members.Add(method.GetDeclarationSyntax().AddBodyStatements(body.ToArray())); } return(members.ToArray()); }
/// <summary> /// Create a class that implements <see cref="ICommand"/>. /// /// The implementation will execute the given <see cref="method"/>. /// </summary> /// <param name="id">The unique identifier of the command for <see cref="ICommand.Id"/>.</param> /// <param name="className">The new class name.</param> /// <param name="moduleType">The type that contains the <see cref="method"/>.</param> /// <param name="method">The method that should be executed when <see cref="ICommand.ExecuteAsync"/> is called.</param> /// <returns>The <see cref="ClassDeclarationSyntax"/>.</returns> private ClassDeclarationSyntax CreateCommandClass( string id, IReadOnlyList <string> aliases, string className, Type moduleType, MethodInfo method) { var permission = ModuleUtils.GetPermissionName(moduleType, method); var moduleName = ModuleUtils.GetModuleName(moduleType); var attr = method.GetCustomAttribute <CommandAttribute>(); var guildOnly = attr.GuildOnly; var permissionGroup = attr.PermissionGroup.ToString(); return(S.ClassDeclaration(className) .AddBaseListTypes(S.SimpleBaseType(CommandType)) .AddMembers( // ICommand.Id S.PropertyDeclaration(StringType, nameof(ICommand.Id)) .AddAccessorListAccessors( S.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .AddBodyStatements(S.ReturnStatement(S.LiteralExpression(SyntaxKind.StringLiteralExpression, S.Literal(id)))) .WithSemicolonToken(S.Token(SyntaxKind.SemicolonToken)) ) .AddModifiers(S.Token(SyntaxKind.PublicKeyword)), // ICommand.Aliases S.PropertyDeclaration(ReadOnlyStringList, nameof(ICommand.Aliases)) .AddAccessorListAccessors( S.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .AddBodyStatements(S.ReturnStatement(S.ArrayCreationExpression( S.ArrayType(StringType) .WithRankSpecifiers(S.SingletonList(S.ArrayRankSpecifier(S.SingletonSeparatedList <ExpressionSyntax>(S.OmittedArraySizeExpression())))), S.InitializerExpression(SyntaxKind.ArrayInitializerExpression, new SeparatedSyntaxList <ExpressionSyntax>() .AddRange(aliases.Select(s => S.LiteralExpression(SyntaxKind.StringLiteralExpression, S.Literal(s)))))))) .WithSemicolonToken(S.Token(SyntaxKind.SemicolonToken)) ) .AddModifiers(S.Token(SyntaxKind.PublicKeyword)), // ICommand.Module S.PropertyDeclaration(StringType, nameof(ICommand.Module)) .AddAccessorListAccessors( S.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .AddBodyStatements(S.ReturnStatement(S.LiteralExpression(SyntaxKind.StringLiteralExpression, S.Literal(moduleName)))) .WithSemicolonToken(S.Token(SyntaxKind.SemicolonToken)) ) .AddModifiers(S.Token(SyntaxKind.PublicKeyword)), // ICommand.Permission S.PropertyDeclaration(StringType, nameof(ICommand.Permission)) .AddAccessorListAccessors( S.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .AddBodyStatements(S.ReturnStatement(S.LiteralExpression(SyntaxKind.StringLiteralExpression, S.Literal(permission)))) .WithSemicolonToken(S.Token(SyntaxKind.SemicolonToken)) ) .AddModifiers(S.Token(SyntaxKind.PublicKeyword)), // ICommand.PermissionGroup S.PropertyDeclaration(S.ParseName(nameof(PermissionGroup)), nameof(ICommand.PermissionGroup)) .AddAccessorListAccessors( S.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .AddBodyStatements(S.ReturnStatement(S.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, S.IdentifierName(nameof(PermissionGroup)), S.IdentifierName(permissionGroup)))) .WithSemicolonToken(S.Token(SyntaxKind.SemicolonToken)) ) .AddModifiers(S.Token(SyntaxKind.PublicKeyword)), // ICommand.GuildOnly S.PropertyDeclaration(BoolType, nameof(ICommand.GuildOnly)) .AddAccessorListAccessors( S.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .AddBodyStatements(S.ReturnStatement(S.LiteralExpression(guildOnly ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression))) .WithSemicolonToken(S.Token(SyntaxKind.SemicolonToken)) ) .AddModifiers(S.Token(SyntaxKind.PublicKeyword)), // ICommand.ExecuteAsync S.MethodDeclaration(TaskType, nameof(ICommand.ExecuteAsync)) .AddModifiers(S.Token(SyntaxKind.PublicKeyword), S.Token(SyntaxKind.AsyncKeyword)) .AddParameterListParameters(Parameter(ArgumentContext, MessageContextType)) .AddBodyStatements( S.ExpressionStatement(InvokeCommand(moduleType, method)) ) )); }
IEnumerable <MemberDeclarationSyntax> CreateConstructors() { SyntaxToken typeName = Symbols.GetNameSyntaxToken(Type); if (Type.Initializer != null) { yield return(SF.ConstructorDeclaration ( SF.List <AttributeListSyntax>(), SF.TokenList(SF.Token( Type.IsAbstract || Type.Initializer.IsProtected ? SyntaxKind.ProtectedKeyword : SyntaxKind.PublicKeyword )), typeName, Type.Initializer.GetParameterListSyntax(Namespaces, Symbols), SF.ConstructorInitializer ( SyntaxKind.BaseConstructorInitializer, SF.ArgumentList( SF.SeparatedList(new[] { SF.Argument( SF.ObjectCreationExpression( SF.Token(SyntaxKind.NewKeyword), SF.ParseTypeName("DeputyProps"), SF.ArgumentList(SF.SeparatedList( new[] { GetBaseArgument() } )), null ) ) }) ) ), SF.Block(), null )); } yield return(SF.ConstructorDeclaration ( SF.List <AttributeListSyntax>(), SF.TokenList(SF.Token(SyntaxKind.ProtectedKeyword)), typeName, SF.ParseParameterList("(ByRefValue reference)"), SF.ConstructorInitializer ( SyntaxKind.BaseConstructorInitializer, SF.ParseArgumentList("(reference)") ), SF.Block(), null )); // This constructor allows child classes to supply their own parameter lists. It is always protected. yield return(SF.ConstructorDeclaration ( SF.List <AttributeListSyntax>(), SF.TokenList(SF.Token(SyntaxKind.ProtectedKeyword)), typeName, SF.ParseParameterList("(DeputyProps props)"), SF.ConstructorInitializer ( SyntaxKind.BaseConstructorInitializer, SF.ParseArgumentList("(props)") ), SF.Block(), null )); ArgumentSyntax GetBaseArgument() { var deputyArguments = (Type.Initializer.Parameters ?? Enumerable.Empty <Parameter>()) .Select(p => Symbols.GetNameSyntaxToken(p)) .Select(i => SF.IdentifierName(i)); // In C#, arrays of reference types are covariant. Because of this, passing a string[] // to a method that takes `params object[] args` will interperet the string array *as* // args, rather than as args' first element. To workaround with, we remove the params // keyword from DeputyBase's constructor, and always explicitly create an array of // objects when calling it. return(SF.Argument( SF.ArrayCreationExpression( SF.Token(SyntaxKind.NewKeyword), SF.ArrayType(SF.ParseTypeName("object[]")), SF.InitializerExpression( SyntaxKind.ArrayInitializerExpression, SF.SeparatedList <ExpressionSyntax>(deputyArguments) ) ) )); } }