コード例 #1
0
        public static async Task <Document> RefactorAsync(
            Document document,
            ExpressionStatementSyntax statement,
            ReturnStatementSyntax returnStatement,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var block = (BlockSyntax)statement.Parent;

            SyntaxList <StatementSyntax> statements = block.Statements;

            int index = statements.IndexOf(statement);

            SyntaxList <StatementSyntax> newStatements = statements.RemoveAt(index);

            var assignmentExpression = (AssignmentExpressionSyntax)statement.Expression;

            ReturnStatementSyntax newReturnStatement = returnStatement
                                                       .WithExpression(assignmentExpression.Right)
                                                       .WithLeadingTrivia(assignmentExpression.GetLeadingTrivia())
                                                       .WithTrailingTrivia(returnStatement.GetTrailingTrivia())
                                                       .WithFormatterAnnotation();

            newStatements = newStatements.Replace(newStatements[index], newReturnStatement);

            root = root.ReplaceNode(block, block.WithStatements(newStatements));

            return(document.WithSyntaxRoot(root));
        }
        private static async Task <Document> MergeLocalDeclarationWithReturnStatementAsync(
            Document document,
            LocalDeclarationStatementSyntax localDeclaration,
            ReturnStatementSyntax returnStatement,
            BlockSyntax block,
            CancellationToken cancellationToken)
        {
            SyntaxNode oldRoot = await document.GetSyntaxRootAsync(cancellationToken);

            ReturnStatementSyntax newReturnStatement = returnStatement
                                                       .WithExpression(localDeclaration.Declaration.Variables[0].Initializer.Value.WithoutTrivia())
                                                       .WithLeadingTrivia(localDeclaration.GetLeadingTrivia())
                                                       .WithTrailingTrivia(returnStatement.GetTrailingTrivia())
                                                       .WithAdditionalAnnotations(Formatter.Annotation);

            int index = block.Statements.IndexOf(localDeclaration);

            SyntaxList <StatementSyntax> newStatements = block.Statements
                                                         .RemoveAt(index)
                                                         .RemoveAt(index)
                                                         .Insert(index, newReturnStatement);

            BlockSyntax newBlock = block.WithStatements(newStatements);

            SyntaxNode newRoot = oldRoot.ReplaceNode(block, newBlock);

            return(document.WithSyntaxRoot(newRoot));
        }
コード例 #3
0
        private async Task <Document> GenerateExplicitConversion(Document document, ReturnStatementSyntax returnStatement, CancellationToken cancellationToken)
        {
            var mappingEngine = await CreateMappingEngine(document, returnStatement, cancellationToken);

            var returnExpressionTypeInfo = mappingEngine.GetExpressionTypeInfo(returnStatement.Expression);
            var mappingExpression        = mappingEngine.MapExpression(returnStatement.Expression, returnExpressionTypeInfo.Type, returnExpressionTypeInfo.ConvertedType);

            return(await ReplaceNode(document, returnStatement, returnStatement.WithExpression(mappingExpression), cancellationToken));
        }
コード例 #4
0
        private async Task <Document> GenerateExplicitConversion(Document document, ReturnStatementSyntax returnStatement, CancellationToken cancellationToken)
        {
            var(mappingEngine, semanticModel) = await CreateMappingEngine(document, returnStatement, cancellationToken);

            var returnExpressionTypeInfo = mappingEngine.GetExpressionTypeInfo(returnStatement.Expression);
            var mappingExpression        = mappingEngine.MapExpression(returnStatement.Expression !.WithoutTrivia(), returnExpressionTypeInfo.GetAnnotatedType(), returnExpressionTypeInfo.GetAnnotatedTypeForConverted(), new MappingContext(returnStatement, semanticModel));

            return(await ReplaceNode(document, returnStatement, returnStatement.WithExpression(mappingExpression), cancellationToken));
        }
コード例 #5
0
        public static async Task <Document> RefactorAsync(
            Document document,
            ReturnStatementSyntax returnStatement,
            ITypeSymbol typeSymbol,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            ExpressionSyntax expression = typeSymbol.ToDefaultExpression();

            ReturnStatementSyntax newReturnStatement = returnStatement.WithExpression(expression);

            return(await document.ReplaceNodeAsync(returnStatement, newReturnStatement, cancellationToken).ConfigureAwait(false));
        }
コード例 #6
0
            public override SyntaxNode VisitReturnStatement(ReturnStatementSyntax node)
            {
                var newNode = node.WithExpression(
                    SyntaxFactory.InvocationExpression(
                        SyntaxFactory.MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            SyntaxFactory.ParseName("System.Threading.Tasks.Task")
                            .WithAdditionalAnnotations(Simplifier.Annotation),
                            SyntaxFactory.IdentifierName("FromResult")),
                        SyntaxFactory.ArgumentList().AddArguments(SyntaxFactory.Argument(node.Expression))));

                return(base.VisitReturnStatement(newNode));
            }
コード例 #7
0
        private async Task <Document> ReplaceWithEmptyEnumerable(Document document, ReturnStatementSyntax returnNullStatement, MethodDeclarationSyntax method, CancellationToken cancellationToken)
        {
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken);

            var typeSymbol          = semanticModel.GetSymbolInfo(method.ReturnType, cancellationToken).Symbol as INamedTypeSymbol;
            var genericTypeArgument = typeSymbol.TypeArguments.Single();

            var        empty = SyntaxFactory.ParseExpression($"Enumerable.Empty<{genericTypeArgument.Name}>()");
            var        returnEmptyStatement = returnNullStatement.WithExpression(empty);
            SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken);

            var newRoot = root.ReplaceNode(returnNullStatement, returnEmptyStatement);

            return(document.WithSyntaxRoot(newRoot));
        }
コード例 #8
0
 private SyntaxNode RewriteExit(ReturnStatementSyntax returnStatement)
 {
     return(returnStatement.WithExpression(
                InvocationExpression(
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        IdentifierName("Task"),
                        IdentifierName("FromResult")))
                .WithArgumentList(
                    ArgumentList(
                        SingletonSeparatedList <ArgumentSyntax>(
                            Argument(
                                returnStatement.Expression))))
                ));
 }
コード例 #9
0
        /// <summary>
        ///   Normalizes the <paramref name="statement" />.
        /// </summary>
        public override SyntaxNode VisitReturnStatement(ReturnStatementSyntax statement)
        {
            var methodSymbol = SemanticModel.GetEnclosingSymbol(statement.SpanStart) as IMethodSymbol;

            if (methodSymbol == null)
            {
                return(base.VisitReturnStatement(statement));
            }

            if (!IsFormulaType(methodSymbol.ReturnType))
            {
                return(base.VisitReturnStatement(statement));
            }

            return(statement.WithExpression(ReplaceImplicitConversion(statement.Expression)));
        }
コード例 #10
0
        public static async Task <Document> RefactorAsync(
            Document document,
            ReturnStatementSyntax returnStatement,
            ITypeSymbol typeSymbol,
            ISymbol symbol,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            ExpressionSyntax expression = SyntaxUtility.CreateDefaultValue(typeSymbol);

            root = root.ReplaceNode(
                returnStatement,
                returnStatement.WithExpression(expression));

            return(document.WithSyntaxRoot(root));
        }
コード例 #11
0
            public override SyntaxNode VisitReturnStatement(ReturnStatementSyntax node)
            {
                ExpressionSyntax expression = node.Expression;

                if (expression?.IsKind(SyntaxKind.AwaitExpression) == false)
                {
                    if (KeepReturnStatement)
                    {
                        return(node.WithExpression(AwaitExpression(expression.WithoutTrivia()).WithTriviaFrom(expression)));
                    }
                    else
                    {
                        return(ExpressionStatement(AwaitExpression(expression.WithoutTrivia()).WithTriviaFrom(expression)).WithTriviaFrom(node));
                    }
                }

                return(base.VisitReturnStatement(node));
            }
コード例 #12
0
            public override SyntaxNode VisitReturnStatement(ReturnStatementSyntax node)
            {
                ExpressionSyntax expression = node.Expression;

                if (expression?.IsKind(SyntaxKind.AwaitExpression) == false)
                {
                    if (KeepReturnStatement)
                    {
                        return(node.WithExpression(AwaitExpression(expression.WithoutTrivia().Parenthesize()).WithTriviaFrom(expression)));
                    }
                    else
                    {
                        return(ExpressionStatement(AwaitExpression(expression.WithoutTrivia().Parenthesize()).WithTriviaFrom(expression))
                               .WithLeadingTrivia(node.GetLeadingTrivia())
                               .WithAdditionalAnnotations(_asyncAwaitAnnotationAndFormatterAnnotation));
                    }
                }

                return(base.VisitReturnStatement(node));
            }
コード例 #13
0
        private SyntaxResult <SyntaxNode> TranslateStatement_Return(ReturnStatement returnStatement, TranslatorState state)
        {
            ReturnStatementSyntax returnStatementSyntax = SyntaxFactory.ReturnStatement();

            if (returnStatement.Expression != null)
            {
                var expression = TranslateExpression(returnStatement.Expression, state);

                if (expression.IsError)
                {
                    returnStatementSyntax = returnStatementSyntax.WithTrailingTrivia(expression.Errors);
                }
                else
                {
                    returnStatementSyntax = returnStatementSyntax.WithExpression(expression.Syntax);
                }
            }

            return(returnStatementSyntax);
        }
コード例 #14
0
        private static async Task <StatementsInfo> RefactorAsync(
            Document document,
            StatementsInfo statementsInfo,
            StatementSyntax statement,
            StatementSyntax newStatement,
            int index,
            int count,
            bool removeReturnStatement,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            ReturnStatementSyntax returnStatement = FindReturnStatementBelow(statementsInfo.Statements, index);

            ExpressionSyntax expression    = returnStatement.Expression;
            ExpressionSyntax newExpression = null;

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

            if (symbol.IsLocal() &&
                index > 0)
            {
                LocalDeclarationStatementSyntax localDeclarationStatement = FindLocalDeclarationStatementAbove(statementsInfo.Statements, index);

                if (localDeclarationStatement?.ContainsDiagnostics == false &&
                    !localDeclarationStatement.SpanOrTrailingTriviaContainsDirectives() &&
                    !statement.GetLeadingTrivia().Any(f => f.IsDirective))
                {
                    SeparatedSyntaxList <VariableDeclaratorSyntax> declarators = localDeclarationStatement.Declaration.Variables;
                    VariableDeclaratorSyntax declarator = FindVariableDeclarator(semanticModel, symbol, declarators, cancellationToken);

                    if (declarator != null)
                    {
                        ExpressionSyntax value = declarator.Initializer?.Value;

                        if (removeReturnStatement || value != null)
                        {
                            IEnumerable <ReferencedSymbol> referencedSymbols = await SymbolFinder.FindReferencesAsync(symbol, document.Solution(), cancellationToken).ConfigureAwait(false);

                            if (referencedSymbols.First().Locations.Count() == count + 1)
                            {
                                newExpression = value;

                                if (declarators.Count == 1)
                                {
                                    statementsInfo = statementsInfo.RemoveNode(localDeclarationStatement, RemoveHelper.GetRemoveOptions(localDeclarationStatement));
                                    index--;
                                }
                                else
                                {
                                    statementsInfo = statementsInfo.ReplaceNode(localDeclarationStatement, localDeclarationStatement.RemoveNode(declarator, RemoveHelper.GetRemoveOptions(declarator)));
                                }

                                returnStatement = FindReturnStatementBelow(statementsInfo.Statements, index);
                            }
                        }
                    }
                }
            }

            if (removeReturnStatement)
            {
                statementsInfo = statementsInfo.RemoveNode(returnStatement, RemoveHelper.GetRemoveOptions(returnStatement));
            }
            else if (newExpression != null)
            {
                statementsInfo = statementsInfo.ReplaceNode(returnStatement, returnStatement.WithExpression(newExpression.WithTriviaFrom(expression)));
            }

            return(statementsInfo.ReplaceNode(statementsInfo.Statements[index], newStatement));
        }
コード例 #15
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsAnyCodeFixEnabled(
                    CodeFixIdentifiers.UseYieldReturnInsteadOfReturn,
                    CodeFixIdentifiers.RemoveReturnKeyword,
                    CodeFixIdentifiers.RemoveReturnExpression))
            {
                return;
            }

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

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

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

            if (returnStatement == null)
            {
                return;
            }

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

                    ExpressionSyntax expression = returnStatement.Expression;

                    if (expression != null)
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        ISymbol containingSymbol = semanticModel.GetEnclosingSymbol(returnStatement.SpanStart, context.CancellationToken);

                        if (containingSymbol?.IsKind(SymbolKind.Method) == true)
                        {
                            var methodSymbol = (IMethodSymbol)containingSymbol;

                            ITypeSymbol returnType = methodSymbol.ReturnType;

                            var replacementKind = SyntaxKind.None;

                            if (returnType.SpecialType == SpecialType.System_Collections_IEnumerable)
                            {
                                if (semanticModel
                                    .GetTypeSymbol(expression, context.CancellationToken)
                                    .IsIEnumerableOrConstructedFromIEnumerableOfT())
                                {
                                    replacementKind = SyntaxKind.ForEachStatement;
                                }
                                else
                                {
                                    replacementKind = SyntaxKind.YieldReturnStatement;
                                }
                            }
                            else if (returnType.IsNamedType())
                            {
                                var namedTypeSymbol = (INamedTypeSymbol)returnType;

                                if (namedTypeSymbol.IsConstructedFromIEnumerableOfT())
                                {
                                    if (semanticModel.IsImplicitConversion(expression, namedTypeSymbol.TypeArguments[0]))
                                    {
                                        replacementKind = SyntaxKind.YieldReturnStatement;
                                    }
                                    else
                                    {
                                        replacementKind = SyntaxKind.ForEachStatement;
                                    }
                                }
                            }

                            if (replacementKind == SyntaxKind.YieldReturnStatement ||
                                (replacementKind == SyntaxKind.ForEachStatement && !returnStatement.SpanContainsDirectives()))
                            {
                                CodeAction codeAction = CodeAction.Create(
                                    "Use yield return instead of return",
                                    cancellationToken => UseYieldReturnInsteadOfReturnRefactoring.RefactorAsync(context.Document, returnStatement, replacementKind, semanticModel, cancellationToken),
                                    GetEquivalenceKey(diagnostic));

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

                    break;
                }

                case CompilerDiagnosticIdentifiers.SinceMethodReturnsVoidReturnKeywordMustNotBeFollowedByObjectExpression:
                case CompilerDiagnosticIdentifiers.SinceMethodIsAsyncMethodThatReturnsTaskReturnKeywordMustNotBeFollowedByObjectExpression:
                {
                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveReturnExpression))
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        ISymbol symbol = semanticModel.GetEnclosingSymbol(returnStatement.SpanStart, context.CancellationToken);

                        if (symbol?.IsMethod() == true)
                        {
                            var methodSymbol = (IMethodSymbol)symbol;

                            if (methodSymbol.ReturnsVoid ||
                                methodSymbol.ReturnType.Equals(semanticModel.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task)))
                            {
                                CodeAction codeAction = CodeAction.Create(
                                    "Remove return expression",
                                    cancellationToken =>
                                    {
                                        ReturnStatementSyntax newNode = returnStatement
                                                                        .WithExpression(null)
                                                                        .WithFormatterAnnotation();

                                        return(context.Document.ReplaceNodeAsync(returnStatement, newNode, cancellationToken));
                                    },
                                    GetEquivalenceKey(diagnostic, CodeFixIdentifiers.RemoveReturnExpression));

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

                    if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveReturnKeyword))
                    {
                        ExpressionSyntax expression = returnStatement.Expression;

                        if (expression.IsKind(
                                SyntaxKind.InvocationExpression,
                                SyntaxKind.ObjectCreationExpression,
                                SyntaxKind.PreDecrementExpression,
                                SyntaxKind.PreIncrementExpression,
                                SyntaxKind.PostDecrementExpression,
                                SyntaxKind.PostIncrementExpression) ||
                            expression is AssignmentExpressionSyntax)
                        {
                            CodeAction codeAction = CodeAction.Create(
                                "Remove 'return'",
                                cancellationToken =>
                                {
                                    SyntaxTriviaList leadingTrivia = returnStatement
                                                                     .GetLeadingTrivia()
                                                                     .AddRange(returnStatement.ReturnKeyword.TrailingTrivia.EmptyIfWhitespace())
                                                                     .AddRange(expression.GetLeadingTrivia().EmptyIfWhitespace());

                                    ExpressionStatementSyntax newNode = SyntaxFactory.ExpressionStatement(
                                        expression.WithLeadingTrivia(leadingTrivia),
                                        returnStatement.SemicolonToken);

                                    return(context.Document.ReplaceNodeAsync(returnStatement, newNode, cancellationToken));
                                },
                                GetEquivalenceKey(diagnostic, CodeFixIdentifiers.RemoveReturnKeyword));

                            context.RegisterCodeFix(codeAction, diagnostic);
                        }
                    }

                    break;
                }
                }
            }
        }
コード例 #16
0
 public override StatementSyntax VisitReturnStatement(ReturnStatementSyntax node)
 {
     return(node.WithExpression(
                node.Expression.Accept(
                    expressionSyntaxVisitor)));
 }