Beispiel #1
0
        private static bool CanRefactor(
            SeparatedSyntaxListSelection <ArgumentSyntax> selection,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            for (int i = selection.StartIndex; i <= selection.EndIndex; i++)
            {
                ArgumentSyntax argument = selection.Items[i];

                NameColonSyntax nameColon = argument.NameColon;

                if (nameColon == null ||
                    nameColon.IsMissing)
                {
                    IParameterSymbol parameterSymbol = semanticModel.DetermineParameter(
                        argument,
                        allowParams: false,
                        cancellationToken: cancellationToken);

                    if (parameterSymbol != null)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        private static bool TryGetParameterInfos(
            ArgumentListSyntax argumentList,
            SemanticModel semanticModel,
            CancellationToken cancellationToken,
            out List <ParameterInfo> parameterInfos)
        {
            List <ParameterInfo> list = null;

            foreach (ArgumentSyntax argument in argumentList.Arguments)
            {
                IParameterSymbol parameterSymbol = semanticModel.DetermineParameter(argument, cancellationToken: cancellationToken);

                if (parameterSymbol != null)
                {
                    (list ?? (list = new List <ParameterInfo>())).Add(new ParameterInfo(parameterSymbol, argument.Expression));
                }
                else
                {
                    parameterInfos = null;
                    return(false);
                }
            }

            parameterInfos = list;
            return(true);
        }
Beispiel #3
0
        private static List <ParameterInfo> GetParameterInfos(
            ArgumentListSyntax argumentList,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            var list = new List <ParameterInfo>();

            foreach (ArgumentSyntax argument in argumentList.Arguments)
            {
                IParameterSymbol parameterSymbol = semanticModel.DetermineParameter(argument, cancellationToken: cancellationToken);

                if (parameterSymbol != null)
                {
                    list.Add(new ParameterInfo(parameterSymbol, argument.Expression));
                }
                else
                {
                    return(null);
                }
            }

            return(list);
        }
Beispiel #4
0
        private static ArgumentSyntax AddParameterName(
            ArgumentSyntax argument,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default)
        {
            if (argument.NameColon?.IsMissing != false)
            {
                IParameterSymbol parameterSymbol = semanticModel.DetermineParameter(
                    argument,
                    allowParams: false,
                    cancellationToken: cancellationToken);

                if (parameterSymbol != null)
                {
                    return(argument
                           .WithNameColon(
                               NameColon(parameterSymbol.ToDisplayString(_symbolDisplayFormat))
                               .WithTrailingTrivia(Space))
                           .WithTriviaFrom(argument));
                }
            }

            return(argument);
        }
Beispiel #5
0
        private static async Task <bool> CanAddParameterNameAsync(
            RefactoringContext context,
            AttributeArgumentSyntax[] arguments)
        {
            foreach (AttributeArgumentSyntax argument in arguments)
            {
                if (argument.NameColon?.IsMissing != false)
                {
                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    IParameterSymbol parameterSymbol = semanticModel.DetermineParameter(
                        argument,
                        allowParams: false,
                        cancellationToken: context.CancellationToken);

                    if (parameterSymbol != null)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Beispiel #6
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out ArgumentSyntax argument))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.ArgumentMustBePassedWithRefOrOutKeyword:
                {
                    if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddOutModifierToArgument))
                    {
                        return;
                    }

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

                    IParameterSymbol parameter = semanticModel.DetermineParameter(argument, allowCandidate: true, cancellationToken: context.CancellationToken);

                    if (parameter == null)
                    {
                        return;
                    }

                    SyntaxToken refOrOutKeyword = default;

                    if (parameter.RefKind == RefKind.Out)
                    {
                        refOrOutKeyword = Token(SyntaxKind.OutKeyword);
                    }
                    else if (parameter.RefKind == RefKind.Ref)
                    {
                        refOrOutKeyword = Token(SyntaxKind.RefKeyword);
                    }
                    else
                    {
                        return;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        $"Add '{SyntaxFacts.GetText(refOrOutKeyword.Kind())}' modifier",
                        cancellationToken =>
                        {
                            ArgumentSyntax newArgument = argument
                                                         .WithRefOrOutKeyword(refOrOutKeyword)
                                                         .WithFormatterAnnotation();

                            return(context.Document.ReplaceNodeAsync(argument, newArgument, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

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

                case CompilerDiagnosticIdentifiers.ArgumentShouldNotBePassedWithRefOrOutKeyword:
                {
                    if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveRefModifier))
                    {
                        return;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Remove 'ref' modifier",
                        cancellationToken =>
                        {
                            ArgumentSyntax newArgument = argument
                                                         .WithRefOrOutKeyword(default(SyntaxToken))
                                                         .PrependToLeadingTrivia(argument.RefOrOutKeyword.GetAllTrivia())
                                                         .WithFormatterAnnotation();

                            return(context.Document.ReplaceNodeAsync(argument, newArgument, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

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

                case CompilerDiagnosticIdentifiers.CannotConvertArgumentType:
                {
                    if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue))
                    {
                        ExpressionSyntax expression = argument.Expression;

                        if (expression.Kind() == SyntaxKind.NullLiteralExpression &&
                            argument.Parent is ArgumentListSyntax argumentList)
                        {
                            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                            ImmutableArray <IParameterSymbol> parameterSymbols = FindParameters(argumentList, semanticModel, context.CancellationToken);

                            if (!parameterSymbols.IsDefault)
                            {
                                int index = argumentList.Arguments.IndexOf(argument);

                                IParameterSymbol parameterSymbol = parameterSymbols[index];

                                ITypeSymbol typeSymbol = parameterSymbol.Type;

                                if (typeSymbol.IsValueType)
                                {
                                    CodeFixRegistrator.ReplaceNullWithDefaultValue(
                                        context,
                                        diagnostic,
                                        expression,
                                        typeSymbol,
                                        CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue);
                                }
                            }
                        }
                    }

                    if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddArgumentList))
                    {
                        ExpressionSyntax expression = argument.Expression;

                        if (expression.IsKind(
                                SyntaxKind.IdentifierName,
                                SyntaxKind.GenericName,
                                SyntaxKind.SimpleMemberAccessExpression))
                        {
                            InvocationExpressionSyntax invocationExpression = InvocationExpression(
                                expression.WithoutTrailingTrivia(),
                                ArgumentList().WithTrailingTrivia(expression.GetTrailingTrivia()));

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

                            if (semanticModel.GetSpeculativeMethodSymbol(expression.SpanStart, invocationExpression) != null)
                            {
                                CodeAction codeAction = CodeAction.Create(
                                    "Add argument list",
                                    cancellationToken =>
                                    {
                                        ArgumentSyntax newNode = argument.WithExpression(invocationExpression);

                                        return(context.Document.ReplaceNodeAsync(argument, newNode, cancellationToken));
                                    },
                                    GetEquivalenceKey(diagnostic, CodeFixIdentifiers.AddArgumentList));

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

                    if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.CreateSingletonArray))
                    {
                        ExpressionSyntax expression = argument.Expression;

                        if (expression?.IsMissing == false)
                        {
                            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                            ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression);

                            if (typeSymbol?.IsErrorType() == false)
                            {
                                foreach (ITypeSymbol typeSymbol2 in DetermineParameterTypeHelper.DetermineParameterTypes(argument, semanticModel, context.CancellationToken))
                                {
                                    if (!typeSymbol.Equals(typeSymbol2) &&
                                        typeSymbol2 is IArrayTypeSymbol arrayType &&
                                        semanticModel.IsImplicitConversion(expression, arrayType.ElementType))
                                    {
                                        CodeAction codeAction = CodeAction.Create(
                                            "Create singleton array",
                                            cancellationToken => CreateSingletonArrayRefactoring.RefactorAsync(context.Document, expression, arrayType.ElementType, semanticModel, cancellationToken),
                                            GetEquivalenceKey(diagnostic, CodeFixIdentifiers.CreateSingletonArray));

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

                    break;
                }

                case CompilerDiagnosticIdentifiers.ReadOnlyFieldCannotBePassedAsRefOrOutValue:
                {
                    if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeFieldWritable))
                    {
                        return;
                    }

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

                    SymbolInfo symbolInfo = semanticModel.GetSymbolInfo(argument.Expression, context.CancellationToken);

                    if (symbolInfo.CandidateReason != CandidateReason.NotAVariable)
                    {
                        return;
                    }

                    if (!(symbolInfo.CandidateSymbols.SingleOrDefault(shouldThrow: false) is IFieldSymbol fieldSymbol))
                    {
                        return;
                    }

                    if (fieldSymbol.DeclaredAccessibility != Accessibility.Private)
                    {
                        return;
                    }

                    if (!(fieldSymbol.GetSyntax().Parent.Parent is FieldDeclarationSyntax fieldDeclaration))
                    {
                        return;
                    }

                    TypeDeclarationSyntax containingTypeDeclaration = fieldDeclaration.FirstAncestor <TypeDeclarationSyntax>();

                    if (!argument.Ancestors().Any(f => f == containingTypeDeclaration))
                    {
                        return;
                    }

                    ModifiersCodeFixRegistrator.RemoveModifier(
                        context,
                        diagnostic,
                        fieldDeclaration,
                        SyntaxKind.ReadOnlyKeyword,
                        title: $"Make '{fieldSymbol.Name}' writable",
                        additionalKey: CodeFixIdentifiers.MakeFieldWritable);

                    break;
                }
                }
            }
        }
        private static ArgumentListPair RewriteArgumentLists(
            ArgumentListSyntax argumentList,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            ArgumentSyntax pattern      = null;
            ArgumentSyntax regexOptions = null;
            ArgumentSyntax matchTimeout = null;

            SeparatedSyntaxList <ArgumentSyntax> arguments = argumentList.Arguments;

            SeparatedSyntaxList <ArgumentSyntax> newArguments = arguments;

            for (int i = arguments.Count - 1; i >= 0; i--)
            {
                IParameterSymbol parameterSymbol = semanticModel.DetermineParameter(arguments[i], cancellationToken: cancellationToken);

                Debug.Assert(parameterSymbol != null, "");

                if (parameterSymbol != null)
                {
                    if (pattern == null &&
                        parameterSymbol.Type.IsString() &&
                        parameterSymbol.Name == "pattern")
                    {
                        pattern      = arguments[i];
                        newArguments = newArguments.RemoveAt(i);
                    }

                    if (regexOptions == null &&
                        parameterSymbol.Type.Equals(semanticModel.GetTypeByMetadataName(MetadataNames.System_Text_RegularExpressions_RegexOptions)))
                    {
                        regexOptions = arguments[i];
                        newArguments = newArguments.RemoveAt(i);
                    }

                    if (matchTimeout == null &&
                        parameterSymbol.Type.Equals(semanticModel.GetTypeByMetadataName(MetadataNames.System_TimeSpan)))
                    {
                        matchTimeout = arguments[i];
                        newArguments = newArguments.RemoveAt(i);
                    }
                }
            }

            argumentList = argumentList.WithArguments(newArguments);

            var arguments2 = new List <ArgumentSyntax>();

            if (pattern != null)
            {
                arguments2.Add(pattern);
            }

            if (regexOptions != null)
            {
                arguments2.Add(regexOptions);
            }

            if (matchTimeout != null)
            {
                arguments2.Add(matchTimeout);
            }

            return(new ArgumentListPair(argumentList, ArgumentList(arguments2.ToArray())));
        }
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out ArgumentSyntax argument))
            {
                return;
            }

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

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

                    IParameterSymbol parameter = semanticModel.DetermineParameter(argument, allowCandidate: true, cancellationToken: context.CancellationToken);

                    if (parameter == null)
                    {
                        return;
                    }

                    SyntaxToken refOrOutKeyword = default;

                    if (parameter.RefKind == RefKind.Out)
                    {
                        refOrOutKeyword = Token(SyntaxKind.OutKeyword);
                    }
                    else if (parameter.RefKind == RefKind.Ref)
                    {
                        refOrOutKeyword = Token(SyntaxKind.RefKeyword);
                    }
                    else
                    {
                        return;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        $"Add '{SyntaxFacts.GetText(refOrOutKeyword.Kind())}' modifier",
                        ct =>
                        {
                            ArgumentSyntax newArgument = argument
                                                         .WithRefOrOutKeyword(refOrOutKeyword)
                                                         .WithFormatterAnnotation();

                            return(context.Document.ReplaceNodeAsync(argument, newArgument, ct));
                        },
                        GetEquivalenceKey(diagnostic));

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

                case CompilerDiagnosticIdentifiers.CS1615_ArgumentShouldNotBePassedWithRefOrOutKeyword:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveRefModifier, context.Document, root.SyntaxTree))
                    {
                        return;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Remove 'ref' modifier",
                        ct =>
                        {
                            ArgumentSyntax newArgument = argument
                                                         .WithRefOrOutKeyword(default(SyntaxToken))
                                                         .PrependToLeadingTrivia(argument.RefOrOutKeyword.GetAllTrivia())
                                                         .WithFormatterAnnotation();

                            return(context.Document.ReplaceNodeAsync(argument, newArgument, ct));
                        },
                        GetEquivalenceKey(diagnostic));

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

                case CompilerDiagnosticIdentifiers.CS0192_ReadOnlyFieldCannotBePassedAsRefOrOutValue:
                {
                    if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeFieldWritable, context.Document, root.SyntaxTree))
                    {
                        return;
                    }

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

                    SymbolInfo symbolInfo = semanticModel.GetSymbolInfo(argument.Expression, context.CancellationToken);

                    if (symbolInfo.CandidateReason != CandidateReason.NotAVariable)
                    {
                        return;
                    }

                    if (symbolInfo.CandidateSymbols.SingleOrDefault(shouldThrow: false) is not IFieldSymbol fieldSymbol)
                    {
                        return;
                    }

                    if (fieldSymbol.DeclaredAccessibility != Accessibility.Private)
                    {
                        return;
                    }

                    if (fieldSymbol.GetSyntax().Parent.Parent is not FieldDeclarationSyntax fieldDeclaration)
                    {
                        return;
                    }

                    TypeDeclarationSyntax containingTypeDeclaration = fieldDeclaration.FirstAncestor <TypeDeclarationSyntax>();

                    if (!argument.Ancestors().Any(f => f == containingTypeDeclaration))
                    {
                        return;
                    }

                    ModifiersCodeFixRegistrator.RemoveModifier(
                        context,
                        diagnostic,
                        fieldDeclaration,
                        SyntaxKind.ReadOnlyKeyword,
                        title: $"Make '{fieldSymbol.Name}' writable",
                        additionalKey: CodeFixIdentifiers.MakeFieldWritable);

                    break;
                }
                }
            }
        }