Example #1
0
        internal static List <TextChange> GetFixListChanges <TNode>(
            SyntaxNode containingNode,
            SyntaxNodeOrToken openNodeOrToken,
            IReadOnlyList <TNode> nodes,
            ListFixMode fixMode = ListFixMode.Fix,
            CancellationToken cancellationToken = default) where TNode : SyntaxNode
        {
            IndentationAnalysis indentationAnalysis = AnalyzeIndentation(containingNode, cancellationToken);

            string increasedIndentation = indentationAnalysis.GetIncreasedIndentation();

            bool isSingleLine;
            SeparatedSyntaxList <TNode> separatedList = default;

            if (nodes is SyntaxList <TNode> list)
            {
                isSingleLine = list.IsSingleLine(includeExteriorTrivia: false, cancellationToken: cancellationToken);
            }
            else
            {
                separatedList = (SeparatedSyntaxList <TNode>)nodes;

                isSingleLine = separatedList.IsSingleLine(
                    includeExteriorTrivia: false,
                    cancellationToken: cancellationToken);
            }

            if (isSingleLine &&
                fixMode == ListFixMode.Fix)
            {
                TNode node = nodes[0];

                SyntaxTriviaList leading = node.GetLeadingTrivia();

                TextSpan span = (leading.Any() && leading.Last().IsWhitespaceTrivia())
                    ? leading.Last().Span
                    : new TextSpan(node.SpanStart, 0);

                return(new List <TextChange>()
                {
                    new TextChange(span, increasedIndentation)
                });
            }

            var textChanges              = new List <TextChange>();
            TextLineCollection lines     = null;
            string             endOfLine = DetermineEndOfLine(containingNode).ToString();

            for (int i = 0; i < nodes.Count; i++)
            {
                SyntaxToken token;
                if (i == 0)
                {
                    token = (openNodeOrToken.IsNode)
                        ? openNodeOrToken.AsNode().GetLastToken()
                        : openNodeOrToken.AsToken();
                }
                else
                {
                    token = (list == default)
                        ? separatedList.GetSeparator(i - 1)
                        : list[i - 1].GetLastToken();
                }

                SyntaxTriviaList trailing = token.TrailingTrivia;
                TNode            node     = nodes[i];
                var indentationAdded      = false;

                if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailing))
                {
                    SyntaxTrivia last = node.GetLeadingTrivia().LastOrDefault();

                    if (last.IsWhitespaceTrivia())
                    {
                        if (last.Span.Length == increasedIndentation.Length)
                        {
                            continue;
                        }

                        textChanges.Add(last.Span, increasedIndentation);
                    }
                    else
                    {
                        textChanges.Add(new TextSpan(node.SpanStart, 0), increasedIndentation);
                    }

                    indentationAdded = true;
                }
                else
                {
                    if (nodes.Count == 1 &&
                        node is ArgumentSyntax argument)
                    {
                        LambdaBlock lambdaBlock = GetLambdaBlock(argument, lines ??= argument.SyntaxTree.GetText().Lines);

                        if (lambdaBlock.Block != null)
                        {
                            increasedIndentation = indentationAnalysis.Indentation.ToString();
                        }
                    }

                    if ((nodes.Count > 1 || fixMode == ListFixMode.Wrap) &&
                        ShouldWrapAndIndent(containingNode, i))
                    {
                        textChanges.Add(
                            (trailing.Any() && trailing.Last().IsWhitespaceTrivia())
                                ? trailing.Last().Span
                                : new TextSpan(token.FullSpan.End, 0),
                            endOfLine);

                        textChanges.Add(new TextSpan(node.FullSpan.Start, 0), increasedIndentation);

                        indentationAdded = true;
                    }
                }

                ImmutableArray <IndentationInfo> indentations = FindIndentations(node, node.Span).ToImmutableArray();

                if (!indentations.Any())
                {
                    continue;
                }

                LambdaBlock lambdaBlock2 = GetLambdaBlock(node, lines ??= node.SyntaxTree.GetText().Lines);

                bool isLambdaBlockWithOpenBraceAtEndOfLine = lambdaBlock2.Token == indentations.Last().Token;

                int baseIndentationLength = (isLambdaBlockWithOpenBraceAtEndOfLine)
                    ? indentations.Last().Span.Length
                    : indentations[0].Span.Length;

                for (int j = indentations.Length - 1; j >= 0; j--)
                {
                    IndentationInfo indentationInfo = indentations[j];

                    if (indentationAdded &&
                        node is ArgumentSyntax argument &&
                        (argument.Expression as AnonymousFunctionExpressionSyntax)?.Block != null)
                    {
                        indentationAdded = false;
                    }

                    string replacement = increasedIndentation;

                    if (indentationAdded)
                    {
                        replacement += indentationAnalysis.GetSingleIndentation();
                    }

                    if ((j > 0 || isLambdaBlockWithOpenBraceAtEndOfLine) &&
                        indentationInfo.Span.Length > baseIndentationLength)
                    {
                        replacement += indentationInfo.ToString().Substring(baseIndentationLength);
                    }

                    if (indentationInfo.Span.Length != replacement.Length)
                    {
                        textChanges.Add(indentationInfo.Span, replacement);
                    }
                }
            }

            FormattingVerifier.VerifyChangedSpansAreWhitespace(containingNode, textChanges);

            return(textChanges);
        }