private static SyntaxKind GetInvertedOperatorKind(SyntaxToken operatorToken)
        {
            switch (operatorToken.Kind())
            {
            case SyntaxKind.AmpersandAmpersandToken:
                return(SyntaxKind.BarBarToken);

            case SyntaxKind.BarBarToken:
                return(SyntaxKind.AmpersandAmpersandToken);

            case SyntaxKind.EqualsEqualsToken:
                return(SyntaxKind.ExclamationEqualsToken);

            case SyntaxKind.ExclamationEqualsToken:
                return(SyntaxKind.EqualsEqualsToken);

            case SyntaxKind.GreaterThanToken:
                return(SyntaxKind.LessThanEqualsToken);

            case SyntaxKind.GreaterThanEqualsToken:
                return(SyntaxKind.LessThanToken);

            case SyntaxKind.LessThanToken:
                return(SyntaxKind.GreaterThanEqualsToken);

            case SyntaxKind.LessThanEqualsToken:
                return(SyntaxKind.GreaterThanToken);

            default:
            {
                SyntaxDebug.Fail(operatorToken);
                return(operatorToken.Kind());
            }
            }
        }
        private static TypeSyntax GetTypeSyntax(SyntaxNode node)
        {
            switch (node)
            {
            case EventDeclarationSyntax eventDeclaration:
            {
                return(eventDeclaration.Type);
            }

            case VariableDeclaratorSyntax declarator:
            {
                if (declarator.Parent is VariableDeclarationSyntax declaration)
                {
                    return(declaration.Type);
                }

                SyntaxDebug.Fail(declarator.Parent);
                break;
            }

            default:
            {
                SyntaxDebug.Fail(node);
                break;
            }
            }

            return(null);
        }
예제 #3
0
        private static async Task <Document> UseStringLengthInsteadOfComparisonWithEmptyStringAsync(
            Document document,
            BinaryExpressionSyntax binaryExpression,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            ExpressionSyntax left = binaryExpression.Left;

            ExpressionSyntax right = binaryExpression.Right;

            BinaryExpressionSyntax newNode;

            if (CSharpUtility.IsEmptyStringExpression(left, semanticModel, cancellationToken))
            {
                newNode = binaryExpression
                          .WithLeft(NumericLiteralExpression(0))
                          .WithRight(CreateConditionalAccess(right));
            }
            else if (CSharpUtility.IsEmptyStringExpression(right, semanticModel, cancellationToken))
            {
                newNode = binaryExpression
                          .WithLeft(CreateConditionalAccess(left))
                          .WithRight(NumericLiteralExpression(0));
            }
            else
            {
                SyntaxDebug.Fail(binaryExpression);
                return(document);
            }

            newNode = newNode.WithTriviaFrom(binaryExpression).WithFormatterAnnotation();

            return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false));
        }
            public override void VisitInvocationExpression(InvocationExpressionSyntax node)
            {
                switch (node.Expression)
                {
                case SimpleNameSyntax simpleName:
                {
                    AnalyzeSimpleName(simpleName);
                    break;
                }

                case MemberBindingExpressionSyntax memberBindingExpression:
                {
                    AnalyzeSimpleName(memberBindingExpression.Name);
                    break;
                }

                case MemberAccessExpressionSyntax memberAccessExpression:
                {
                    AnalyzeSimpleName(memberAccessExpression.Name);
                    break;
                }

                default:
                {
                    SyntaxDebug.Fail(node);
                    break;
                }
                }

                base.VisitInvocationExpression(node);
            }
예제 #5
0
        public static async Task <Document> RefactorAsync(
            Document document,
            AccessorListSyntax accessorList,
            CancellationToken cancellationToken)
        {
            if (accessorList.Accessors.All(f => f.BodyOrExpressionBody() == null))
            {
                SyntaxNode parent = accessorList.Parent;

                switch (parent)
                {
                case PropertyDeclarationSyntax propertyDeclaration:
                {
                    TextSpan span = TextSpan.FromBounds(
                        propertyDeclaration.Identifier.Span.End,
                        accessorList.CloseBraceToken.SpanStart);

                    PropertyDeclarationSyntax newNode = propertyDeclaration.RemoveWhitespace(span);

                    newNode = newNode.WithFormatterAnnotation();

                    return(await document.ReplaceNodeAsync(propertyDeclaration, newNode, cancellationToken).ConfigureAwait(false));
                }

                case IndexerDeclarationSyntax indexerDeclaration:
                {
                    TextSpan span = TextSpan.FromBounds(
                        indexerDeclaration.ParameterList.CloseBracketToken.Span.End,
                        accessorList.CloseBraceToken.SpanStart);

                    IndexerDeclarationSyntax newNode = indexerDeclaration.RemoveWhitespace(span);

                    newNode = newNode.WithFormatterAnnotation();

                    return(await document.ReplaceNodeAsync(indexerDeclaration, newNode, cancellationToken).ConfigureAwait(false));
                }

                default:
                {
                    SyntaxDebug.Fail(parent);
                    return(document);
                }
                }
            }
            else
            {
                AccessorListSyntax newAccessorList = GetNewAccessorList(accessorList);

                newAccessorList = AddNewLineAfterFirstAccessorIfNecessary(accessorList, newAccessorList, cancellationToken);

                newAccessorList = newAccessorList.WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(accessorList, newAccessorList, cancellationToken).ConfigureAwait(false));
            }
        }
예제 #6
0
        public static Task <Document> RefactorAsync(
            Document document,
            BinaryExpressionSyntax binaryExpression,
            CancellationToken cancellationToken)
        {
            ExpressionSyntax left  = binaryExpression.Left;
            ExpressionSyntax right = binaryExpression.Right;

            ExpressionSyntax newNode = binaryExpression;

            TextSpan span = TextSpan.FromBounds(left.Span.End, right.SpanStart);

            IEnumerable <SyntaxTrivia> trivia = binaryExpression.DescendantTrivia(span);

            bool isWhiteSpaceOrEndOfLine = trivia.All(f => f.IsWhitespaceOrEndOfLineTrivia());

            if (IsBooleanLiteralExpression(left.Kind()))
            {
                SyntaxTriviaList leadingTrivia = binaryExpression.GetLeadingTrivia();

                if (!isWhiteSpaceOrEndOfLine)
                {
                    leadingTrivia = leadingTrivia.AddRange(trivia);
                }

                newNode = right.WithLeadingTrivia(leadingTrivia);
            }
            else if (IsBooleanLiteralExpression(right.Kind()))
            {
                SyntaxTriviaList trailingTrivia = binaryExpression.GetTrailingTrivia();

                if (!isWhiteSpaceOrEndOfLine)
                {
                    trailingTrivia = trailingTrivia.InsertRange(0, trivia);
                }

                newNode = left.WithTrailingTrivia(trailingTrivia);
            }
            else
            {
                SyntaxDebug.Fail(binaryExpression);
            }

            return(document.ReplaceNodeAsync(binaryExpression, newNode.WithFormatterAnnotation(), cancellationToken));
        }
        private static InvocationExpressionSyntax GetNewInvocation(InvocationExpressionSyntax invocation)
        {
            ExpressionSyntax   expression   = invocation.Expression;
            ArgumentListSyntax argumentList = invocation.ArgumentList;
            SeparatedSyntaxList <ArgumentSyntax> arguments = argumentList.Arguments;
            ArgumentSyntax argument = arguments[0];

            MemberAccessExpressionSyntax newMemberAccess = CreateNewMemberAccessExpression();

            if (newMemberAccess == null)
            {
                return(null);
            }

            return(invocation
                   .WithExpression(newMemberAccess)
                   .WithArgumentList(argumentList.WithArguments(arguments.Remove(argument))));

            MemberAccessExpressionSyntax CreateNewMemberAccessExpression()
            {
                switch (expression.Kind())
                {
                case SyntaxKind.IdentifierName:
                case SyntaxKind.GenericName:
                {
                    return(SimpleMemberAccessExpression(
                               ParenthesizedExpression(argument.Expression),
                               (SimpleNameSyntax)expression));
                }

                case SyntaxKind.SimpleMemberAccessExpression:
                {
                    var memberAccess = (MemberAccessExpressionSyntax)expression;

                    return(memberAccess.WithExpression(ParenthesizedExpression(argument.Expression)));
                }

                default:
                {
                    SyntaxDebug.Fail(expression);
                    return(null);
                }
                }
            }
        }
예제 #8
0
        public override bool CanBeRenamed(SyntaxToken token)
        {
            switch (token.Kind())
            {
            case SyntaxKind.IdentifierToken:
                return(true);

            case SyntaxKind.ThisKeyword:
            case SyntaxKind.BaseKeyword:
            case SyntaxKind.GetKeyword:
            case SyntaxKind.SetKeyword:
            case SyntaxKind.AddKeyword:
            case SyntaxKind.RemoveKeyword:
                return(false);
            }

            SyntaxDebug.Fail(token);

            return(false);
        }
        private static SyntaxKind GetBinaryExpressionKind(AssignmentExpressionSyntax assignmentExpression)
        {
            switch (assignmentExpression.Kind())
            {
            case SyntaxKind.AddAssignmentExpression:
                return(SyntaxKind.AddExpression);

            case SyntaxKind.SubtractAssignmentExpression:
                return(SyntaxKind.SubtractExpression);

            case SyntaxKind.MultiplyAssignmentExpression:
                return(SyntaxKind.MultiplyExpression);

            case SyntaxKind.DivideAssignmentExpression:
                return(SyntaxKind.DivideExpression);

            case SyntaxKind.ModuloAssignmentExpression:
                return(SyntaxKind.ModuloExpression);

            case SyntaxKind.AndAssignmentExpression:
                return(SyntaxKind.BitwiseAndExpression);

            case SyntaxKind.OrAssignmentExpression:
                return(SyntaxKind.BitwiseOrExpression);

            case SyntaxKind.ExclusiveOrAssignmentExpression:
                return(SyntaxKind.ExclusiveOrExpression);

            case SyntaxKind.LeftShiftAssignmentExpression:
                return(SyntaxKind.LeftShiftExpression);

            case SyntaxKind.RightShiftAssignmentExpression:
                return(SyntaxKind.RightShiftExpression);
            }

            SyntaxDebug.Fail(assignmentExpression);
            return(SyntaxKind.None);
        }
        private static (ISymbol symbol, ITypeSymbol typeSymbol) GetContainingSymbolAndType(
            ExpressionSyntax expression,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default)
        {
            switch (semanticModel.GetEnclosingSymbol(expression.SpanStart, cancellationToken))
            {
            case IMethodSymbol methodSymbol:
            {
                MethodKind methodKind = methodSymbol.MethodKind;

                if (methodKind == MethodKind.PropertyGet)
                {
                    var propertySymbol = (IPropertySymbol)methodSymbol.AssociatedSymbol;

                    return(propertySymbol, propertySymbol.Type);
                }

                if (methodKind == MethodKind.Ordinary &&
                    methodSymbol.PartialImplementationPart != null)
                {
                    methodSymbol = methodSymbol.PartialImplementationPart;
                }

                return(methodSymbol, methodSymbol.ReturnType);
            }

            case IFieldSymbol fieldSymbol:
            {
                return(fieldSymbol, fieldSymbol.Type);
            }
            }

            SyntaxDebug.Fail(expression);

            return(default((ISymbol, ITypeSymbol)));
        }
        private static void AnalyzeNameEquals(SyntaxNodeAnalysisContext context)
        {
            var node = (NameEqualsSyntax)context.Node;

            switch (node.Parent.Kind())
            {
            case SyntaxKind.AttributeArgument:
            {
                var attributeArgument = (AttributeArgumentSyntax)node.Parent;

                Analyze(context, attributeArgument.NameEquals.EqualsToken, attributeArgument.Expression);
                break;
            }

            case SyntaxKind.AnonymousObjectMemberDeclarator:
            {
                var declarator = (AnonymousObjectMemberDeclaratorSyntax)node.Parent;

                Analyze(context, declarator.NameEquals.EqualsToken, declarator.Expression);
                break;
            }

            case SyntaxKind.UsingDirective:
            {
                var usingDirective = (UsingDirectiveSyntax)node.Parent;

                Analyze(context, usingDirective.Alias.EqualsToken, usingDirective.Name);
                break;
            }

            default:
            {
                SyntaxDebug.Fail(node.Parent);
                break;
            }
            }
        }
예제 #12
0
            public override SyntaxNode VisitYieldStatement(YieldStatementSyntax node)
            {
                SyntaxToken      keyword    = node.ReturnOrBreakKeyword;
                ExpressionSyntax expression = node.Expression;

                SyntaxKind kind = node.Kind();

                if (kind == SyntaxKind.YieldReturnStatement)
                {
                    ParenthesizedExpressionSyntax parenthesizedExpression = expression.Parenthesize();

                    CastExpressionSyntax castExpression = CastExpression(
                        _typeSymbol.ToMinimalTypeSyntax(_semanticModel, node.SpanStart),
                        parenthesizedExpression);

                    InvocationExpressionSyntax invocationExpression = SimpleMemberInvocationExpression(
                        _identifierName,
                        _addName,
                        Argument(castExpression.WithSimplifierAnnotation()));

                    return(ExpressionStatement(invocationExpression.WithoutTrivia())
                           .WithTriviaFrom(node)
                           .AppendToLeadingTrivia(node.DescendantTrivia(TextSpan.FromBounds(keyword.Span.End, expression.SpanStart))));
                }
                else if (kind == SyntaxKind.YieldBreakStatement)
                {
                    return(ReturnStatement(
                               Token(keyword.LeadingTrivia, SyntaxKind.ReturnKeyword, keyword.TrailingTrivia),
                               _identifierName,
                               node.SemicolonToken));
                }

                SyntaxDebug.Fail(node);

                return(base.VisitYieldStatement(node));
            }
예제 #13
0
        internal static bool IsFixable(
            PropertyDeclarationSyntax propertyDeclaration,
            AccessorDeclarationSyntax accessor,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            switch (accessor.Kind())
            {
            case SyntaxKind.GetAccessorDeclaration:
            {
                ExpressionSyntax expression = GetGetAccessorExpression(accessor);

                if (expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) != true)
                {
                    return(false);
                }

                var memberAccess = (MemberAccessExpressionSyntax)expression;

                if (memberAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true)
                {
                    return(false);
                }

                SimpleNameSyntax simpleName = memberAccess.Name;

                IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken);

                if (propertySymbol == null)
                {
                    return(false);
                }

                IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty;

                if (overriddenProperty == null)
                {
                    return(false);
                }

                ISymbol symbol = semanticModel.GetSymbol(simpleName, cancellationToken);

                return(SymbolEqualityComparer.Default.Equals(overriddenProperty, symbol));
            }

            case SyntaxKind.SetAccessorDeclaration:
            {
                ExpressionSyntax expression = GetSetAccessorExpression(accessor);

                SimpleAssignmentExpressionInfo assignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expression);

                if (!assignment.Success)
                {
                    return(false);
                }

                if (assignment.Left.Kind() != SyntaxKind.SimpleMemberAccessExpression)
                {
                    return(false);
                }

                var memberAccess = (MemberAccessExpressionSyntax)assignment.Left;

                if (memberAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true)
                {
                    return(false);
                }

                if (assignment.Right.Kind() != SyntaxKind.IdentifierName)
                {
                    return(false);
                }

                var identifierName = (IdentifierNameSyntax)assignment.Right;

                if (identifierName.Identifier.ValueText != "value")
                {
                    return(false);
                }

                SimpleNameSyntax simpleName = memberAccess.Name;

                if (simpleName == null)
                {
                    return(false);
                }

                IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken);

                if (propertySymbol == null)
                {
                    return(false);
                }

                IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty;

                if (overriddenProperty == null)
                {
                    return(false);
                }

                ISymbol symbol = semanticModel.GetSymbol(simpleName, cancellationToken);

                return(SymbolEqualityComparer.Default.Equals(overriddenProperty, symbol));
            }

            case SyntaxKind.UnknownAccessorDeclaration:
            {
                return(false);
            }

            default:
            {
                SyntaxDebug.Fail(accessor);
                return(false);
            }
            }
        }
        private static SyntaxNode Refactor(SyntaxNode node)
        {
            switch (node.Kind())
            {
            case SyntaxKind.MethodDeclaration:
                {
                    var methodDeclaration            = (MethodDeclarationSyntax)node;
                    BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(methodDeclaration.Body);

                    return(methodDeclaration
                           .WithExpressionBody(CreateExpressionBody(analysis, methodDeclaration))
                           .WithSemicolonToken(CreateSemicolonToken(methodDeclaration.Body, analysis))
                           .WithBody(null));
                }

            case SyntaxKind.ConstructorDeclaration:
                {
                    var constructorDeclaration       = (ConstructorDeclarationSyntax)node;
                    BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(constructorDeclaration.Body);

                    return(constructorDeclaration
                           .WithExpressionBody(CreateExpressionBody(analysis, constructorDeclaration))
                           .WithSemicolonToken(CreateSemicolonToken(constructorDeclaration.Body, analysis))
                           .WithBody(null));
                }

            case SyntaxKind.DestructorDeclaration:
                {
                    var destructorDeclaration        = (DestructorDeclarationSyntax)node;
                    BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(destructorDeclaration.Body);

                    return(destructorDeclaration
                           .WithExpressionBody(CreateExpressionBody(analysis, destructorDeclaration))
                           .WithSemicolonToken(CreateSemicolonToken(destructorDeclaration.Body, analysis))
                           .WithBody(null));
                }

            case SyntaxKind.LocalFunctionStatement:
                {
                    var localFunction = (LocalFunctionStatementSyntax)node;
                    BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(localFunction.Body);

                    return(localFunction
                           .WithExpressionBody(CreateExpressionBody(analysis, localFunction))
                           .WithSemicolonToken(CreateSemicolonToken(localFunction.Body, analysis))
                           .WithBody(null));
                }

            case SyntaxKind.OperatorDeclaration:
            {
                var operatorDeclaration          = (OperatorDeclarationSyntax)node;
                BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(operatorDeclaration.Body);

                return(operatorDeclaration
                       .WithExpressionBody(CreateExpressionBody(analysis, operatorDeclaration))
                       .WithSemicolonToken(CreateSemicolonToken(operatorDeclaration.Body, analysis))
                       .WithBody(null));
            }

            case SyntaxKind.ConversionOperatorDeclaration:
            {
                var operatorDeclaration          = (ConversionOperatorDeclarationSyntax)node;
                BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(operatorDeclaration.Body);

                return(operatorDeclaration
                       .WithExpressionBody(CreateExpressionBody(analysis, operatorDeclaration))
                       .WithSemicolonToken(CreateSemicolonToken(operatorDeclaration.Body, analysis))
                       .WithBody(null));
            }

            case SyntaxKind.PropertyDeclaration:
            {
                var propertyDeclaration          = (PropertyDeclarationSyntax)node;
                BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(propertyDeclaration.AccessorList);

                return(propertyDeclaration
                       .WithExpressionBody(CreateExpressionBody(analysis, propertyDeclaration))
                       .WithSemicolonToken(CreateSemicolonToken(analysis.Block, analysis))
                       .WithAccessorList(null));
            }

            case SyntaxKind.IndexerDeclaration:
            {
                var indexerDeclaration           = (IndexerDeclarationSyntax)node;
                BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(indexerDeclaration.AccessorList);

                return(indexerDeclaration
                       .WithExpressionBody(CreateExpressionBody(analysis, indexerDeclaration))
                       .WithSemicolonToken(CreateSemicolonToken(analysis.Block, analysis))
                       .WithAccessorList(null));
            }

            case SyntaxKind.GetAccessorDeclaration:
            case SyntaxKind.SetAccessorDeclaration:
            case SyntaxKind.InitAccessorDeclaration:
            case SyntaxKind.AddAccessorDeclaration:
            case SyntaxKind.RemoveAccessorDeclaration:
            {
                var accessor = (AccessorDeclarationSyntax)node;
                BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(accessor);

                return(accessor
                       .WithExpressionBody(CreateExpressionBody(analysis, accessor))
                       .WithSemicolonToken(CreateSemicolonToken(analysis.Block, analysis))
                       .WithBody(null));
            }

            default:
            {
                SyntaxDebug.Fail(node);
                return(node);
            }
            }
        }
예제 #15
0
        private static async Task <Document> RefactorAsync(
            Document document,
            ConditionalAccessExpressionSyntax conditionalAccess,
            CancellationToken cancellationToken)
        {
            ExpressionSyntax expression = conditionalAccess.Expression;

            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            int position = conditionalAccess.SpanStart;

            string localName = NameGenerator.Default.EnsureUniqueLocalName(DefaultNames.Variable, semanticModel, position);

            ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression, cancellationToken);

            TypeSyntax type = (typeSymbol?.SupportsExplicitDeclaration() == true)
                ? typeSymbol.ToMinimalTypeSyntax(semanticModel, position)
                : VarType();

            LocalDeclarationStatementSyntax localStatement = LocalDeclarationStatement(
                type,
                Identifier(localName).WithRenameAnnotation(),
                expression);

            ExpressionSyntax newExpression = ReturnCompletedTaskInsteadOfNullCodeFixProvider.CreateCompletedTaskExpression(document, conditionalAccess, semanticModel, cancellationToken);

            IfStatementSyntax ifStatement = IfStatement(
                NotEqualsExpression(IdentifierName(localName), NullLiteralExpression()),
                Block(ReturnStatement(conditionalAccess
                                      .WithExpression(IdentifierName(localName).WithTriviaFrom(conditionalAccess.Expression))
                                      .RemoveOperatorToken())),
                ElseClause(Block(ReturnStatement(newExpression))));

            SyntaxList <StatementSyntax> statements = List(new StatementSyntax[] { localStatement, ifStatement });

            SyntaxNode parent = conditionalAccess.Parent;

            if (parent is ReturnStatementSyntax returnStatement)
            {
                statements = statements.WithTriviaFrom(returnStatement);

                if (returnStatement.IsEmbedded())
                {
                    return(await document.ReplaceNodeAsync(returnStatement, Block(statements), cancellationToken).ConfigureAwait(false));
                }
                else
                {
                    return(await document.ReplaceNodeAsync(returnStatement, statements, cancellationToken).ConfigureAwait(false));
                }
            }
            else if (parent is SimpleLambdaExpressionSyntax simpleLambda)
            {
                SimpleLambdaExpressionSyntax newNode = simpleLambda
                                                       .WithBody(Block(statements))
                                                       .WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(simpleLambda, newNode, cancellationToken).ConfigureAwait(false));
            }
            else if (parent is ParenthesizedLambdaExpressionSyntax parenthesizedLambda)
            {
                ParenthesizedLambdaExpressionSyntax newNode = parenthesizedLambda
                                                              .WithBody(Block(statements))
                                                              .WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(parenthesizedLambda, newNode, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                var arrowExpressionClause = (ArrowExpressionClauseSyntax)parent;

                SyntaxNode node = arrowExpressionClause.Parent;

                SyntaxNode newNode = CreateNewNode(node).WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(node, newNode, cancellationToken).ConfigureAwait(false));
            }

            SyntaxNode CreateNewNode(SyntaxNode node)
            {
                switch (node)
                {
                case MethodDeclarationSyntax methodDeclaration:
                {
                    return(methodDeclaration
                           .WithExpressionBody(null)
                           .WithBody(Block(statements)));
                }

                case LocalFunctionStatementSyntax localFunction:
                {
                    return(localFunction
                           .WithExpressionBody(null)
                           .WithBody(Block(statements)));
                }

                case PropertyDeclarationSyntax propertyDeclaration:
                {
                    return(propertyDeclaration
                           .WithExpressionBody(null)
                           .WithSemicolonToken(default(SyntaxToken))
                           .WithAccessorList(AccessorList(GetAccessorDeclaration(Block(statements)))));
                }

                case IndexerDeclarationSyntax indexerDeclaration:
                {
                    return(indexerDeclaration
                           .WithExpressionBody(null)
                           .WithSemicolonToken(default(SyntaxToken))
                           .WithAccessorList(AccessorList(GetAccessorDeclaration(Block(statements)))));
                }

                case AccessorDeclarationSyntax accessorDeclaration:
                {
                    return(accessorDeclaration
                           .WithExpressionBody(null)
                           .WithSemicolonToken(default(SyntaxToken))
                           .WithBody(Block(statements)));
                }

                default:
                {
                    SyntaxDebug.Fail(node);
                    return(node);
                }
                }
            }
        }
예제 #16
0
        private static void AnalyzeSingleLineDocumentationCommentTrivia(SyntaxNodeAnalysisContext context)
        {
            var documentationComment = (DocumentationCommentTriviaSyntax)context.Node;

            if (!documentationComment.IsPartOfMemberDeclaration())
            {
                return;
            }

            bool?useCorrectDocumentationTagEnabled = null;
            var  containsInheritDoc       = false;
            var  containsIncludeOrExclude = false;
            var  containsSummaryElement   = false;
            var  containsContentElement   = false;
            var  isFirst = true;

            CancellationToken cancellationToken = context.CancellationToken;

            SyntaxList <XmlNodeSyntax> content = documentationComment.Content;

            for (int i = 0; i < content.Count; i++)
            {
                cancellationToken.ThrowIfCancellationRequested();

                XmlElementInfo info = SyntaxInfo.XmlElementInfo(content[i]);

                if (info.Success)
                {
                    switch (info.GetTag())
                    {
                    case XmlTag.Include:
                    case XmlTag.Exclude:
                    {
                        if (isFirst)
                        {
                            containsIncludeOrExclude = true;
                        }

                        break;
                    }

                    case XmlTag.InheritDoc:
                    {
                        containsInheritDoc = true;
                        break;
                    }

                    case XmlTag.Content:
                    {
                        containsContentElement = true;
                        break;
                    }

                    case XmlTag.Summary:
                    {
                        if (info.IsContentEmptyOrWhitespace)
                        {
                            ReportDiagnosticIfEffective(context, DiagnosticRules.AddSummaryToDocumentationComment, info.Element);
                        }

                        containsSummaryElement = true;

                        if (useCorrectDocumentationTagEnabled ??= DiagnosticRules.FixDocumentationCommentTag.IsEffective(context))
                        {
                            FixDocumentationCommentTagAnalysis.Analyze(context, info);
                        }

                        break;
                    }

                    case XmlTag.Example:
                    case XmlTag.Remarks:
                    case XmlTag.Returns:
                    case XmlTag.Value:
                    {
                        if (info.IsContentEmptyOrWhitespace)
                        {
                            ReportUnusedElement(context, info.Element, i, content);
                        }

                        if (useCorrectDocumentationTagEnabled ??= DiagnosticRules.FixDocumentationCommentTag.IsEffective(context))
                        {
                            FixDocumentationCommentTagAnalysis.Analyze(context, info);
                        }

                        break;
                    }

                    case XmlTag.Exception:
                    case XmlTag.List:
                    case XmlTag.Param:
                    case XmlTag.Permission:
                    case XmlTag.TypeParam:
                    {
                        if (useCorrectDocumentationTagEnabled ??= DiagnosticRules.FixDocumentationCommentTag.IsEffective(context))
                        {
                            FixDocumentationCommentTagAnalysis.Analyze(context, info);
                        }

                        break;
                    }

                    case XmlTag.C:
                    case XmlTag.Code:
                    case XmlTag.Para:
                    case XmlTag.ParamRef:
                    case XmlTag.See:
                    case XmlTag.SeeAlso:
                    case XmlTag.TypeParamRef:
                    {
                        break;
                    }

                    default:
                    {
                        SyntaxDebug.Fail(content[i]);
                        break;
                    }
                    }

                    if (isFirst)
                    {
                        isFirst = false;
                    }
                    else
                    {
                        containsIncludeOrExclude = false;
                    }
                }
            }

            if (containsInheritDoc ||
                containsIncludeOrExclude)
            {
                return;
            }

            if (!containsSummaryElement &&
                !containsContentElement)
            {
                ReportDiagnosticIfEffective(context, DiagnosticRules.AddSummaryElementToDocumentationComment, documentationComment);
            }

            SyntaxNode parent = documentationComment.ParentTrivia.Token.Parent;

            bool unusedElement = DiagnosticRules.UnusedElementInDocumentationComment.IsEffective(context);
            bool orderParams   = DiagnosticRules.OrderElementsInDocumentationComment.IsEffective(context);
            bool addParam      = DiagnosticRules.AddParamElementToDocumentationComment.IsEffective(context);
            bool addTypeParam  = DiagnosticRules.AddTypeParamElementToDocumentationComment.IsEffective(context);

            if (addParam ||
                orderParams ||
                unusedElement)
            {
                SeparatedSyntaxList <ParameterSyntax> parameters = CSharpUtility.GetParameters(
                    (parent is MemberDeclarationSyntax) ? parent : parent.Parent);

                if (addParam &&
                    parameters.Any())
                {
                    foreach (ParameterSyntax parameter in parameters)
                    {
                        if (IsMissing(documentationComment, parameter))
                        {
                            ReportDiagnostic(context, DiagnosticRules.AddParamElementToDocumentationComment, documentationComment);
                            break;
                        }
                    }
                }

                if (orderParams || unusedElement)
                {
                    Analyze(context, documentationComment.Content, parameters, XmlTag.Param, (nodes, name) => nodes.IndexOf(name));
                }
            }

            if (addTypeParam ||
                orderParams ||
                unusedElement)
            {
                SeparatedSyntaxList <TypeParameterSyntax> typeParameters = CSharpUtility.GetTypeParameters(
                    (parent is MemberDeclarationSyntax) ? parent : parent.Parent);

                if (addTypeParam &&
                    typeParameters.Any())
                {
                    foreach (TypeParameterSyntax typeParameter in typeParameters)
                    {
                        if (IsMissing(documentationComment, typeParameter))
                        {
                            ReportDiagnostic(context, DiagnosticRules.AddTypeParamElementToDocumentationComment, documentationComment);
                            break;
                        }
                    }
                }

                if (orderParams || unusedElement)
                {
                    Analyze(context, documentationComment.Content, typeParameters, XmlTag.TypeParam, (nodes, name) => nodes.IndexOf(name));
                }
            }
        }
예제 #17
0
        public virtual void VisitStatement(StatementSyntax node)
        {
            switch (node.Kind())
            {
            case SyntaxKind.Block:
            {
                VisitBlock((BlockSyntax)node);
                break;
            }

            case SyntaxKind.BreakStatement:
            {
                VisitBreakStatement((BreakStatementSyntax)node);
                break;
            }

            case SyntaxKind.ContinueStatement:
            {
                VisitContinueStatement((ContinueStatementSyntax)node);
                break;
            }

            case SyntaxKind.DoStatement:
            {
                VisitDoStatement((DoStatementSyntax)node);
                break;
            }

            case SyntaxKind.EmptyStatement:
            {
                VisitEmptyStatement((EmptyStatementSyntax)node);
                break;
            }

            case SyntaxKind.ExpressionStatement:
            {
                VisitExpressionStatement((ExpressionStatementSyntax)node);
                break;
            }

            case SyntaxKind.FixedStatement:
            {
                VisitFixedStatement((FixedStatementSyntax)node);
                break;
            }

            case SyntaxKind.ForEachStatement:
            {
                VisitForEachStatement((ForEachStatementSyntax)node);
                break;
            }

            case SyntaxKind.ForEachVariableStatement:
            {
                VisitForEachVariableStatement((ForEachVariableStatementSyntax)node);
                break;
            }

            case SyntaxKind.ForStatement:
            {
                VisitForStatement((ForStatementSyntax)node);
                break;
            }

            case SyntaxKind.GotoStatement:
            case SyntaxKind.GotoCaseStatement:
            case SyntaxKind.GotoDefaultStatement:
            {
                VisitGotoStatement((GotoStatementSyntax)node);
                break;
            }

            case SyntaxKind.CheckedStatement:
            case SyntaxKind.UncheckedStatement:
            {
                VisitCheckedStatement((CheckedStatementSyntax)node);
                break;
            }

            case SyntaxKind.IfStatement:
            {
                VisitIfStatement((IfStatementSyntax)node);
                break;
            }

            case SyntaxKind.LabeledStatement:
            {
                VisitLabeledStatement((LabeledStatementSyntax)node);
                break;
            }

            case SyntaxKind.LocalDeclarationStatement:
            {
                VisitLocalDeclarationStatement((LocalDeclarationStatementSyntax)node);
                break;
            }

            case SyntaxKind.LocalFunctionStatement:
            {
                VisitLocalFunctionStatement((LocalFunctionStatementSyntax)node);
                break;
            }

            case SyntaxKind.LockStatement:
            {
                VisitLockStatement((LockStatementSyntax)node);
                break;
            }

            case SyntaxKind.ReturnStatement:
            {
                VisitReturnStatement((ReturnStatementSyntax)node);
                break;
            }

            case SyntaxKind.SwitchStatement:
            {
                VisitSwitchStatement((SwitchStatementSyntax)node);
                break;
            }

            case SyntaxKind.ThrowStatement:
            {
                VisitThrowStatement((ThrowStatementSyntax)node);
                break;
            }

            case SyntaxKind.TryStatement:
            {
                VisitTryStatement((TryStatementSyntax)node);
                break;
            }

            case SyntaxKind.UnsafeStatement:
            {
                VisitUnsafeStatement((UnsafeStatementSyntax)node);
                break;
            }

            case SyntaxKind.UsingStatement:
            {
                VisitUsingStatement((UsingStatementSyntax)node);
                break;
            }

            case SyntaxKind.WhileStatement:
            {
                VisitWhileStatement((WhileStatementSyntax)node);
                break;
            }

            case SyntaxKind.YieldBreakStatement:
            case SyntaxKind.YieldReturnStatement:
            {
                VisitYieldStatement((YieldStatementSyntax)node);
                break;
            }

            default:
            {
                SyntaxDebug.Fail(node);
                Visit(node);
                break;
            }
            }
        }
예제 #18
0
        private static Func <CancellationToken, Task <Document> > GetCreateChangedDocument(CodeFixContext context, SyntaxNode node)
        {
            switch (node.Kind())
            {
            case SyntaxKind.MethodDeclaration:
            {
                var methodDeclaration = (MethodDeclarationSyntax)node;

                SyntaxToken semicolonToken = methodDeclaration.SemicolonToken;

                if (semicolonToken.IsKind(SyntaxKind.None))
                {
                    break;
                }

                ParameterListSyntax parameterList = methodDeclaration.ParameterList;

                if (parameterList == null)
                {
                    break;
                }

                return(ct =>
                    {
                        MethodDeclarationSyntax newNode = methodDeclaration
                                                          .WithParameterList(parameterList.AppendToTrailingTrivia(semicolonToken.GetAllTrivia()))
                                                          .WithSemicolonToken(default(SyntaxToken))
                                                          .WithBody(Block())
                                                          .WithFormatterAnnotation();

                        return context.Document.ReplaceNodeAsync(node, newNode, ct);
                    });
            }

            case SyntaxKind.ConstructorDeclaration:
            {
                var constructorDeclaration = (ConstructorDeclarationSyntax)node;

                SyntaxToken semicolonToken = constructorDeclaration.SemicolonToken;

                if (semicolonToken.IsKind(SyntaxKind.None))
                {
                    break;
                }

                ParameterListSyntax parameterList = constructorDeclaration.ParameterList;

                if (parameterList == null)
                {
                    break;
                }

                return(ct =>
                    {
                        ConstructorDeclarationSyntax newNode = constructorDeclaration
                                                               .WithParameterList(parameterList.AppendToTrailingTrivia(semicolonToken.GetAllTrivia()))
                                                               .WithSemicolonToken(default(SyntaxToken))
                                                               .WithBody(Block())
                                                               .WithFormatterAnnotation();

                        return context.Document.ReplaceNodeAsync(node, newNode, ct);
                    });
            }

            case SyntaxKind.DestructorDeclaration:
            {
                var destructorDeclaration = (DestructorDeclarationSyntax)node;

                SyntaxToken semicolonToken = destructorDeclaration.SemicolonToken;

                if (semicolonToken.IsKind(SyntaxKind.None))
                {
                    break;
                }

                ParameterListSyntax parameterList = destructorDeclaration.ParameterList;

                if (parameterList == null)
                {
                    break;
                }

                return(ct =>
                    {
                        DestructorDeclarationSyntax newNode = destructorDeclaration
                                                              .WithParameterList(parameterList.AppendToTrailingTrivia(semicolonToken.GetAllTrivia()))
                                                              .WithSemicolonToken(default(SyntaxToken))
                                                              .WithBody(Block())
                                                              .WithFormatterAnnotation();

                        return context.Document.ReplaceNodeAsync(node, newNode, ct);
                    });
            }

            case SyntaxKind.OperatorDeclaration:
            {
                var operatorDeclaration = (OperatorDeclarationSyntax)node;

                SyntaxToken semicolonToken = operatorDeclaration.SemicolonToken;

                if (semicolonToken.IsKind(SyntaxKind.None))
                {
                    break;
                }

                ParameterListSyntax parameterList = operatorDeclaration.ParameterList;

                if (parameterList == null)
                {
                    break;
                }

                return(ct =>
                    {
                        OperatorDeclarationSyntax newNode = operatorDeclaration
                                                            .WithParameterList(parameterList.AppendToTrailingTrivia(semicolonToken.GetAllTrivia()))
                                                            .WithSemicolonToken(default(SyntaxToken))
                                                            .WithBody(Block())
                                                            .WithFormatterAnnotation();

                        return context.Document.ReplaceNodeAsync(node, newNode, ct);
                    });
            }

            case SyntaxKind.ConversionOperatorDeclaration:
            {
                var conversionOperatorDeclaration = (ConversionOperatorDeclarationSyntax)node;

                SyntaxToken semicolonToken = conversionOperatorDeclaration.SemicolonToken;

                if (semicolonToken.IsKind(SyntaxKind.None))
                {
                    break;
                }

                ParameterListSyntax parameterList = conversionOperatorDeclaration.ParameterList;

                if (parameterList == null)
                {
                    break;
                }

                return(ct =>
                    {
                        ConversionOperatorDeclarationSyntax newNode = conversionOperatorDeclaration
                                                                      .WithParameterList(parameterList.AppendToTrailingTrivia(semicolonToken.GetAllTrivia()))
                                                                      .WithSemicolonToken(default(SyntaxToken))
                                                                      .WithBody(Block())
                                                                      .WithFormatterAnnotation();

                        return context.Document.ReplaceNodeAsync(node, newNode, ct);
                    });
            }

            case SyntaxKind.GetAccessorDeclaration:
            case SyntaxKind.SetAccessorDeclaration:
            {
                var accessorDeclaration = (AccessorDeclarationSyntax)node;

                SyntaxToken semicolonToken = accessorDeclaration.SemicolonToken;

                if (semicolonToken.IsKind(SyntaxKind.None))
                {
                    break;
                }

                return(ct =>
                    {
                        AccessorDeclarationSyntax newNode = accessorDeclaration
                                                            .WithSemicolonToken(default(SyntaxToken))
                                                            .WithBody(Block(
                                                                          Token(default(SyntaxTriviaList), SyntaxKind.OpenBraceToken, TriviaList(ElasticSpace)),
                                                                          default(SyntaxList <StatementSyntax>),
                                                                          Token(default(SyntaxTriviaList), SyntaxKind.CloseBraceToken, semicolonToken.LeadingAndTrailingTrivia())));

                        SyntaxToken keyword = newNode.Keyword;

                        if (!keyword.HasTrailingTrivia)
                        {
                            newNode = newNode.WithKeyword(keyword.WithTrailingTrivia(ElasticSpace));
                        }

                        return context.Document.ReplaceNodeAsync(node, newNode, ct);
                    });
            }

            case SyntaxKind.LocalFunctionStatement:
            {
                var localFunction = (LocalFunctionStatementSyntax)node;

                SyntaxToken semicolonToken = localFunction.SemicolonToken;

                if (semicolonToken.IsKind(SyntaxKind.None))
                {
                    break;
                }

                ParameterListSyntax parameterList = localFunction.ParameterList;

                if (parameterList == null)
                {
                    break;
                }

                return(ct =>
                    {
                        LocalFunctionStatementSyntax newNode = localFunction
                                                               .WithParameterList(parameterList.AppendToTrailingTrivia(semicolonToken.GetAllTrivia()))
                                                               .WithSemicolonToken(default(SyntaxToken))
                                                               .WithBody(Block())
                                                               .WithFormatterAnnotation();

                        return context.Document.ReplaceNodeAsync(node, newNode, ct);
                    });
            }
            }

            SyntaxDebug.Fail(node);

            return(null);
        }
예제 #19
0
        public static ImmutableArray <ISymbol> FindLocalSymbols(
            SyntaxNode node,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default)
        {
            var walker = new LocalSymbolCollector(semanticModel, cancellationToken);

            switch (node.Kind())
            {
            case SyntaxKind.ConstructorDeclaration:
            {
                var constructor = (ConstructorDeclarationSyntax)node;
                walker.Visit(constructor.BodyOrExpressionBody());

                break;
            }

            case SyntaxKind.EventDeclaration:
            {
                var eventDeclaration = (EventDeclarationSyntax)node;

                foreach (AccessorDeclarationSyntax accessor in eventDeclaration.AccessorList.Accessors)
                {
                    walker.Visit(accessor.BodyOrExpressionBody());
                }

                break;
            }

            case SyntaxKind.IndexerDeclaration:
            {
                var indexerDeclaration = (IndexerDeclarationSyntax)node;

                foreach (AccessorDeclarationSyntax accessor in indexerDeclaration.AccessorList.Accessors)
                {
                    walker.Visit(accessor.BodyOrExpressionBody());
                }

                break;
            }

            case SyntaxKind.MethodDeclaration:
            {
                var methodDeclaration = (MethodDeclarationSyntax)node;

                walker.Visit(methodDeclaration.BodyOrExpressionBody());

                break;
            }

            case SyntaxKind.PropertyDeclaration:
            {
                var propertyDeclaration = (PropertyDeclarationSyntax)node;

                ArrowExpressionClauseSyntax expressionBody = propertyDeclaration.ExpressionBody;

                if (expressionBody != null)
                {
                    walker.Visit(expressionBody);
                }
                else
                {
                    foreach (AccessorDeclarationSyntax accessor in propertyDeclaration.AccessorList.Accessors)
                    {
                        walker.Visit(accessor.BodyOrExpressionBody());
                    }
                }

                break;
            }

            case SyntaxKind.VariableDeclarator:
            {
                var declarator = (VariableDeclaratorSyntax)node;

                ExpressionSyntax expression = declarator.Initializer?.Value;

                if (expression != null)
                {
                    walker.Visit(expression);
                }

                break;
            }

            case SyntaxKind.OperatorDeclaration:
            {
                var declaration = (OperatorDeclarationSyntax)node;

                walker.Visit(declaration.BodyOrExpressionBody());
                break;
            }

            case SyntaxKind.ConversionOperatorDeclaration:
            {
                var declaration = (ConversionOperatorDeclarationSyntax)node;

                walker.Visit(declaration.BodyOrExpressionBody());
                break;
            }

            default:
            {
                SyntaxDebug.Fail(node);

                walker.Visit(node);
                break;
            }
            }

            return(walker.Definitions.ToImmutableArray());
        }
        private static void AnalyzeAccessorDeclarationBlock(
            SyntaxNodeAnalysisContext context,
            AccessorDeclarationSyntax accessor,
            BlockSyntax body)
        {
            if (body.ContainsDirectives)
                return;

            if (accessor.AttributeLists.Any())
                return;

            BodyStyle style = context.GetBodyStyle();

            if (style.IsDefault)
                return;

            bool isGetter = accessor.IsKind(SyntaxKind.GetAccessorDeclaration);

            BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(body, allowExpressionStatement: !isGetter);

            ExpressionSyntax expression = analysis.Expression;

            if (expression == null)
                return;

            if (!style.UseExpression)
                return;

            if (style.UseBlockWhenExpressionIsMultiLine == true
                && expression.IsMultiLine())
            {
                return;
            }

            if (isGetter
                && accessor.Parent is AccessorListSyntax accessorList
                && accessorList.Accessors.Count == 1)
            {
                if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(accessorList.OpenBraceToken))
                    return;

                if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(accessor.Keyword))
                    return;

                if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(body.OpenBraceToken))
                    return;

                if (style.UseBlockWhenDeclarationIsMultiLine == true)
                {
                    switch (accessorList.Parent.Kind())
                    {
                        case SyntaxKind.PropertyDeclaration:
                            {
                                if (accessor.SyntaxTree.IsMultiLineSpan(((PropertyDeclarationSyntax)accessorList.Parent).HeaderSpan()))
                                    return;

                                break;
                            }
                        case SyntaxKind.IndexerDeclaration:
                            {
                                if (accessor.SyntaxTree.IsMultiLineSpan(((IndexerDeclarationSyntax)accessorList.Parent).HeaderSpan()))
                                    return;

                                break;
                            }
                        default:
                            {
                                SyntaxDebug.Fail(accessorList.Parent);
                                break;
                            }
                    }

                    return;
                }

                ReportDiagnostic(context, accessorList);
                return;
            }

            if (!accessor.Keyword.TrailingTrivia.IsEmptyOrWhitespace())
                return;

            if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(body.OpenBraceToken))
                return;

            if (!accessor.Keyword.LeadingTrivia.IsEmptyOrWhitespace())
                return;

            ReportDiagnostic(context, body);
        }
예제 #21
0
        public static void ComputeRefactoring(RefactoringContext context, SwitchStatementSyntax switchStatement)
        {
            SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections;

            var containsNonDefaultSection     = false;
            var containsSectionWithoutDefault = false;

            foreach (SwitchSectionSyntax section in sections)
            {
                var containsPattern = false;
                var containsDefault = false;

                foreach (SwitchLabelSyntax label in section.Labels)
                {
                    switch (label.Kind())
                    {
                    case SyntaxKind.CasePatternSwitchLabel:
                    {
                        containsPattern = true;
                        break;
                    }

                    case SyntaxKind.CaseSwitchLabel:
                    {
                        break;
                    }

                    case SyntaxKind.DefaultSwitchLabel:
                    {
                        containsDefault = true;
                        break;
                    }

                    default:
                    {
                        SyntaxDebug.Fail(label);
                        return;
                    }
                    }

                    if (containsDefault)
                    {
                        if (containsPattern)
                        {
                            return;
                        }
                    }
                    else
                    {
                        containsSectionWithoutDefault = true;
                    }
                }

                if (!containsDefault)
                {
                    containsNonDefaultSection = true;
                }
            }

            if (!containsNonDefaultSection)
            {
                return;
            }

            if (!containsSectionWithoutDefault)
            {
                return;
            }

            context.RegisterRefactoring(
                "Convert to 'if'",
                ct => ConvertSwitchToIfAsync(context.Document, switchStatement, ct),
                RefactoringDescriptors.ConvertSwitchToIf);
        }
예제 #22
0
        private static async Task <Document> RefactorAsync(
            Document document,
            StatementSyntax statement,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(statement);

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            int index = statements.IndexOf(statement);

            switch (statement)
            {
            case IfStatementSyntax ifStatement:
            {
                var expressionStatement = (ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault();

                var assignment = (AssignmentExpressionSyntax)expressionStatement.Expression;

                ExpressionSyntax left  = assignment.Left;
                ExpressionSyntax right = assignment.Right;

                BinaryExpressionSyntax coalesceExpression = CreateCoalesceExpression(
                    left.WithoutLeadingTrivia().WithTrailingTrivia(Space),
                    right.WithLeadingTrivia(Space),
                    semanticModel.GetTypeSymbol(left, cancellationToken),
                    semanticModel.GetTypeSymbol(right, cancellationToken));

                AssignmentExpressionSyntax newAssignment = assignment.WithRight(coalesceExpression.WithTriviaFrom(right));

                ExpressionStatementSyntax newNode = expressionStatement.WithExpression(newAssignment);

                IEnumerable <SyntaxTrivia> trivia = ifStatement.DescendantTrivia(TextSpan.FromBounds(ifStatement.SpanStart, expressionStatement.SpanStart));

                if (trivia.All(f => f.IsWhitespaceOrEndOfLineTrivia()))
                {
                    newNode = newNode.WithLeadingTrivia(ifStatement.GetLeadingTrivia());
                }
                else
                {
                    newNode = newNode
                              .WithLeadingTrivia(ifStatement.GetLeadingTrivia().Concat(trivia))
                              .WithFormatterAnnotation();
                }

                return(await document.ReplaceNodeAsync(ifStatement, newNode, cancellationToken).ConfigureAwait(false));
            }

            case ExpressionStatementSyntax expressionStatement:
            {
                var assignment = (AssignmentExpressionSyntax)expressionStatement.Expression;

                return(await RefactorAsync(document, expressionStatement, (IfStatementSyntax)statements[index + 1], index, statementsInfo, assignment.Right, semanticModel, cancellationToken).ConfigureAwait(false));
            }

            case LocalDeclarationStatementSyntax localDeclaration:
            {
                ExpressionSyntax value = localDeclaration
                                         .Declaration
                                         .Variables[0]
                                         .Initializer
                                         .Value;

                return(await RefactorAsync(document, localDeclaration, (IfStatementSyntax)statements[index + 1], index, statementsInfo, value, semanticModel, cancellationToken).ConfigureAwait(false));
            }

            default:
            {
                SyntaxDebug.Fail(statement);

                return(document);
            }
            }
        }
예제 #23
0
        internal static bool IsFixable(
            IndexerDeclarationSyntax indexerDeclaration,
            AccessorDeclarationSyntax accessor,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            switch (accessor.Kind())
            {
            case SyntaxKind.GetAccessorDeclaration:
            {
                ExpressionSyntax expression = GetGetAccessorExpression(accessor);

                if (expression is not ElementAccessExpressionSyntax elementAccess)
                {
                    return(false);
                }

                if (elementAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true)
                {
                    return(false);
                }

                if (elementAccess.ArgumentList == null)
                {
                    return(false);
                }

                IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(indexerDeclaration, cancellationToken);

                if (propertySymbol == null)
                {
                    return(false);
                }

                IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty;

                if (overriddenProperty == null)
                {
                    return(false);
                }

                ISymbol symbol = semanticModel.GetSymbol(elementAccess, cancellationToken);

                return(SymbolEqualityComparer.Default.Equals(overriddenProperty, symbol) &&
                       CheckParameters(indexerDeclaration.ParameterList, elementAccess.ArgumentList, semanticModel, cancellationToken) &&
                       CheckDefaultValues(propertySymbol.Parameters, overriddenProperty.Parameters));
            }

            case SyntaxKind.SetAccessorDeclaration:
            {
                ExpressionSyntax expression = GetSetAccessorExpression(accessor);

                SimpleAssignmentExpressionInfo assignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expression);

                if (!assignment.Success)
                {
                    return(false);
                }

                if (assignment.Left.Kind() != SyntaxKind.ElementAccessExpression)
                {
                    return(false);
                }

                var elementAccess = (ElementAccessExpressionSyntax)assignment.Left;

                if (elementAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true)
                {
                    return(false);
                }

                if (elementAccess.ArgumentList == null)
                {
                    return(false);
                }

                if (assignment.Right.Kind() != SyntaxKind.IdentifierName)
                {
                    return(false);
                }

                var identifierName = (IdentifierNameSyntax)assignment.Right;

                if (identifierName.Identifier.ValueText != "value")
                {
                    return(false);
                }

                IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(indexerDeclaration, cancellationToken);

                if (propertySymbol == null)
                {
                    return(false);
                }

                IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty;

                if (overriddenProperty == null)
                {
                    return(false);
                }

                ISymbol symbol = semanticModel.GetSymbol(elementAccess, cancellationToken);

                return(SymbolEqualityComparer.Default.Equals(overriddenProperty, symbol) &&
                       CheckParameters(indexerDeclaration.ParameterList, elementAccess.ArgumentList, semanticModel, cancellationToken) &&
                       CheckDefaultValues(propertySymbol.Parameters, overriddenProperty.Parameters));
            }

            case SyntaxKind.UnknownAccessorDeclaration:
            {
                return(false);
            }

            default:
            {
                SyntaxDebug.Fail(accessor);
                return(false);
            }
            }
        }
        private static void AnalyzeParenthesizedExpression(SyntaxNodeAnalysisContext context)
        {
            var parenthesizedExpression = (ParenthesizedExpressionSyntax)context.Node;

            ExpressionSyntax expression = parenthesizedExpression.Expression;

            if (expression?.IsMissing != false)
            {
                return;
            }

            SyntaxToken openParen = parenthesizedExpression.OpenParenToken;

            if (openParen.IsMissing)
            {
                return;
            }

            SyntaxToken closeParen = parenthesizedExpression.CloseParenToken;

            if (closeParen.IsMissing)
            {
                return;
            }

            SyntaxNode parent = parenthesizedExpression.Parent;

            SyntaxKind parentKind = parent.Kind();

            switch (parentKind)
            {
            case SyntaxKind.ParenthesizedExpression:
            case SyntaxKind.ArrowExpressionClause:
            case SyntaxKind.AttributeArgument:
            case SyntaxKind.Argument:
            case SyntaxKind.ExpressionStatement:
            case SyntaxKind.ReturnStatement:
            case SyntaxKind.YieldReturnStatement:
            case SyntaxKind.WhileStatement:
            case SyntaxKind.DoStatement:
            case SyntaxKind.UsingStatement:
            case SyntaxKind.LockStatement:
            case SyntaxKind.IfStatement:
            case SyntaxKind.SwitchStatement:
            case SyntaxKind.ArrayRankSpecifier:
            {
                ReportDiagnostic();
                break;
            }

            case SyntaxKind.LessThanExpression:
            case SyntaxKind.GreaterThanExpression:
            case SyntaxKind.LessThanOrEqualExpression:
            case SyntaxKind.GreaterThanOrEqualExpression:
            case SyntaxKind.EqualsExpression:
            case SyntaxKind.NotEqualsExpression:
            {
                if (expression.IsKind(SyntaxKind.IdentifierName) ||
                    expression is LiteralExpressionSyntax)
                {
                    ReportDiagnostic();
                }

                break;
            }

            case SyntaxKind.MultiplyExpression:
            case SyntaxKind.DivideExpression:
            case SyntaxKind.ModuloExpression:
            case SyntaxKind.AddExpression:
            case SyntaxKind.SubtractExpression:
            case SyntaxKind.LeftShiftExpression:
            case SyntaxKind.RightShiftExpression:
            case SyntaxKind.BitwiseAndExpression:
            case SyntaxKind.ExclusiveOrExpression:
            case SyntaxKind.BitwiseOrExpression:
            case SyntaxKind.LogicalAndExpression:
            case SyntaxKind.LogicalOrExpression:
            {
                SyntaxKind kind = expression.Kind();

                if (kind == SyntaxKind.IdentifierName ||
                    expression is LiteralExpressionSyntax)
                {
                    ReportDiagnostic();
                }
                else if (kind == parentKind &&
                         ((BinaryExpressionSyntax)parent).Left == parenthesizedExpression)
                {
                    ReportDiagnostic();
                }

                break;
            }

            case SyntaxKind.LogicalNotExpression:
            {
                switch (expression.Kind())
                {
                case SyntaxKind.IdentifierName:
                case SyntaxKind.GenericName:
                case SyntaxKind.InvocationExpression:
                case SyntaxKind.SimpleMemberAccessExpression:
                case SyntaxKind.ElementAccessExpression:
                case SyntaxKind.ConditionalAccessExpression:
                {
                    ReportDiagnostic();
                    break;
                }
                }

                break;
            }

            case SyntaxKind.SimpleAssignmentExpression:
            case SyntaxKind.AddAssignmentExpression:
            case SyntaxKind.SubtractAssignmentExpression:
            case SyntaxKind.MultiplyAssignmentExpression:
            case SyntaxKind.DivideAssignmentExpression:
            case SyntaxKind.ModuloAssignmentExpression:
            case SyntaxKind.AndAssignmentExpression:
            case SyntaxKind.ExclusiveOrAssignmentExpression:
            case SyntaxKind.OrAssignmentExpression:
            case SyntaxKind.LeftShiftAssignmentExpression:
            case SyntaxKind.RightShiftAssignmentExpression:
            {
                if (((AssignmentExpressionSyntax)parent).Left == parenthesizedExpression)
                {
                    ReportDiagnostic();
                }
                else if (expression.IsKind(SyntaxKind.IdentifierName) ||
                         expression is LiteralExpressionSyntax)
                {
                    ReportDiagnostic();
                }

                break;
            }

            case SyntaxKind.Interpolation:
            {
                if (!expression.IsKind(SyntaxKind.ConditionalExpression) &&
                    !expression.DescendantNodes().Any(f => f.IsKind(SyntaxKind.AliasQualifiedName)) &&
                    ((InterpolationSyntax)parent).Expression == parenthesizedExpression)
                {
                    ReportDiagnostic();
                }

                break;
            }

            case SyntaxKind.AwaitExpression:
            {
                if (parenthesizedExpression.Expression.IsKind(SyntaxKind.SwitchExpression))
                {
                    return;
                }

                if (CSharpFacts.GetOperatorPrecedence(expression.Kind()) <= CSharpFacts.GetOperatorPrecedence(SyntaxKind.AwaitExpression))
                {
                    ReportDiagnostic();
                }

                break;
            }

            case SyntaxKind.ArrayInitializerExpression:
            case SyntaxKind.CollectionInitializerExpression:
            {
                if (expression is not AssignmentExpressionSyntax)
                {
                    ReportDiagnostic();
                }

                break;
            }

            case SyntaxKind.SimpleLambdaExpression:
            case SyntaxKind.ParenthesizedLambdaExpression:
            {
                switch (parent.Parent.Kind())
                {
                case SyntaxKind.ParenthesizedExpression:
                case SyntaxKind.ArrowExpressionClause:
                case SyntaxKind.Argument:
                case SyntaxKind.ReturnStatement:
                case SyntaxKind.YieldReturnStatement:
                case SyntaxKind.SimpleAssignmentExpression:
                case SyntaxKind.AddAssignmentExpression:
                case SyntaxKind.SubtractAssignmentExpression:
                {
                    ReportDiagnostic();
                    break;
                }

#if DEBUG
                default:
                {
                    SyntaxDebug.Fail(parent.Parent);
                    break;
                }
#endif
                }

                break;
            }
            }

            void ReportDiagnostic()
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticRules.RemoveRedundantParentheses,
                    openParen.GetLocation(),
                    additionalLocations: ImmutableArray.Create(closeParen.GetLocation()));

                DiagnosticHelpers.ReportToken(context, DiagnosticRules.RemoveRedundantParenthesesFadeOut, openParen);
                DiagnosticHelpers.ReportToken(context, DiagnosticRules.RemoveRedundantParenthesesFadeOut, closeParen);
            }
        }