private static SyntaxList <StatementSyntax> InsertWithinTriviaOfNext(
            SyntaxList <StatementSyntax> oldStatements,
            StatementSyntax newStatement,
            int statementIndex)
        {
            var nextStatement = oldStatements.ElementAtOrDefault(statementIndex);

            if (nextStatement == null)
            {
                return(oldStatements.Insert(statementIndex, newStatement));
            }

            // Grab all the trivia before the line the next statement is on and move it to the new node.

            var nextStatementLeading = nextStatement.GetLeadingTrivia();
            var precedingEndOfLine   = nextStatementLeading.LastOrDefault(t => t.Kind() == SyntaxKind.EndOfLineTrivia);

            if (precedingEndOfLine == default)
            {
                return(oldStatements.ReplaceRange(
                           nextStatement, new[] { newStatement, nextStatement }));
            }

            var endOfLineIndex = nextStatementLeading.IndexOf(precedingEndOfLine) + 1;

            return(oldStatements.ReplaceRange(
                       nextStatement, new[]
            {
                newStatement.WithLeadingTrivia(nextStatementLeading.Take(endOfLineIndex)),
                nextStatement.WithLeadingTrivia(nextStatementLeading.Skip(endOfLineIndex)),
            }));
        }
예제 #2
0
        private static Task <Document> ConvertWhileStatementToForStatementAsync(
            Document document,
            WhileStatementSyntax whileStatement,
            CancellationToken cancellationToken)
        {
            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(whileStatement);

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            int index = statements.IndexOf(whileStatement);

            SingleLocalDeclarationStatementInfo localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo((LocalDeclarationStatementSyntax)statements[index - 1]);

            var block = (BlockSyntax)whileStatement.Statement;

            var expressionStatement = (ExpressionStatementSyntax)block.Statements.Last();

            var postIncrementExpression = (PostfixUnaryExpressionSyntax)expressionStatement.Expression;

            BlockSyntax newBlock = block.WithStatements(block.Statements.Remove(expressionStatement));

            ForStatementSyntax forStatement = CSharpFactory.ForStatement(
                declaration: localInfo.Declaration.TrimTrivia(),
                condition: whileStatement.Condition,
                incrementor: postIncrementExpression.TrimTrivia(),
                statement: newBlock);

            forStatement = forStatement
                           .WithLeadingTrivia(localInfo.Statement.GetLeadingTrivia().AddRange(whileStatement.GetLeadingTrivia().EmptyIfWhitespace()))
                           .WithFormatterAnnotation();

            SyntaxList <StatementSyntax> newStatements = statements.ReplaceRange(index - 1, 2, new StatementSyntax[] { forStatement });

            return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken));
        }
        private static async Task <Document> SplitAttributesAsync(
            Document document,
            MemberDeclarationSyntax member,
            AttributeListSyntax[] attributeLists,
            CancellationToken cancellationToken)
        {
            SyntaxNode oldRoot = await document.GetSyntaxRootAsync(cancellationToken);

            SyntaxList <AttributeListSyntax> lists = member.GetAttributeLists();

            int index = lists.IndexOf(attributeLists[attributeLists.Length - 1]);

            for (int i = attributeLists.Length - 1; i >= 0; i--)
            {
                lists = lists.ReplaceRange(
                    lists[index],
                    AttributeRefactoring.SplitAttributes(attributeLists[i])
                    .Select(f => f.WithAdditionalAnnotations(Formatter.Annotation)));

                index--;
            }

            SyntaxNode newRoot = oldRoot.ReplaceNode(member, member.SetAttributeLists(lists));

            return(document.WithSyntaxRoot(newRoot));
        }
        private static Task <Document> RefactorAsync(
            Document document,
            IfStatementSyntax ifStatement,
            CancellationToken cancellationToken)
        {
            StatementSyntax newStatement;

            if (ifStatement.Parent is IfStatementSyntax parentIf)
            {
                newStatement = ifStatement.Statement;
            }
            else
            {
                var parentBlock = (BlockSyntax)ifStatement.Parent;

                parentIf = (IfStatementSyntax)parentBlock.Parent;

                SyntaxList <StatementSyntax> statements = parentBlock.Statements;

                SyntaxList <StatementSyntax> newStatements = (ifStatement.Statement is BlockSyntax block)
                    ? block.Statements
                    : SyntaxFactory.SingletonList(ifStatement.Statement);

                newStatements = statements.ReplaceRange(ifStatement, newStatements);

                newStatement = parentBlock.WithStatements(newStatements);
            }

            IfStatementSyntax newNode = parentIf
                                        .WithStatement(newStatement)
                                        .WithCondition(LogicalAndExpression(parentIf.Condition.Parenthesize(), ifStatement.Condition.Parenthesize()))
                                        .WithFormatterAnnotation();

            return(document.ReplaceNodeAsync(parentIf, newNode, cancellationToken));
        }
 private static SyntaxList<StatementSyntax> InsertWithinTriviaOfNext(
     SyntaxList<StatementSyntax> oldStatements,
     StatementSyntax newStatement,
     int statementIndex)
 {
     var nextStatement = oldStatements.ElementAtOrDefault(statementIndex);
     return nextStatement == null
         ? oldStatements.Insert(statementIndex, newStatement)
         : oldStatements.ReplaceRange(nextStatement, new[] {
             newStatement.WithLeadingTrivia(nextStatement.GetLeadingTrivia()),
             nextStatement.WithoutLeadingTrivia() });
 }
예제 #6
0
        private static async Task <Document> RefactorAsync(
            Document document,
            StatementSyntax statement,
            CancellationToken cancellationToken)
        {
            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(statement);

            var methodDeclaration = (MethodDeclarationSyntax)statementsInfo.Parent.Parent;

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

            string name = methodDeclaration.Identifier.ValueText;

            if (!name.EndsWith("Iterator", StringComparison.Ordinal))
            {
                name += "Iterator";
            }

            name = NameGenerator.Default.EnsureUniqueLocalName(name, semanticModel, statement.SpanStart, cancellationToken: cancellationToken);

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            int index = statements.IndexOf(statement);

            List <StatementSyntax> localFunctionStatements = statements.Skip(index).ToList();

            int lastIndex = localFunctionStatements.Count - 1;

            localFunctionStatements[lastIndex] = localFunctionStatements[lastIndex].WithoutTrailingTrivia();

            LocalFunctionStatementSyntax localFunction = LocalFunctionStatement(
                default(SyntaxTokenList),
                methodDeclaration.ReturnType.WithoutTrivia(),
                Identifier(name).WithRenameAnnotation(),
                ParameterList(),
                Block(localFunctionStatements).WithTrailingTrivia(statements.Last().GetTrailingTrivia()));

            localFunction = localFunction.WithFormatterAnnotation();

            ReturnStatementSyntax returnStatement = ReturnStatement(
                Token(SyntaxKind.ReturnKeyword).WithLeadingTrivia(statement.GetLeadingTrivia()),
                InvocationExpression(IdentifierName(name)),
                SemicolonToken());

            SyntaxList <StatementSyntax> newStatements = statements.ReplaceRange(
                index,
                statements.Count - index,
                new StatementSyntax[] { returnStatement, localFunction });

            return(await document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken).ConfigureAwait(false));
        }
예제 #7
0
        private static async Task <Document> SplitFieldDeclarationAsync(
            Document document,
            FieldDeclarationSyntax declaration,
            CancellationToken cancellationToken)
        {
            var containingMember = (MemberDeclarationSyntax)declaration.Parent;

            SyntaxList <MemberDeclarationSyntax> members = containingMember.GetMembers();

            SyntaxList <MemberDeclarationSyntax> newMembers = members.ReplaceRange(
                declaration,
                SplitFieldDeclaration(declaration));

            MemberDeclarationSyntax newNode = containingMember.SetMembers(newMembers);

            return(await document.ReplaceNodeAsync(containingMember, newNode, cancellationToken).ConfigureAwait(false));
        }
예제 #8
0
        private static Task <Document> SplitEventFieldDeclarationAsync(
            Document document,
            EventFieldDeclarationSyntax declaration,
            CancellationToken cancellationToken)
        {
            var containingMember = (TypeDeclarationSyntax)declaration.Parent;

            SyntaxList <MemberDeclarationSyntax> members = containingMember.Members;

            SyntaxList <MemberDeclarationSyntax> newMembers = members.ReplaceRange(
                declaration,
                SplitEventFieldDeclaration(declaration));

            MemberDeclarationSyntax newNode = containingMember.WithMembers(newMembers);

            return(document.ReplaceNodeAsync(containingMember, newNode, cancellationToken));
        }
예제 #9
0
        private void DoTestAddInsertRemoveReplaceOnEmptyList(SyntaxList <SyntaxNode> list)
        {
            Assert.Equal(0, list.Count);

            SyntaxNode nodeD = SyntaxFactory.ParseExpression("D ");
            SyntaxNode nodeE = SyntaxFactory.ParseExpression("E ");

            var newList = list.Add(nodeD);

            Assert.Equal(1, newList.Count);
            Assert.Equal("D ", newList.ToFullString());

            newList = list.AddRange(new[] { nodeD, nodeE });
            Assert.Equal(2, newList.Count);
            Assert.Equal("D E ", newList.ToFullString());

            newList = list.Insert(0, nodeD);
            Assert.Equal(1, newList.Count);
            Assert.Equal("D ", newList.ToFullString());

            newList = list.InsertRange(0, new[] { nodeD, nodeE });
            Assert.Equal(2, newList.Count);
            Assert.Equal("D E ", newList.ToFullString());

            newList = list.Remove(nodeD);
            Assert.Equal(0, newList.Count);

            Assert.Equal(-1, list.IndexOf(nodeD));
            Assert.Throws <ArgumentOutOfRangeException>(() => list.RemoveAt(0));
            Assert.Throws <ArgumentOutOfRangeException>(() => list.Insert(1, nodeD));
            Assert.Throws <ArgumentOutOfRangeException>(() => list.Insert(-1, nodeD));
            Assert.Throws <ArgumentOutOfRangeException>(() => list.InsertRange(1, new[] { nodeD }));
            Assert.Throws <ArgumentOutOfRangeException>(() => list.InsertRange(-1, new[] { nodeD }));
            Assert.Throws <ArgumentException>(() => list.Replace(nodeD, nodeE));
            Assert.Throws <ArgumentException>(() => list.ReplaceRange(nodeD, new[] { nodeE }));
            Assert.Throws <ArgumentNullException>(() => list.Add(null));
            Assert.Throws <ArgumentNullException>(
                () => list.AddRange((IEnumerable <SyntaxNode>)null)
                );
            Assert.Throws <ArgumentNullException>(() => list.Insert(0, null));
            Assert.Throws <ArgumentNullException>(
                () => list.InsertRange(0, (IEnumerable <SyntaxNode>)null)
                );
        }
예제 #10
0
        private static Task <Document> RefactorAsync(
            Document document,
            SyntaxListSelection <SwitchLabelSyntax> selectedLabels,
            IComparer <SwitchLabelSyntax> comparer,
            CancellationToken cancellationToken = default)
        {
            SyntaxList <SwitchLabelSyntax> labels = selectedLabels.UnderlyingList;

            SyntaxList <SwitchLabelSyntax> newLabels = labels.ReplaceRange(
                selectedLabels.FirstIndex,
                selectedLabels.Count,
                selectedLabels.OrderBy(f => f, comparer));

            var section = (SwitchSectionSyntax)labels[0].Parent;

            SwitchSectionSyntax newSection = section.WithLabels(newLabels);

            return(document.ReplaceNodeAsync(section, newSection, cancellationToken));
        }
예제 #11
0
        private static async Task <Document> RefactorAsync(
            Document document,
            StatementSyntax statement,
            CancellationToken cancellationToken)
        {
            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(statement);

            var methodDeclaration = (MethodDeclarationSyntax)statementsInfo.Parent.Parent;

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

            string name = methodDeclaration.Identifier.ValueText;

            name = NameGenerator.Default.EnsureUniqueLocalName(name, semanticModel, statement.SpanStart, cancellationToken: cancellationToken);

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            int index = statements.IndexOf(statement);

            List <StatementSyntax> localFunctionStatements = statements.Skip(index).ToList();

            localFunctionStatements[0] = localFunctionStatements[0].TrimLeadingTrivia();

            LocalFunctionStatementSyntax localFunction = LocalFunctionStatement(
                default(SyntaxTokenList),
                methodDeclaration.ReturnType.WithoutTrivia(),
                Identifier(name).WithRenameAnnotation(),
                ParameterList(),
                Block(localFunctionStatements));

            ReturnStatementSyntax returnStatement = ReturnStatement(
                Token(TriviaList(NewLine()), SyntaxKind.ReturnKeyword, TriviaList()),
                InvocationExpression(IdentifierName(name)),
                Token(SyntaxTriviaList.Empty, SyntaxKind.SemicolonToken, TriviaList(NewLine(), NewLine())));

            SyntaxList <StatementSyntax> newStatements = statements.ReplaceRange(
                index,
                statements.Count - index,
                new StatementSyntax[] { returnStatement.WithFormatterAnnotation(), localFunction.WithFormatterAnnotation() });

            return(await document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken).ConfigureAwait(false));
        }
            public override SyntaxList <TNode> VisitList <TNode>(SyntaxList <TNode> list)
            {
                list = base.VisitList(list);

                var index = 0;

                while (index < list.Count)
                {
                    var element = list[index];
                    if (element.HasAnnotation(NodeToReplaceAnnotation))
                    {
                        list = list.ReplaceRange(element, RemovePlaceHolder(element as XmlElementSyntax).Cast <TNode>());
                    }
                    else
                    {
                        index++;
                    }
                }

                return(list);
            }
예제 #13
0
        private static async Task <Document> SplitEventFieldDeclarationAsync(
            Document document,
            EventFieldDeclarationSyntax declaration,
            CancellationToken cancellationToken)
        {
            SyntaxNode oldRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var containingMember = (MemberDeclarationSyntax)declaration.Parent;

            SyntaxList <MemberDeclarationSyntax> members = containingMember.GetMembers();

            SyntaxList <MemberDeclarationSyntax> newMembers = members.ReplaceRange(
                declaration,
                SplitEventFieldDeclaration(declaration));

            MemberDeclarationSyntax newNode = containingMember.SetMembers(newMembers);

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

            return(document.WithSyntaxRoot(newRoot));
        }
예제 #14
0
        private static async Task <Document> SplitVariablesIntoMultipleDeclarationsAsync(
            Document document,
            FieldDeclarationSyntax declaration,
            CancellationToken cancellationToken)
        {
            SyntaxNode oldRoot = await document.GetSyntaxRootAsync(cancellationToken);

            var containingMember = (MemberDeclarationSyntax)declaration.Parent;

            SyntaxList <MemberDeclarationSyntax> members = containingMember.GetMembers();

            SyntaxList <MemberDeclarationSyntax> newMembers = members.ReplaceRange(
                declaration,
                CreateFieldDeclarations(declaration));

            MemberDeclarationSyntax newNode = containingMember.SetMembers(newMembers);

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

            return(document.WithSyntaxRoot(newRoot));
        }
예제 #15
0
        public override SyntaxList <TNode> VisitList <TNode>(SyntaxList <TNode> list)
        {
            if (_originalNode is TNode)
            {
                var index = list.IndexOf((TNode)_originalNode);
                if (index >= 0 && index < list.Count)
                {
                    switch (_editKind)
                    {
                    case ListEditKind.Replace:
                        return(list.ReplaceRange((TNode)_originalNode, _newNodes.Cast <TNode>()));

                    case ListEditKind.InsertAfter:
                        return(list.InsertRange(index + 1, _newNodes.Cast <TNode>()));

                    case ListEditKind.InsertBefore:
                        return(list.InsertRange(index, _newNodes.Cast <TNode>()));
                    }
                }
            }

            return(base.VisitList <TNode>(list));
        }
        private SyntaxNode RemoveUnnecessaryParagraphs(XmlElementSyntax originalNode, XmlElementSyntax rewrittenNode)
        {
            bool hasUnnecessary = false;
            SyntaxList <XmlNodeSyntax> content = rewrittenNode.Content;

            for (int i = 0; i < content.Count; i++)
            {
                if (content[i].HasAnnotation(UnnecessaryParagraphAnnotation))
                {
                    hasUnnecessary = true;
                    XmlElementSyntax unnecessaryElement = (XmlElementSyntax)content[i];
                    content = content.ReplaceRange(unnecessaryElement, unnecessaryElement.Content);
                    i      += unnecessaryElement.Content.Count;
                }
            }

            if (!hasUnnecessary)
            {
                return(rewrittenNode);
            }

            return(rewrittenNode.WithContent(content));
        }
예제 #17
0
        private static SyntaxList <XmlNodeSyntax> SortElements <TNode>(
            SeparatedSyntaxList <TNode> nodes,
            SyntaxList <XmlNodeSyntax> content,
            int firstIndex,
            XmlElementKind kind,
            Func <SeparatedSyntaxList <TNode>, string, int> indexOf) where TNode : SyntaxNode
        {
            var xmlNodes = new List <XmlNodeSyntax>();

            var ranks = new Dictionary <XmlNodeSyntax, int>();

            for (int i = firstIndex; i < content.Count; i++)
            {
                XmlElementInfo elementInfo = SyntaxInfo.XmlElementInfo(content[i]);

                if (elementInfo.Success)
                {
                    if (elementInfo.IsElementKind(kind))
                    {
                        XmlNodeSyntax element = elementInfo.Element;

                        string value = (element.IsKind(SyntaxKind.XmlElement))
                            ? ((XmlElementSyntax)element).GetAttributeValue("name")
                            : ((XmlEmptyElementSyntax)element).GetAttributeValue("name");

                        if (value != null)
                        {
                            ranks[element] = indexOf(nodes, value);
                        }
                        else
                        {
                            break;
                        }
                    }
                    else
                    {
                        break;
                    }
                }

                xmlNodes.Add(content[i]);
            }

            for (int i = 0; i < xmlNodes.Count - 1; i++)
            {
                for (int j = 0; j < xmlNodes.Count - i - 1; j++)
                {
                    XmlNodeSyntax node1 = xmlNodes[j];

                    if (ranks.TryGetValue(node1, out int rank1))
                    {
                        int k = j + 1;

                        while (k < xmlNodes.Count - i - 1)
                        {
                            XmlNodeSyntax node2 = xmlNodes[k];
                            if (ranks.TryGetValue(node2, out int rank2))
                            {
                                if (rank1 > rank2)
                                {
                                    xmlNodes[k] = node1;
                                    xmlNodes[j] = node2;
                                }

                                break;
                            }

                            k++;
                        }
                    }
                }
            }

            return(content.ReplaceRange(firstIndex, xmlNodes.Count, xmlNodes));
        }
예제 #18
0
        public static async Task <Document> InvertIfAsync(
            Document document,
            IfStatementSyntax ifStatement,
            bool recursive = false,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();

            StatementSyntax statement = ifStatement.Statement;

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement);

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            InvertIfAnalysis analysis = InvertIfAnalysis.Create(ifStatement, statement);

            int ifStatementIndex = statements.IndexOf(ifStatement);

            StatementSyntax lastStatement = analysis.LastStatement;

            int lastStatementIndex = statements.IndexOf(lastStatement);

            bool isLastStatementRedundant = IsLastStatementRedundant();

            bool shouldUseElseClause = !CSharpFacts.IsJumpStatement(lastStatement.Kind());

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

            SyntaxList <StatementSyntax> newStatements = statements;

            if (!recursive)
            {
                Refactor();
            }
            else
            {
                IfStatementSyntax lastIfStatement;

                InvertIfAnalysis a = analysis.AnalyzeNextStatement();

                do
                {
                    lastIfStatement = a.IfStatement;

                    a = a.AnalyzeNextStatement();
                } while (a.Success);

                int firstLastStatementIndex = lastStatementIndex;

                int index = statements.IndexOf(lastIfStatement);

                int firstIndex = ifStatementIndex;

                while (index >= firstIndex)
                {
                    ifStatementIndex = index;
                    ifStatement      = (IfStatementSyntax)statements[ifStatementIndex];
                    statement        = ifStatement.Statement;
                    Refactor();
                    lastStatementIndex = firstLastStatementIndex + newStatements.Count - statements.Count;
                    lastStatement      = (statement is BlockSyntax block) ? block.Statements.Last() : statement;
                    index--;
                }
            }

            return(await document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken).ConfigureAwait(false));

            void Refactor()
            {
                cancellationToken.ThrowIfCancellationRequested();

                SyntaxList <StatementSyntax> nextStatements = newStatements
                                                              .Skip(ifStatementIndex + 1)
                                                              .Take(lastStatementIndex - ifStatementIndex)
                                                              .ToSyntaxList()
                                                              .TrimTrivia();

                BlockSyntax newStatement;
                SyntaxList <StatementSyntax> newNextStatements;

                if (statement is BlockSyntax block)
                {
                    newStatement      = block.WithStatements(nextStatements);
                    newNextStatements = block.Statements;
                }
                else
                {
                    newStatement      = Block(nextStatements);
                    newNextStatements = SingletonList(statement);
                }

                if (isLastStatementRedundant)
                {
                    newNextStatements = newNextStatements.RemoveAt(newNextStatements.Count - 1);
                }

                ElseClauseSyntax elseClause = null;

                if (newNextStatements.Any() &&
                    shouldUseElseClause)
                {
                    elseClause        = ElseClause(Block(newNextStatements));
                    newNextStatements = default;
                }

                IfStatementSyntax newIfStatement = ifStatement.Update(
                    ifKeyword: ifStatement.IfKeyword,
                    openParenToken: ifStatement.OpenParenToken,
                    condition: SyntaxInverter.LogicallyInvert(ifStatement.Condition, semanticModel, cancellationToken),
                    closeParenToken: ifStatement.CloseParenToken,
                    statement: newStatement,
                    @else: elseClause);

                newIfStatement = newIfStatement.WithFormatterAnnotation();

                SyntaxList <StatementSyntax> newNodes = newNextStatements.Insert(0, newIfStatement);

                newStatements = newStatements.ReplaceRange(ifStatementIndex, lastStatementIndex - ifStatementIndex + 1, newNodes);
            }

            bool IsLastStatementRedundant()
            {
                StatementSyntax jumpStatement = analysis.JumpStatement;

                switch (jumpStatement.Kind())
                {
                case SyntaxKind.ReturnStatement:
                {
                    if (((ReturnStatementSyntax)jumpStatement).Expression == null &&
                        RemoveRedundantStatementAnalysis.IsFixable(lastStatement, SyntaxKind.ReturnStatement))
                    {
                        return(true);
                    }

                    break;
                }

                case SyntaxKind.ContinueStatement:
                {
                    if (RemoveRedundantStatementAnalysis.IsFixable(lastStatement, SyntaxKind.ContinueStatement))
                    {
                        return(true);
                    }

                    break;
                }
                }

                return(false);
            }
        }