Beispiel #1
0
        public static IEnumerable<ReplaceAction> GetSimplifications(ForEachStatementSyntax forLoop, ISemanticModel model, Assumptions assume, CancellationToken cancellationToken = default(CancellationToken))
        {
            var body = forLoop.Statement.Statements();
            if (body.None()) yield break;

            var unconditionalStatements = body.Skip(1);
            var conditionalStatement = body.First() as IfStatementSyntax;
            if (conditionalStatement == null) yield break;

            var trueBranch = conditionalStatement.Statement.Statements().AppendUnlessJumps(unconditionalStatements).Block();
            var falseBranch = conditionalStatement.ElseStatementOrEmptyBlock().Statements().AppendUnlessJumps(unconditionalStatements).Block();

            var falseIsEmpty = falseBranch.HasSideEffects(model, assume) == false;
            var trueIsEmpty = trueBranch.HasSideEffects(model, assume) == false;
            if (falseIsEmpty == trueIsEmpty) yield break;

            var condition = falseIsEmpty ? conditionalStatement.Condition : conditionalStatement.Condition.Inverted();
            var conditionalActions = falseIsEmpty ? trueBranch : falseBranch;

            var query = forLoop.Expression.Accessing("Where").Invoking(forLoop.Identifier.Lambdad(condition).Args1());

            var forWhereDo = forLoop.WithExpression(query).WithStatement(conditionalActions);

            yield return new ReplaceAction(
                "Filter collection",
                forLoop,
                forWhereDo);
        }
Beispiel #2
0
        private async Task <Document> ConvertVariableAssignmentToLINQ(Document document, VariableDeclaratorSyntax variableDeclarator, ForEachStatementSyntax foreachStatement, CancellationToken c)
        {
            var generator = SyntaxGenerator.GetGenerator(document);

            var oldVariableName = foreachStatement.Identifier.Text;
            var newVariableName = variableDeclarator.Identifier.Text;

            var oldVariables = variableDeclarator.Initializer.Value.DescendantNodesAndSelf().OfType <IdentifierNameSyntax>().Where(x => x.Identifier.Text == oldVariableName);

            var selectCall = generator.InvocationExpression(
                generator.MemberAccessExpression(foreachStatement.Expression, "Select"),
                generator.Argument(
                    generator.ValueReturningLambdaExpression(
                        new[] { generator.LambdaParameter("x") },
                        variableDeclarator.Initializer.Value.ReplaceNodes(oldVariables, (x, y) => generator.IdentifierName("x")))));

            var root = await document.GetSyntaxRootAsync(c);

            Debug.WriteLine(variableDeclarator.Parent);
            var restOfForeachBody = foreachStatement.Statement
                                    .RemoveNode(variableDeclarator, SyntaxRemoveOptions.AddElasticMarker)
                                    .WithAdditionalAnnotations(Formatter.Annotation);
            var newFeStatement = foreachStatement
                                 .WithExpression((ExpressionSyntax)selectCall)
                                 .WithIdentifier(generator.IdentifierName(newVariableName).GetFirstToken())
                                 .WithStatement(restOfForeachBody);

            var newRoot = root.ReplaceNode(foreachStatement, newFeStatement);

            var withEmptyVariableDeclarationsRemoved = new RemoveEmptyVariableDeclarationSyntax().Visit(newRoot);

            return(document.WithSyntaxRoot(withEmptyVariableDeclarationsRemoved));
        }
Beispiel #3
0
        private async Task <Document> ConvertIfContinueToLINQ(Document document, IfStatementSyntax ifStatement, ForEachStatementSyntax foreachStatement, CancellationToken c)
        {
            var generator = SyntaxGenerator.GetGenerator(document);

            var oldVariables = ifStatement.Condition.DescendantNodesAndSelf().OfType <IdentifierNameSyntax>().Where(x => x.Identifier.Text == foreachStatement.Identifier.Text);

            var whereCall = generator.InvocationExpression(
                generator.MemberAccessExpression(foreachStatement.Expression, "Where"),
                generator.Argument(
                    generator.ValueReturningLambdaExpression(
                        new[] { generator.LambdaParameter("x") },
                        generator.LogicalNotExpression(
                            ifStatement.Condition.ReplaceNodes(oldVariables, (x, y) => generator.IdentifierName("x"))))));

            var root = await document.GetSyntaxRootAsync(c);

            var restOfForeachBody = foreachStatement.Statement
                                    .ReplaceNode(ifStatement, ifStatement.Else?.Statement)
                                    .WithAdditionalAnnotations(Formatter.Annotation);
            var newFeStatement = foreachStatement
                                 .WithExpression((ExpressionSyntax)whereCall)
                                 .WithStatement(restOfForeachBody);

            var newRoot = root.ReplaceNode(foreachStatement, newFeStatement);

            return(document.WithSyntaxRoot(newRoot));
        }
Beispiel #4
0
        public static IEnumerable<ReplaceAction> GetSimplifications(ForEachStatementSyntax forLoop, ISemanticModel model, Assumptions assume, CancellationToken cancellationToken = default(CancellationToken))
        {
            // loop uses iterator once?
            var declaredSymbol = model.GetDeclaredSymbol(forLoop);
            var singleRead = forLoop.Statement.DescendantNodes()
                             .OfType<SimpleNameSyntax>()
                             .Where(e => model.GetSymbolInfo(e).Symbol == declaredSymbol)
                             .SingleOrDefaultAllowMany();
            if (singleRead == null) yield break;

            // safe iterator projection?
            var guaranteedProjectionPerIteration = forLoop.Statement.CompleteExecutionGuaranteesChildExecutedExactlyOnce(singleRead);
            var projection = singleRead.AncestorsAndSelf()
                             .TakeWhile(e => !(e is StatementSyntax))
                             .OfType<ExpressionSyntax>()
                             .TakeWhile(e => model.GetTypeInfo(e).Type.SpecialType != SpecialType.System_Void)
                             .TakeWhile(e => guaranteedProjectionPerIteration == true || e.HasSideEffects(model, assume) == false)
                             .LastOrDefault();
            if (projection == null) yield break;
            if (projection.TryEvalAlternativeComparison(singleRead, model, assume) == true) yield break;

            // build replacement loop
            var projectedCollection = forLoop.Expression
                                      .Accessing("Select")
                                      .Invoking(forLoop.Identifier.Lambdad(projection).Args1());
            var newBody = forLoop.Statement.ReplaceNode(projection, singleRead);
            var replacedLoop = forLoop.WithExpression(projectedCollection).WithStatement(newBody);

            // expose as code action/issue
            yield return new ReplaceAction(
                "Project collection",
                forLoop,
                replacedLoop);
        }
                public override SyntaxNode VisitForEachStatement(ForEachStatementSyntax node)
                {
                    if (node != this.ContainerOfStatementsOrFieldToReplace)
                    {
                        return(base.VisitForEachStatement(node));
                    }

                    return(node.WithExpression(VisitNode(node.Expression))
                           .WithStatement(ReplaceStatementIfNeeded(node.Statement)));
                }