private static async Task <Document> RefactorAsync(
            Document document,
            ParameterSyntax parameter,
            ParameterListSyntax parameterList,
            CancellationToken cancellationToken)
        {
            SyntaxNode oldRoot = await document.GetSyntaxRootAsync(cancellationToken);

            SeparatedSyntaxList <ParameterSyntax> parameters = parameterList.Parameters;

            int index = parameters.IndexOf(parameter);

            ParameterSyntax nextParameter = parameters[index + 1]
                                            .WithTriviaFrom(parameter);

            parameters = parameters
                         .Replace(parameter, nextParameter);

            parameters = parameters
                         .Replace(parameters[index + 1], parameter.WithTriviaFrom(nextParameter));

            ParameterListSyntax newNode = parameterList.WithParameters(parameters);

            SyntaxNode newRoot = oldRoot.ReplaceNode(parameterList, newNode);

            return(document.WithSyntaxRoot(newRoot));
        }
            public override SyntaxNode VisitParameterList(ParameterListSyntax node)
            {
                ParameterListSyntax processedNode = (ParameterListSyntax)base.VisitParameterList(node);

                if (node.Equals(this.parameterList))
                {
                    // Get the lowest index on ParameterList of compressed Parameters
                    // Considers:
                    // void foo(int a, >int b, int c<, int d) -> void foo(int a, ParameterObject o, int d)

                    int order = this.parameters.Min(n => this.parameterList.Parameters.IndexOf(n));

                    // Create new parameter declaration
                    // TODO: hard-coded type name!
                    ParameterSyntax newParameter = Syntax.Parameter(Syntax.Identifier(this.parameterObjectName))
                                                   .WithType(Syntax.ParseTypeName("ParameterObject"))
                                                   .WithAdditionalAnnotations(CodeAnnotations.Formatting);

                    // Insert new parameter's declaration to the list
                    ParameterListSyntax newParameterList = processedNode.WithParameters(processedNode.Parameters.Insert(order, newParameter));

                    return(newParameterList);
                }

                return(processedNode);
            }
Exemple #3
0
            public override SyntaxNode VisitParameterList(ParameterListSyntax node)
            {
                if (node.Parent?.Equals(constructorDeclaration) == true && parameterToRemove != null)
                {
                    var pl = constructorDeclaration.ParameterList;
                    return(node.WithParameters(pl.Parameters.Remove(parameterToRemove)));
                }

                return(base.VisitParameterList(node));
            }
        private async Task <CSharpSyntaxNode> ConvertToFunctionDeclarationOrNull(VBSyntax.LambdaExpressionSyntax vbNode,
                                                                                 ParameterListSyntax param, BlockSyntax block,
                                                                                 ArrowExpressionClauseSyntax arrow)
        {
            if (!(_semanticModel.GetOperation(vbNode) is IAnonymousFunctionOperation anonFuncOp))
            {
                return(null);
            }

            var potentialAncestorDeclarationOperation = anonFuncOp.GetParentIgnoringConversions();
            // Could do: See if we can improve upon returning "object" for pretty much everything (which is what the symbols say)
            // I believe that in general, special VB functions such as MultiplyObject are designed to work the same as integer when given two integers for example.
            // If all callers currently pass an integer, perhaps it'd be more idiomatic in C# to specify "int", than to have Operators
            var paramsWithTypes = anonFuncOp.Symbol.Parameters.Select(p => CommonConversions.CsSyntaxGenerator.ParameterDeclaration(p));

            var paramListWithTypes = param.WithParameters(SyntaxFactory.SeparatedList(paramsWithTypes));

            if (potentialAncestorDeclarationOperation is IFieldInitializerOperation fieldInit)
            {
                var fieldSymbol = fieldInit.InitializedFields.Single();
                if (fieldSymbol.GetResultantVisibility() != SymbolVisibility.Public && !fieldSymbol.Type.IsDelegateReferencableByName() && await _solution.IsNeverWritten(fieldSymbol))
                {
                    return(CreateMethodDeclaration(anonFuncOp, fieldSymbol, block, arrow));
                }
            }

            if (potentialAncestorDeclarationOperation is IVariableInitializerOperation vio)
            {
                if (vio.GetParentIgnoringConversions() is IVariableDeclarationGroupOperation go)
                {
                    potentialAncestorDeclarationOperation = go.Declarations.First(d => d.Syntax.FullSpan.Contains(vbNode.FullSpan));
                }
                else
                {
                    potentialAncestorDeclarationOperation = vio.Parent;
                }

                if (potentialAncestorDeclarationOperation is IVariableDeclarationOperation variableDeclaration)
                {
                    var variableDeclaratorOperation = variableDeclaration.Declarators.Single();
                    if (!variableDeclaratorOperation.Symbol.Type.IsDelegateReferencableByName() &&
                        await _solution.IsNeverWritten(variableDeclaratorOperation.Symbol))
                    {
                        //Should do: Check no (other) write usages exist: SymbolFinder.FindReferencesAsync + checking if they're an assignment LHS or out parameter
                        return(CreateLocalFunction(anonFuncOp, variableDeclaratorOperation, paramListWithTypes, block,
                                                   arrow));
                    }
                }
            }

            return(null);
        }
        private ParameterListSyntax ToNullableParameter(ParameterListSyntax parameterListSyntax, string parameterName)
        {
            var parameter = parameterListSyntax.Parameters.FirstOrDefault(param => param.Identifier.ToString() == parameterName);

            if (parameter == null)
            {
                return(parameterListSyntax);
            }

            var nullableParameter = parameter.WithType(NullUtilities.ToNullable(parameter.Type !));

            return(parameterListSyntax.WithParameters(parameterListSyntax.Parameters.Replace(parameter, nullableParameter)));
        }
        public static Task <Document> RefactorAsync(
            Document document,
            ParenthesizedLambdaExpressionSyntax parenthesizedLambda,
            MemberDeclarationSyntax memberDeclaration,
            TypeDeclarationSyntax typeDeclaration,
            string methodName,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            methodName = NameGenerator.Default.EnsureUniqueLocalName(methodName, semanticModel, parenthesizedLambda.SpanStart, cancellationToken: cancellationToken);

            MemberDeclarationSyntax newMemberDeclaration = memberDeclaration.ReplaceNode(parenthesizedLambda, IdentifierName(methodName).WithTriviaFrom(parenthesizedLambda));

            IMethodSymbol lambdaSymbol = semanticModel.GetMethodSymbol(parenthesizedLambda, cancellationToken);

            ParameterListSyntax parameterList = parenthesizedLambda.ParameterList;

            SeparatedSyntaxList <ParameterSyntax> parameters = parameterList.Parameters;

            ImmutableArray <IParameterSymbol> parameterSymbols = lambdaSymbol.Parameters;

            parameters = parameters
                         .ReplaceAt(0, AddTypeIfMissing(parameters[0], parameterSymbols[0]))
                         .ReplaceAt(1, AddTypeIfMissing(parameters[1], parameterSymbols[1]));

            cancellationToken.ThrowIfCancellationRequested();

            MethodDeclarationSyntax newMethodDeclaration = MethodDeclaration(
                (SyntaxInfo.ModifierListInfo(memberDeclaration).IsStatic) ? Modifiers.Private_Static() : Modifiers.Private(),
                VoidType(),
                Identifier(methodName).WithRenameAnnotation(),
                parameterList.WithParameters(parameters),
                CreateMethodBody(parenthesizedLambda.Body))
                                                           .WithFormatterAnnotation();

            SyntaxList <MemberDeclarationSyntax> newMembers = typeDeclaration.Members.Replace(memberDeclaration, newMemberDeclaration);

            newMembers = MemberDeclarationInserter.Default.Insert(newMembers, newMethodDeclaration);

            return(document.ReplaceNodeAsync(typeDeclaration, typeDeclaration.WithMembers(newMembers), cancellationToken));
Exemple #7
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddDocumentationComment) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveParametersFromStaticConstructor) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveMemberDeclaration) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RenameDestructorToMatchClassName) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RenameTupleElement))
            {
                return;
            }

            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.MissingXmlCommentForPubliclyVisibleTypeOrMember:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddDocumentationComment))
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Add documentation comment",
                        cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, false, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);

                    CodeAction codeAction2 = CodeAction.Create(
                        "Add documentation comment (copy from base if available)",
                        cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, true, cancellationToken),
                        GetEquivalenceKey(diagnostic, "CopyFromBaseIfAvailable"));

                    context.RegisterCodeFix(codeAction2, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.MethodReturnTypeMustMatchOverriddenMethodReturnType:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                    ITypeSymbol typeSymbol = methodSymbol.OverriddenMethod.ReturnType;

                    CodeFixRegistrator.ChangeMemberDeclarationType(context, diagnostic, memberDeclaration, typeSymbol, semanticModel);

                    break;
                }

                case CompilerDiagnosticIdentifiers.PartialMethodsMustHaveVoidReturnType:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    var methodDeclaration = (MethodDeclarationSyntax)memberDeclaration;

                    MethodDeclarationSyntax otherPart = semanticModel.GetOtherPart(methodDeclaration, context.CancellationToken);

                    if (otherPart == null)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Change return type to 'void'",
                        cancellationToken =>
                        {
                            return(context.Document.Solution().ReplaceNodesAsync(
                                       new MethodDeclarationSyntax[] { methodDeclaration, otherPart },
                                       (node, _) => node.WithReturnType(CSharpFactory.VoidType().WithTriviaFrom(node.ReturnType)),
                                       cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.MemberTypeMustMatchOverriddenMemberType:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ITypeSymbol typeSymbol = null;

                    switch (memberDeclaration.Kind())
                    {
                    case SyntaxKind.PropertyDeclaration:
                    case SyntaxKind.IndexerDeclaration:
                    {
                        var propertySymbol = (IPropertySymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                        typeSymbol = propertySymbol.OverriddenProperty.Type;
                        break;
                    }

                    case SyntaxKind.EventDeclaration:
                    {
                        var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                        typeSymbol = eventSymbol.OverriddenEvent.Type;
                        break;
                    }

                    case SyntaxKind.EventFieldDeclaration:
                    {
                        VariableDeclaratorSyntax declarator = ((EventFieldDeclarationSyntax)memberDeclaration).Declaration.Variables.First();

                        var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(declarator, context.CancellationToken);

                        typeSymbol = eventSymbol.OverriddenEvent.Type;
                        break;
                    }
                    }

                    CodeFixRegistrator.ChangeMemberDeclarationType(context, diagnostic, memberDeclaration, typeSymbol, semanticModel);

                    break;
                }

                case CompilerDiagnosticIdentifiers.MissingPartialModifier:
                case CompilerDiagnosticIdentifiers.PartialMethodMustBeDeclaredInPartialClassOrPartialStruct:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier))
                    {
                        break;
                    }

                    SyntaxNode node = null;

                    switch (memberDeclaration.Kind())
                    {
                    case SyntaxKind.MethodDeclaration:
                    {
                        if (memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration))
                        {
                            node = memberDeclaration.Parent;
                        }

                        break;
                    }

                    case SyntaxKind.ClassDeclaration:
                    case SyntaxKind.StructDeclaration:
                    case SyntaxKind.InterfaceDeclaration:
                    {
                        node = memberDeclaration;
                        break;
                    }
                    }

                    Debug.Assert(node != null, memberDeclaration.ToString());

                    if (node == null)
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.PartialKeyword);
                    break;
                }

                case CompilerDiagnosticIdentifiers.MemberIsAbstractButItIsContainedInNonAbstractClass:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract))
                    {
                        break;
                    }

                    if (!memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration))
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.AddModifier(
                        context,
                        diagnostic,
                        memberDeclaration.Parent,
                        SyntaxKind.AbstractKeyword,
                        title: "Make containing class abstract");

                    break;
                }

                case CompilerDiagnosticIdentifiers.StaticConstructorMustBeParameterless:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveParametersFromStaticConstructor))
                    {
                        break;
                    }

                    var constructorDeclaration = (ConstructorDeclarationSyntax)memberDeclaration;

                    CodeAction codeAction = CodeAction.Create(
                        "Remove parameters",
                        cancellationToken =>
                        {
                            ParameterListSyntax parameterList = constructorDeclaration.ParameterList;

                            ParameterListSyntax newParameterList = parameterList
                                                                   .WithParameters(default(SeparatedSyntaxList <ParameterSyntax>))
                                                                   .WithOpenParenToken(parameterList.OpenParenToken.WithoutTrailingTrivia())
                                                                   .WithCloseParenToken(parameterList.CloseParenToken.WithoutLeadingTrivia());

                            ConstructorDeclarationSyntax newNode = constructorDeclaration.WithParameterList(newParameterList);

                            return(context.Document.ReplaceNodeAsync(constructorDeclaration, newNode, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.ExplicitInterfaceDeclarationCanOnlyBeDeclaredInClassOrStruct:
                case CompilerDiagnosticIdentifiers.InterfacesCannotContainFields:
                case CompilerDiagnosticIdentifiers.InterfacesCannotContainOperators:
                case CompilerDiagnosticIdentifiers.InterfacesCannotDeclareTypes:
                case CompilerDiagnosticIdentifiers.OnlyClassTypesCanContainDestructors:
                case CompilerDiagnosticIdentifiers.StructsCannotContainExplicitParameterlessConstructors:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveMemberDeclaration))
                    {
                        break;
                    }

                    CodeFixRegistrator.RemoveMember(context, diagnostic, memberDeclaration);
                    break;
                }

                case CompilerDiagnosticIdentifiers.NameOfDestructorMustMatchNameOfClass:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RenameDestructorToMatchClassName))
                    {
                        break;
                    }

                    if (!(memberDeclaration is DestructorDeclarationSyntax destructorDeclaration))
                    {
                        break;
                    }

                    if (!(memberDeclaration.Parent is ClassDeclarationSyntax classDeclaration))
                    {
                        break;
                    }

                    if (classDeclaration.Identifier.ValueText.Length == 0)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Rename destructor to match class name",
                        cancellationToken =>
                        {
                            DestructorDeclarationSyntax newNode = destructorDeclaration.WithIdentifier(classDeclaration.Identifier.WithTriviaFrom(destructorDeclaration.Identifier));

                            return(context.Document.ReplaceNodeAsync(destructorDeclaration, newNode, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.CannotChangeTupleElementNameWhenOverridingInheritedMember:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RenameTupleElement))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    if (memberDeclaration is MethodDeclarationSyntax methodDeclaration)
                    {
                        IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken);

                        if (!(methodSymbol.ReturnType is INamedTypeSymbol tupleType))
                        {
                            break;
                        }

                        if (!tupleType.IsTupleType)
                        {
                            break;
                        }

                        if (!(methodSymbol.OverriddenMethod?.ReturnType is INamedTypeSymbol baseTupleType))
                        {
                            break;
                        }

                        if (!baseTupleType.IsTupleType)
                        {
                            break;
                        }

                        ImmutableArray <IFieldSymbol> elements     = tupleType.TupleElements;
                        ImmutableArray <IFieldSymbol> baseElements = baseTupleType.TupleElements;

                        if (elements.Length != baseElements.Length)
                        {
                            break;
                        }

                        int i = 0;
                        while (i < elements.Length)
                        {
                            if (elements[i].Name != baseElements[i].Name)
                            {
                                break;
                            }

                            i++;
                        }

                        if (i == elements.Length)
                        {
                            break;
                        }

                        TupleElementSyntax tupleElement = ((TupleTypeSyntax)methodDeclaration.ReturnType).Elements[i];

                        CodeAction codeAction = CodeAction.Create(
                            $"Rename '{elements[i].Name}' to '{baseElements[i].Name}'",
                            ct => RenameTupleElementAsync(context.Document, methodDeclaration, tupleElement, elements[i], baseElements[i].Name, semanticModel, ct),
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }
                    else if (memberDeclaration is PropertyDeclarationSyntax propertyDeclaration)
                    {
                        IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, context.CancellationToken);

                        if (!(propertySymbol.Type is INamedTypeSymbol tupleType))
                        {
                            break;
                        }

                        if (!tupleType.IsTupleType)
                        {
                            break;
                        }

                        if (!(propertySymbol.OverriddenProperty?.Type is INamedTypeSymbol baseTupleType))
                        {
                            break;
                        }

                        if (!baseTupleType.IsTupleType)
                        {
                            break;
                        }

                        ImmutableArray <IFieldSymbol> elements     = tupleType.TupleElements;
                        ImmutableArray <IFieldSymbol> baseElements = baseTupleType.TupleElements;

                        if (elements.Length != baseElements.Length)
                        {
                            break;
                        }

                        int i = 0;
                        while (i < elements.Length)
                        {
                            if (elements[i].Name != baseElements[i].Name)
                            {
                                break;
                            }

                            i++;
                        }

                        if (i == elements.Length)
                        {
                            break;
                        }

                        TupleElementSyntax tupleElement = ((TupleTypeSyntax)propertyDeclaration.Type).Elements[i];

                        CodeAction codeAction = CodeAction.Create(
                            $"Rename '{elements[i].Name}' to '{baseElements[i].Name}'",
                            ct => RenameTupleElementAsync(context.Document, propertyDeclaration, tupleElement, elements[i], baseElements[i].Name, semanticModel, ct),
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }

                    break;
                }
                }
            }
        }
        private static Task <Document> RefactorAsync(
            Document document,
            ImmutableArray <FieldInfo> fieldInfos,
            TypeDeclarationSyntax typeDeclaration,
            CancellationToken cancellationToken)
        {
            SyntaxList <MemberDeclarationSyntax> members = typeDeclaration.Members;

            HashSet <string> reservedNames = null;

            for (int i = 0; i < members.Count; i++)
            {
                if (!(members[i] is ConstructorDeclarationSyntax constructorDeclaration))
                {
                    continue;
                }

                if (constructorDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword))
                {
                    continue;
                }

                ParameterListSyntax parameterList = constructorDeclaration.ParameterList;

                if (parameterList == null)
                {
                    continue;
                }

                BlockSyntax body = constructorDeclaration.Body;

                if (body == null)
                {
                    continue;
                }

                SeparatedSyntaxList <ParameterSyntax> parameters = parameterList.Parameters;

                reservedNames?.Clear();

                ConstructorInitializerSyntax initializer  = null;
                ArgumentListSyntax           argumentList = null;
                var arguments = default(SeparatedSyntaxList <ArgumentSyntax>);

                if (constructorDeclaration.Initializer?.Kind() == SyntaxKind.ThisConstructorInitializer)
                {
                    initializer  = constructorDeclaration.Initializer;
                    argumentList = initializer.ArgumentList;
                    arguments    = argumentList.Arguments;
                }

                SyntaxList <StatementSyntax> statements = body.Statements;

                foreach (FieldInfo fieldInfo in fieldInfos)
                {
                    string parameterName = GetParameterName(fieldInfo.NameCamelCase, parameters, ref reservedNames);

                    parameters = parameters.Add(Parameter(fieldInfo.Type.WithoutTrivia(), parameterName));

                    if (initializer != null)
                    {
                        arguments = arguments.Add(Argument(IdentifierName(parameterName)));
                    }

                    statements = statements.Add(
                        SimpleAssignmentStatement(
                            SimpleMemberAccessExpression(ThisExpression(), IdentifierName(fieldInfo.Name)).WithSimplifierAnnotation(),
                            IdentifierName(parameterName)).WithFormatterAnnotation());
                }

                parameterList = parameterList.WithParameters(parameters).WithFormatterAnnotation();

                if (initializer != null)
                {
                    initializer = initializer
                                  .WithArgumentList(argumentList.WithArguments(arguments))
                                  .WithFormatterAnnotation();
                }

                body = body.WithStatements(statements);

                constructorDeclaration = constructorDeclaration.Update(
                    constructorDeclaration.AttributeLists,
                    constructorDeclaration.Modifiers,
                    constructorDeclaration.Identifier,
                    parameterList,
                    initializer,
                    body,
                    constructorDeclaration.SemicolonToken);

                members = members.ReplaceAt(i, constructorDeclaration);
            }

            TypeDeclarationSyntax newNode = typeDeclaration.WithMembers(members);

            return(document.ReplaceNodeAsync(typeDeclaration, newNode, cancellationToken));
        }
Exemple #9
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.OverridingMemberCannotChangeAccessModifiers) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddDocumentationComment) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeMemberNonStatic) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveParametersFromStaticConstructor))
            {
                return;
            }

            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            MemberDeclarationSyntax memberDeclaration = root
                                                        .FindNode(context.Span, getInnermostNodeForTie: true)?
                                                        .FirstAncestorOrSelf <MemberDeclarationSyntax>();

            Debug.Assert(memberDeclaration != null, $"{nameof(memberDeclaration)} is null");

            if (memberDeclaration == null)
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.CannotChangeAccessModifiersWhenOverridingInheritedMember:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.OverridingMemberCannotChangeAccessModifiers))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    OverrideInfo overrideInfo = OverridingMemberCannotChangeAccessModifiersRefactoring.GetOverrideInfo(memberDeclaration, semanticModel, context.CancellationToken);

                    Accessibility newAccessibility = overrideInfo.OverriddenSymbol.DeclaredAccessibility;

                    string title = $"Change accessibility to '{AccessibilityHelper.GetAccessibilityName(newAccessibility)}'";

                    CodeAction codeAction = CodeAction.Create(
                        title,
                        cancellationToken => OverridingMemberCannotChangeAccessModifiersRefactoring.RefactorAsync(context.Document, memberDeclaration, newAccessibility, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.MissingXmlCommentForPubliclyVisibleTypeOrMember:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddDocumentationComment))
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Add documentation comment",
                        cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, false, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);

                    CodeAction codeAction2 = CodeAction.Create(
                        "Add documentation comment (copy from base if available)",
                        cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, true, cancellationToken),
                        GetEquivalenceKey(diagnostic, "CopyFromBaseIfAvailable"));

                    context.RegisterCodeFix(codeAction2, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.MethodReturnTypeMustMatchOverriddenMethodReturnType:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                    ITypeSymbol typeSymbol = methodSymbol.OverriddenMethod.ReturnType;

                    if (typeSymbol?.IsErrorType() == false)
                    {
                        TypeSyntax newType = typeSymbol.ToMinimalTypeSyntax(semanticModel, memberDeclaration.SpanStart);

                        CodeAction codeAction = CodeAction.Create(
                            $"Change return type to '{SymbolDisplay.GetMinimalString(typeSymbol, semanticModel, memberDeclaration.SpanStart)}'",
                            cancellationToken => MemberTypeMustMatchOverriddenMemberTypeRefactoring.RefactorAsync(context.Document, memberDeclaration, typeSymbol, semanticModel, cancellationToken),
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.PartialMethodsMustHaveVoidReturnType:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    var methodDeclaration = (MethodDeclarationSyntax)memberDeclaration;

                    MethodDeclarationSyntax otherPart = semanticModel.GetOtherPart(methodDeclaration, context.CancellationToken);

                    if (otherPart == null)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Change return type to 'void'",
                        cancellationToken =>
                        {
                            return(context.Document.Solution().ReplaceNodesAsync(
                                       new MethodDeclarationSyntax[] { methodDeclaration, otherPart },
                                       (node, rewrittenNode) => node.WithReturnType(CSharpFactory.VoidType().WithTriviaFrom(node.ReturnType)),
                                       cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.MemberTypeMustMatchOverriddenMemberType:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ITypeSymbol typeSymbol = null;

                    switch (memberDeclaration.Kind())
                    {
                    case SyntaxKind.PropertyDeclaration:
                    case SyntaxKind.IndexerDeclaration:
                    {
                        var propertySymbol = (IPropertySymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                        typeSymbol = propertySymbol.OverriddenProperty.Type;
                        break;
                    }

                    case SyntaxKind.EventDeclaration:
                    {
                        var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                        typeSymbol = eventSymbol.OverriddenEvent.Type;
                        break;
                    }

                    case SyntaxKind.EventFieldDeclaration:
                    {
                        VariableDeclaratorSyntax declarator = ((EventFieldDeclarationSyntax)memberDeclaration).Declaration.Variables.First();

                        var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(declarator, context.CancellationToken);

                        typeSymbol = eventSymbol.OverriddenEvent.Type;
                        break;
                    }
                    }

                    if (typeSymbol?.IsErrorType() == false)
                    {
                        string title = $"Change type to '{SymbolDisplay.GetMinimalString(typeSymbol, semanticModel, memberDeclaration.SpanStart)}'";

                        CodeAction codeAction = CodeAction.Create(
                            title,
                            cancellationToken => MemberTypeMustMatchOverriddenMemberTypeRefactoring.RefactorAsync(context.Document, memberDeclaration, typeSymbol, semanticModel, cancellationToken),
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.MissingPartialModifier:
                case CompilerDiagnosticIdentifiers.PartialMethodMustBeDeclaredWithinPartialClassOrPartialStruct:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier))
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Add 'partial' modifier",
                        cancellationToken =>
                        {
                            if (memberDeclaration.IsKind(SyntaxKind.MethodDeclaration) &&
                                memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration))
                            {
                                return(context.Document.InsertModifierAsync(memberDeclaration.Parent, SyntaxKind.PartialKeyword, ModifierComparer.Instance, cancellationToken));
                            }
                            else if (memberDeclaration.IsKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration, SyntaxKind.InterfaceDeclaration))
                            {
                                return(context.Document.InsertModifierAsync(memberDeclaration, SyntaxKind.PartialKeyword, ModifierComparer.Instance, cancellationToken));
                            }

                            return(Task.FromResult(context.Document));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.MemberIsAbstractButItIsContainedInNonAbstractClass:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract))
                    {
                        break;
                    }

                    if (!memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration))
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Make containing class abstract",
                        cancellationToken => context.Document.InsertModifierAsync(memberDeclaration.Parent, SyntaxKind.AbstractKeyword, ModifierComparer.Instance, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.ObjectReferenceIsRequiredForNonStaticMember:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeMemberNonStatic))
                    {
                        break;
                    }

                    SyntaxTokenList modifiers = memberDeclaration.GetModifiers();

                    Debug.Assert(modifiers.Contains(SyntaxKind.StaticKeyword), memberDeclaration.ToString());

                    if (!modifiers.Contains(SyntaxKind.StaticKeyword))
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        $"Make containing {memberDeclaration.GetTitle()} non-static",
                        cancellationToken => context.Document.RemoveModifierAsync(memberDeclaration, SyntaxKind.StaticKeyword, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.StaticConstructorMustBeParameterless:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveParametersFromStaticConstructor))
                    {
                        break;
                    }

                    var constructorDeclaration = (ConstructorDeclarationSyntax)memberDeclaration;

                    CodeAction codeAction = CodeAction.Create(
                        "Remove parameters",
                        cancellationToken =>
                        {
                            ParameterListSyntax parameterList = constructorDeclaration.ParameterList;

                            ParameterListSyntax newParameterList = parameterList
                                                                   .WithParameters(default(SeparatedSyntaxList <ParameterSyntax>))
                                                                   .WithOpenParenToken(parameterList.OpenParenToken.WithoutTrailingTrivia())
                                                                   .WithCloseParenToken(parameterList.CloseParenToken.WithoutLeadingTrivia());

                            ConstructorDeclarationSyntax newNode = constructorDeclaration.WithParameterList(newParameterList);

                            return(context.Document.ReplaceNodeAsync(constructorDeclaration, newNode, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddDocumentationComment) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveParametersFromStaticConstructor) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveMemberDeclaration))
            {
                return;
            }

            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.MissingXmlCommentForPubliclyVisibleTypeOrMember:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddDocumentationComment))
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Add documentation comment",
                        cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, false, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);

                    CodeAction codeAction2 = CodeAction.Create(
                        "Add documentation comment (copy from base if available)",
                        cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, true, cancellationToken),
                        GetEquivalenceKey(diagnostic, "CopyFromBaseIfAvailable"));

                    context.RegisterCodeFix(codeAction2, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.MethodReturnTypeMustMatchOverriddenMethodReturnType:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                    ITypeSymbol typeSymbol = methodSymbol.OverriddenMethod.ReturnType;

                    if (typeSymbol?.IsErrorType() == false)
                    {
                        CodeAction codeAction = CodeAction.Create(
                            $"Change return type to '{SymbolDisplay.GetMinimalString(typeSymbol, semanticModel, memberDeclaration.SpanStart)}'",
                            cancellationToken => MemberTypeMustMatchOverriddenMemberTypeRefactoring.RefactorAsync(context.Document, memberDeclaration, typeSymbol, semanticModel, cancellationToken),
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.PartialMethodsMustHaveVoidReturnType:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    var methodDeclaration = (MethodDeclarationSyntax)memberDeclaration;

                    MethodDeclarationSyntax otherPart = semanticModel.GetOtherPart(methodDeclaration, context.CancellationToken);

                    if (otherPart == null)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Change return type to 'void'",
                        cancellationToken =>
                        {
                            return(context.Document.Solution().ReplaceNodesAsync(
                                       new MethodDeclarationSyntax[] { methodDeclaration, otherPart },
                                       (node, rewrittenNode) => node.WithReturnType(CSharpFactory.VoidType().WithTriviaFrom(node.ReturnType)),
                                       cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.MemberTypeMustMatchOverriddenMemberType:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ITypeSymbol typeSymbol = null;

                    switch (memberDeclaration.Kind())
                    {
                    case SyntaxKind.PropertyDeclaration:
                    case SyntaxKind.IndexerDeclaration:
                    {
                        var propertySymbol = (IPropertySymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                        typeSymbol = propertySymbol.OverriddenProperty.Type;
                        break;
                    }

                    case SyntaxKind.EventDeclaration:
                    {
                        var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                        typeSymbol = eventSymbol.OverriddenEvent.Type;
                        break;
                    }

                    case SyntaxKind.EventFieldDeclaration:
                    {
                        VariableDeclaratorSyntax declarator = ((EventFieldDeclarationSyntax)memberDeclaration).Declaration.Variables.First();

                        var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(declarator, context.CancellationToken);

                        typeSymbol = eventSymbol.OverriddenEvent.Type;
                        break;
                    }
                    }

                    if (typeSymbol?.IsErrorType() == false)
                    {
                        string title = $"Change type to '{SymbolDisplay.GetMinimalString(typeSymbol, semanticModel, memberDeclaration.SpanStart)}'";

                        CodeAction codeAction = CodeAction.Create(
                            title,
                            cancellationToken => MemberTypeMustMatchOverriddenMemberTypeRefactoring.RefactorAsync(context.Document, memberDeclaration, typeSymbol, semanticModel, cancellationToken),
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.MissingPartialModifier:
                case CompilerDiagnosticIdentifiers.PartialMethodMustBeDeclaredWithinPartialClassOrPartialStruct:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier))
                    {
                        break;
                    }

                    SyntaxNode node = null;

                    switch (memberDeclaration.Kind())
                    {
                    case SyntaxKind.MethodDeclaration:
                    {
                        if (memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration))
                        {
                            node = memberDeclaration.Parent;
                        }

                        break;
                    }

                    case SyntaxKind.ClassDeclaration:
                    case SyntaxKind.StructDeclaration:
                    case SyntaxKind.InterfaceDeclaration:
                    {
                        node = memberDeclaration;
                        break;
                    }
                    }

                    Debug.Assert(node != null, memberDeclaration.ToString());

                    if (node == null)
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.PartialKeyword);
                    break;
                }

                case CompilerDiagnosticIdentifiers.MemberIsAbstractButItIsContainedInNonAbstractClass:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract))
                    {
                        break;
                    }

                    if (!memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration))
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.AddModifier(
                        context,
                        diagnostic,
                        memberDeclaration.Parent,
                        SyntaxKind.AbstractKeyword,
                        title: "Make containing class abstract");

                    break;
                }

                case CompilerDiagnosticIdentifiers.StaticConstructorMustBeParameterless:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveParametersFromStaticConstructor))
                    {
                        break;
                    }

                    var constructorDeclaration = (ConstructorDeclarationSyntax)memberDeclaration;

                    CodeAction codeAction = CodeAction.Create(
                        "Remove parameters",
                        cancellationToken =>
                        {
                            ParameterListSyntax parameterList = constructorDeclaration.ParameterList;

                            ParameterListSyntax newParameterList = parameterList
                                                                   .WithParameters(default(SeparatedSyntaxList <ParameterSyntax>))
                                                                   .WithOpenParenToken(parameterList.OpenParenToken.WithoutTrailingTrivia())
                                                                   .WithCloseParenToken(parameterList.CloseParenToken.WithoutLeadingTrivia());

                            ConstructorDeclarationSyntax newNode = constructorDeclaration.WithParameterList(newParameterList);

                            return(context.Document.ReplaceNodeAsync(constructorDeclaration, newNode, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.ExplicitInterfaceDeclarationCanOnlyBeDeclaredInClassOrStruct:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveMemberDeclaration))
                    {
                        break;
                    }

                    CodeFixRegistrator.RemoveMember(context, diagnostic, memberDeclaration);
                    break;
                }
                }
            }
        }
 private static ParameterListSyntax RemoveType(ParameterListSyntax parameterList)
 {
     return(parameterList.WithParameters(SyntaxFactory.SeparatedList(parameterList.Parameters.Select(x => RemoveType(x)), parameterList.Parameters.GetSeparators())));
 }
        public static Task <Document> RefactorAsync(
            Document document,
            ParenthesizedLambdaExpressionSyntax parenthesizedLambda,
            MemberDeclarationSyntax memberDeclaration,
            TypeDeclarationSyntax typeDeclaration,
            string methodName,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            methodName = NameGenerator.Default.EnsureUniqueLocalName(methodName, semanticModel, parenthesizedLambda.SpanStart, cancellationToken: cancellationToken);

            MemberDeclarationSyntax newMemberDeclaration = memberDeclaration.ReplaceNode(parenthesizedLambda, IdentifierName(methodName).WithTriviaFrom(parenthesizedLambda));

            IMethodSymbol lambdaSymbol = semanticModel.GetMethodSymbol(parenthesizedLambda, cancellationToken);

            ParameterListSyntax parameterList = parenthesizedLambda.ParameterList;

            SeparatedSyntaxList <ParameterSyntax> parameters = parameterList.Parameters;

            ImmutableArray <IParameterSymbol> parameterSymbols = lambdaSymbol.Parameters;

            parameters = parameters
                         .ReplaceAt(0, AddTypeIfMissing(parameters[0], parameterSymbols[0]))
                         .ReplaceAt(1, AddTypeIfMissing(parameters[1], parameterSymbols[1]));

            cancellationToken.ThrowIfCancellationRequested();

            MethodDeclarationSyntax newMethodDeclaration = MethodDeclaration(
                (SyntaxInfo.ModifierListInfo(memberDeclaration).IsStatic) ? Modifiers.Private_Static() : Modifiers.Private(),
                VoidType(),
                Identifier(methodName).WithRenameAnnotation(),
                parameterList.WithParameters(parameters),
                CreateMethodBody(parenthesizedLambda.Body)).WithFormatterAnnotation();

            SyntaxList <MemberDeclarationSyntax> newMembers = typeDeclaration.Members.Replace(memberDeclaration, newMemberDeclaration);

            newMembers = MemberDeclarationInserter.Default.Insert(newMembers, newMethodDeclaration);

            return(document.ReplaceNodeAsync(typeDeclaration, typeDeclaration.WithMembers(newMembers), cancellationToken));

            BlockSyntax CreateMethodBody(CSharpSyntaxNode lambdaBody)
            {
                switch (lambdaBody)
                {
                case BlockSyntax block:
                    return(block);

                case ExpressionSyntax expression:
                    return(Block(ExpressionStatement(expression)));

                default:
                    return(Block());
                }
            }

            ParameterSyntax AddTypeIfMissing(ParameterSyntax parameter, IParameterSymbol parameterSymbol)
            {
                TypeSyntax type = parameter.Type;

                if (type?.IsMissing == false)
                {
                    return(parameter);
                }

                type = parameterSymbol.Type.ToMinimalTypeSyntax(semanticModel, typeDeclaration.OpenBraceToken.Span.End);

                return(parameter.WithType(type));
            }
        }
        private static Task <Document> RefactorAsync(
            Document document,
            VariableDeclaratorSyntax variableDeclarator,
            TypeDeclarationSyntax typeDeclaration,
            CancellationToken cancellationToken)
        {
            SyntaxList <MemberDeclarationSyntax> members = typeDeclaration.Members;

            string name          = variableDeclarator.Identifier.ValueText;
            string camelCaseName = StringUtility.ToCamelCase(name);

            HashSet <string> reservedNames = null;

            for (int i = 0; i < members.Count; i++)
            {
                if (!(members[i] is ConstructorDeclarationSyntax constructorDeclaration))
                {
                    continue;
                }

                if (constructorDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword))
                {
                    continue;
                }

                ParameterListSyntax parameterList = constructorDeclaration.ParameterList;

                if (parameterList == null)
                {
                    continue;
                }

                BlockSyntax body = constructorDeclaration.Body;

                if (body == null)
                {
                    continue;
                }

                SeparatedSyntaxList <ParameterSyntax> parameters = parameterList.Parameters;

                reservedNames?.Clear();

                string parameterName = GetParameterName(camelCaseName, parameters, ref reservedNames);

                ParameterSyntax parameter = Parameter(((VariableDeclarationSyntax)variableDeclarator.Parent).Type.WithoutTrivia(), parameterName);

                parameterList = parameterList.WithParameters(parameters.Add(parameter)).WithFormatterAnnotation();

                ConstructorInitializerSyntax initializer = constructorDeclaration.Initializer;

                if (initializer?.Kind() == SyntaxKind.ThisConstructorInitializer)
                {
                    ArgumentListSyntax argumentList = initializer.ArgumentList;

                    if (argumentList != null)
                    {
                        SeparatedSyntaxList <ArgumentSyntax> arguments = argumentList.Arguments;

                        initializer = initializer.WithArgumentList(
                            argumentList.WithArguments(
                                arguments.Add(Argument(IdentifierName(parameterName))))).WithFormatterAnnotation();
                    }
                }

                body = body.WithStatements(
                    body.Statements.Add(
                        SimpleAssignmentStatement(
                            SimpleMemberAccessExpression(ThisExpression(), IdentifierName(name)).WithSimplifierAnnotation(),
                            IdentifierName(parameterName)).WithFormatterAnnotation()));

                constructorDeclaration = constructorDeclaration.Update(
                    constructorDeclaration.AttributeLists,
                    constructorDeclaration.Modifiers,
                    constructorDeclaration.Identifier,
                    parameterList,
                    initializer,
                    body,
                    constructorDeclaration.SemicolonToken);

                members = members.ReplaceAt(i, constructorDeclaration);
            }

            TypeDeclarationSyntax newNode = typeDeclaration.WithMembers(members);

            return(document.ReplaceNodeAsync(typeDeclaration, newNode, cancellationToken));
        }
Exemple #14
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.CS1591_MissingXmlCommentForPubliclyVisibleTypeOrMember:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddDocumentationComment, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Add documentation comment",
                        ct => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, false, ct),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);

                    CodeAction codeAction2 = CodeAction.Create(
                        "Add documentation comment (copy from base if available)",
                        ct => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, true, ct),
                        GetEquivalenceKey(diagnostic, "CopyFromBaseIfAvailable"));

                    context.RegisterCodeFix(codeAction2, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.CS0508_MethodReturnTypeMustMatchOverriddenMethodReturnType:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeMethodReturnType, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                    ITypeSymbol typeSymbol = methodSymbol.OverriddenMethod.ReturnType;

                    CodeFixRegistrator.ChangeTypeOrReturnType(context, diagnostic, memberDeclaration, typeSymbol, semanticModel);

                    break;
                }

                case CompilerDiagnosticIdentifiers.CS0766_PartialMethodsMustHaveVoidReturnType:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeMethodReturnType, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    var methodDeclaration = (MethodDeclarationSyntax)memberDeclaration;

                    MethodDeclarationSyntax otherPart = semanticModel.GetOtherPart(methodDeclaration, context.CancellationToken);

                    if (otherPart == null)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Change return type to 'void'",
                        ct =>
                        {
                            return(context.Document.Solution().ReplaceNodesAsync(
                                       new MethodDeclarationSyntax[] { methodDeclaration, otherPart },
                                       (node, _) => node.WithReturnType(CSharpFactory.VoidType().WithTriviaFrom(node.ReturnType)),
                                       ct));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.CS1715_MemberTypeMustMatchOverriddenMemberType:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ITypeSymbol typeSymbol = null;

                    switch (memberDeclaration.Kind())
                    {
                    case SyntaxKind.PropertyDeclaration:
                    case SyntaxKind.IndexerDeclaration:
                    {
                        var propertySymbol = (IPropertySymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                        typeSymbol = propertySymbol.OverriddenProperty.Type;
                        break;
                    }

                    case SyntaxKind.EventDeclaration:
                    {
                        var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken);

                        typeSymbol = eventSymbol.OverriddenEvent.Type;
                        break;
                    }

                    case SyntaxKind.EventFieldDeclaration:
                    {
                        VariableDeclaratorSyntax declarator = ((EventFieldDeclarationSyntax)memberDeclaration).Declaration.Variables[0];

                        var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(declarator, context.CancellationToken);

                        typeSymbol = eventSymbol.OverriddenEvent.Type;
                        break;
                    }
                    }

                    CodeFixRegistrator.ChangeTypeOrReturnType(context, diagnostic, memberDeclaration, typeSymbol, semanticModel);

                    break;
                }

                case CompilerDiagnosticIdentifiers.CS0260_MissingPartialModifier:
                case CompilerDiagnosticIdentifiers.CS0751_PartialMethodMustBeDeclaredInPartialClassOrPartialStruct:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddPartialModifier, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    SyntaxNode node = null;

                    switch (memberDeclaration.Kind())
                    {
                    case SyntaxKind.MethodDeclaration:
                    {
                        if (memberDeclaration.IsParentKind(
                                SyntaxKind.ClassDeclaration,
                                SyntaxKind.StructDeclaration,
                                SyntaxKind.RecordDeclaration,
                                SyntaxKind.RecordStructDeclaration))
                        {
                            node = memberDeclaration.Parent;
                        }

                        break;
                    }

                    case SyntaxKind.ClassDeclaration:
                    case SyntaxKind.StructDeclaration:
                    case SyntaxKind.RecordStructDeclaration:
                    case SyntaxKind.InterfaceDeclaration:
                    case SyntaxKind.RecordDeclaration:
                    {
                        node = memberDeclaration;
                        break;
                    }
                    }

                    SyntaxDebug.Assert(node != null, memberDeclaration);

                    if (node == null)
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.PartialKeyword, title: $"Make {CSharpFacts.GetTitle(node)} partial");
                    break;
                }

                case CompilerDiagnosticIdentifiers.CS0513_MemberIsAbstractButItIsContainedInNonAbstractClass:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeContainingClassAbstract, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    if (!memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration))
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.AddModifier(
                        context,
                        diagnostic,
                        memberDeclaration.Parent,
                        SyntaxKind.AbstractKeyword,
                        title: "Make containing class abstract");

                    break;
                }

                case CompilerDiagnosticIdentifiers.CS0132_StaticConstructorMustBeParameterless:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveParametersFromStaticConstructor, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    var constructorDeclaration = (ConstructorDeclarationSyntax)memberDeclaration;

                    CodeAction codeAction = CodeAction.Create(
                        "Remove parameters",
                        ct =>
                        {
                            ParameterListSyntax parameterList = constructorDeclaration.ParameterList;

                            ParameterListSyntax newParameterList = parameterList
                                                                   .WithParameters(default(SeparatedSyntaxList <ParameterSyntax>))
                                                                   .WithOpenParenToken(parameterList.OpenParenToken.WithoutTrailingTrivia())
                                                                   .WithCloseParenToken(parameterList.CloseParenToken.WithoutLeadingTrivia());

                            ConstructorDeclarationSyntax newNode = constructorDeclaration.WithParameterList(newParameterList);

                            return(context.Document.ReplaceNodeAsync(constructorDeclaration, newNode, ct));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.CS0541_ExplicitInterfaceDeclarationCanOnlyBeDeclaredInClassOrStruct:
                case CompilerDiagnosticIdentifiers.CS0525_InterfacesCannotContainFields:
                case CompilerDiagnosticIdentifiers.CS0567_InterfacesCannotContainOperators:
                case CompilerDiagnosticIdentifiers.CS0524_InterfacesCannotDeclareTypes:
                case CompilerDiagnosticIdentifiers.CS0575_OnlyClassTypesCanContainDestructors:
                case CompilerDiagnosticIdentifiers.CS0568_StructsCannotContainExplicitParameterlessConstructors:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveMemberDeclaration, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    CodeFixRegistrator.RemoveMemberDeclaration(context, diagnostic, memberDeclaration);
                    break;
                }

                case CompilerDiagnosticIdentifiers.CS0574_NameOfDestructorMustMatchNameOfClass:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RenameDestructorToMatchClassName, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    if (memberDeclaration is not DestructorDeclarationSyntax destructorDeclaration)
                    {
                        break;
                    }

                    if (memberDeclaration.Parent is not ClassDeclarationSyntax classDeclaration)
                    {
                        break;
                    }

                    if (classDeclaration.Identifier.ValueText.Length == 0)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Rename destructor to match class name",
                        ct =>
                        {
                            DestructorDeclarationSyntax newNode = destructorDeclaration.WithIdentifier(classDeclaration.Identifier.WithTriviaFrom(destructorDeclaration.Identifier));

                            return(context.Document.ReplaceNodeAsync(destructorDeclaration, newNode, ct));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.CS8139_CannotChangeTupleElementNameWhenOverridingInheritedMember:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RenameTupleElement, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    if (memberDeclaration is MethodDeclarationSyntax methodDeclaration)
                    {
                        IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken);

                        if (methodSymbol.ReturnType is not INamedTypeSymbol tupleType)
                        {
                            break;
                        }

                        if (!tupleType.IsTupleType)
                        {
                            break;
                        }

                        if (methodSymbol.OverriddenMethod?.ReturnType is not INamedTypeSymbol baseTupleType)
                        {
                            break;
                        }

                        if (!baseTupleType.IsTupleType)
                        {
                            break;
                        }

                        ImmutableArray <IFieldSymbol> elements     = tupleType.TupleElements;
                        ImmutableArray <IFieldSymbol> baseElements = baseTupleType.TupleElements;

                        if (elements.Length != baseElements.Length)
                        {
                            break;
                        }

                        int i = 0;
                        while (i < elements.Length)
                        {
                            if (elements[i].Name != baseElements[i].Name)
                            {
                                break;
                            }

                            i++;
                        }

                        if (i == elements.Length)
                        {
                            break;
                        }

                        TupleElementSyntax tupleElement = ((TupleTypeSyntax)methodDeclaration.ReturnType).Elements[i];

                        CodeAction codeAction = CodeAction.Create(
                            $"Rename '{elements[i].Name}' to '{baseElements[i].Name}'",
                            ct => RenameTupleElementAsync(context.Document, methodDeclaration, tupleElement, elements[i], baseElements[i].Name, semanticModel, ct),
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }
                    else if (memberDeclaration is PropertyDeclarationSyntax propertyDeclaration)
                    {
                        IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, context.CancellationToken);

                        if (propertySymbol.Type is not INamedTypeSymbol tupleType)
                        {
                            break;
                        }

                        if (!tupleType.IsTupleType)
                        {
                            break;
                        }

                        if (propertySymbol.OverriddenProperty?.Type is not INamedTypeSymbol baseTupleType)
                        {
                            break;
                        }

                        if (!baseTupleType.IsTupleType)
                        {
                            break;
                        }

                        ImmutableArray <IFieldSymbol> elements     = tupleType.TupleElements;
                        ImmutableArray <IFieldSymbol> baseElements = baseTupleType.TupleElements;

                        if (elements.Length != baseElements.Length)
                        {
                            break;
                        }

                        int i = 0;
                        while (i < elements.Length)
                        {
                            if (elements[i].Name != baseElements[i].Name)
                            {
                                break;
                            }

                            i++;
                        }

                        if (i == elements.Length)
                        {
                            break;
                        }

                        TupleElementSyntax tupleElement = ((TupleTypeSyntax)propertyDeclaration.Type).Elements[i];

                        CodeAction codeAction = CodeAction.Create(
                            $"Rename '{elements[i].Name}' to '{baseElements[i].Name}'",
                            ct => RenameTupleElementAsync(context.Document, propertyDeclaration, tupleElement, elements[i], baseElements[i].Name, semanticModel, ct),
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.CS3000_MethodsWithVariableArgumentsAreNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3001_ArgumentTypeIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3002_ReturnTypeIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3003_TypeOfVariableIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3005_IdentifierDifferingOnlyInCaseIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3006_OverloadedMethodDifferingOnlyInRefOrOutOrInArrayRankIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3007_OverloadedMethodDifferingOnlyByUnnamedArrayTypesIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3008_IdentifierIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3009_BaseTypeIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3016_ArraysAsAttributeArgumentsIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3024_ConstraintTypeIsNotCLSCompliant:
                case CompilerDiagnosticIdentifiers.CS3027_TypeIsNotCLSCompliantBecauseBaseInterfaceIsNotCLSCompliant:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.MarkDeclarationAsNonCLSCompliant, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        $"Mark {CSharpFacts.GetTitle(memberDeclaration)} as non-CLS-compliant",
                        ct => MarkDeclarationAsNonCLSCompliantAsync(context.Document, memberDeclaration, ct),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.CS0539_ExplicitInterfaceDeclarationIsNotMemberOfInterface:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddParameterToExplicitlyImplementedInterfaceMember, context.Document, root.SyntaxTree))
                    {
                        break;
                    }

                    var context2 = new CommonFixContext(
                        context.Document,
                        GetEquivalenceKey(diagnostic),
                        await context.GetSemanticModelAsync().ConfigureAwait(false),
                        context.CancellationToken);

                    CodeAction codeAction = AddParameterToInterfaceMemberRefactoring.ComputeRefactoringForExplicitImplementation(context2, memberDeclaration);

                    if (codeAction != null)
                    {
                        context.RegisterCodeFix(codeAction, diagnostic);
                    }

                    break;
                }
                }
            }
        }
 public SyntaxNode ComputeReplacementNode(SyntaxNode replacedNode)
 => _parameterList
 .WithParameters(_parameterList.Parameters.Remove(_parameter))                         // there's no way for the parameter list to be rewritten by any other changes
 .WithAdditionalAnnotations(Formatter.Annotation);
        private static ParameterListSyntax NormalizeParameterList(ParameterListSyntax node)
        {
            int count = node.Parameters.Count;

            SyntaxTriviaList[] argumentTriviasLeading  = new SyntaxTriviaList[count];
            SyntaxTriviaList[] argumentTriviasTrailing = new SyntaxTriviaList[count];
            for (int j = 0; j < count; j++)
            {
                argumentTriviasLeading[j]  = SyntaxTriviaList.Empty;
                argumentTriviasTrailing[j] = SyntaxTriviaList.Empty;
            }

            if (count > 0)
            {
                // save trivia after open paren
                SyntaxTriviaList trailing = SyntaxTriviaList.Empty.AddRange(node.OpenParenToken.TrailingTrivia.Where(MultiLineCommentPredicate));
                argumentTriviasLeading[0] = argumentTriviasLeading[0].AddRange(trailing);
            }
            for (int j = 0; j < count - 1; j++)
            {
                // save trivia on trailing edge of separator to next argument
                SyntaxTriviaList trailing = SyntaxTriviaList.Empty.AddRange(node.Parameters.GetSeparator(j).TrailingTrivia.Where(MultiLineCommentPredicate));
                argumentTriviasLeading[j + 1] = argumentTriviasLeading[j + 1].AddRange(trailing);
            }
            for (int j = 0; j < count; j++)
            {
                // save leading and trailing trivia from argument
                SyntaxTriviaList leading  = node.Parameters[j].GetLeadingTrivia();
                SyntaxTriviaList trailing = node.Parameters[j].GetTrailingTrivia();
                argumentTriviasLeading[j]  = argumentTriviasLeading[j].AddRange(leading);
                argumentTriviasTrailing[j] = argumentTriviasTrailing[j].AddRange(trailing);
            }
            for (int j = 0; j < count - 1; j++)
            {
                // save trivia on leading edge of separator to previous argument
                SyntaxTriviaList leading = SyntaxTriviaList.Empty.AddRange(node.Parameters.GetSeparator(j).LeadingTrivia.Where(MultiLineCommentPredicate));
                argumentTriviasTrailing[j] = argumentTriviasTrailing[j].AddRange(leading);
            }
            if (count > 0)
            {
                // save trivia before close paren
                SyntaxTriviaList leading = node.CloseParenToken.LeadingTrivia;
                argumentTriviasTrailing[count - 1] = argumentTriviasTrailing[count - 1].AddRange(leading);
            }

            bool multiline;
            int  indent;

            DetectMultiLineArgumentList(node.Parameters, out multiline, out indent);

            // strip all trivia
            node = node.WithOpenParenToken(node.OpenParenToken.WithTrailingTrivia(SyntaxTriviaList.Empty));
            node = node.WithCloseParenToken(node.CloseParenToken.WithLeadingTrivia(SyntaxTriviaList.Empty));
            for (int j = 0; j < count - 1; j++)
            {
                node = node.WithParameters(
                    node.Parameters.ReplaceSeparator(
                        node.Parameters.GetSeparator(j),
                        node.Parameters.GetSeparator(j).WithLeadingTrivia(SyntaxTriviaList.Empty).WithTrailingTrivia(SyntaxTriviaList.Empty)));
            }

            // reformat
            SyntaxTriviaList delimiterTrailing = CreateDelimiterTrailer(multiline, indent);

            if (multiline)
            {
                node = node.WithOpenParenToken(node.OpenParenToken.WithTrailingTrivia(delimiterTrailing));
            }
            for (int j = 0; j < count - 1; j++)
            {
                node = node.WithParameters(
                    node.Parameters.ReplaceSeparator(
                        node.Parameters.GetSeparator(j),
                        node.Parameters.GetSeparator(j).WithTrailingTrivia(delimiterTrailing)));
            }

            // reassociate comment trivia to arguments
            for (int j = 0; j < count; j++)
            {
                node = node.WithParameters(
                    node.Parameters.Replace(
                        node.Parameters[j],
                        node.Parameters[j]
                        .WithoutTrivia()
                        .WithLeadingTrivia(argumentTriviasLeading[j])
                        .WithTrailingTrivia(argumentTriviasTrailing[j])));
            }

            return(node);
        }