Exemplo n.º 1
0
 public static Task <Document> AddNewLineBeforeAndIncreaseIndentationAsync(
     Document document,
     SyntaxToken token,
     IndentationAnalysis indentation,
     CancellationToken cancellationToken = default)
 {
     return(AddNewLineBeforeAsync(
                document,
                token,
                indentation.GetIncreasedIndentation(),
                cancellationToken));
 }
        private static void Analyze <TNode>(
            SyntaxNodeAnalysisContext context,
            SyntaxNodeOrToken openNodeOrToken,
            SeparatedSyntaxList <TNode> nodes) where TNode : SyntaxNode
        {
            TNode first = nodes.FirstOrDefault();

            if (first == null)
            {
                return;
            }

            TextSpan span = nodes.GetSpan(includeExteriorTrivia: false);

            if (span.IsSingleLine(first.SyntaxTree))
            {
                SyntaxTriviaList trailing = openNodeOrToken.GetTrailingTrivia();

                if (!IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailing))
                {
                    return;
                }

                int indentationLength = GetIncreasedIndentationLength(openNodeOrToken.Parent);

                if (indentationLength == 0)
                {
                    return;
                }

                if (ShouldFixIndentation(first.GetLeadingTrivia(), indentationLength))
                {
                    ReportDiagnostic();
                }
            }
            else
            {
                TextLineCollection lines = null;

                IndentationAnalysis indentationAnalysis = IndentationAnalysis.Create(openNodeOrToken.Parent);

                int indentationLength = indentationAnalysis.IncreasedIndentationLength;

                if (indentationLength == 0)
                {
                    return;
                }

                for (int i = nodes.Count - 1; i >= 0; i--)
                {
                    SyntaxTriviaList trailing = (i == 0)
                        ? openNodeOrToken.GetTrailingTrivia()
                        : nodes.GetSeparator(i - 1).TrailingTrivia;

                    if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailing))
                    {
                        if (ShouldFixIndentation(nodes[i].GetLeadingTrivia(), indentationLength))
                        {
                            ReportDiagnostic();
                            break;
                        }
                    }
                    else
                    {
                        if (nodes.Count > 1 &&
                            ShouldWrapAndIndent(context.Node, i))
                        {
                            ReportDiagnostic();
                            break;
                        }

                        if (nodes.Count == 1 &&
                            first.IsKind(SyntaxKind.Argument))
                        {
                            var argument = (ArgumentSyntax)(SyntaxNode)first;

                            LambdaBlock lambdaBlock = GetLambdaBlock(argument, lines ??= first.SyntaxTree.GetText().Lines);

                            if (lambdaBlock.Block != null)
                            {
                                SyntaxToken      token   = lambdaBlock.Token;
                                SyntaxTriviaList leading = token.LeadingTrivia;

                                if (leading.Any())
                                {
                                    SyntaxTrivia trivia = leading.Last();

                                    if (trivia.IsWhitespaceTrivia() &&
                                        trivia.SpanStart == lambdaBlock.LineStartIndex &&
                                        trivia.Span.Length != indentationAnalysis.IndentationLength)
                                    {
                                        ReportDiagnostic();
                                        break;
                                    }
                                }
                                else if (lambdaBlock.LineStartIndex == token.SpanStart)
                                {
                                    ReportDiagnostic();
                                    break;
                                }

                                return;
                            }
                        }

                        if (lines == null)
                        {
                            lines = first.SyntaxTree.GetText().Lines;
                        }

                        int lineIndex = lines.IndexOf(span.Start);
                        if (lineIndex < lines.Count - 1)
                        {
                            int lineStartIndex = lines[lineIndex + 1].Start;

                            if (first.Span.Contains(lineStartIndex))
                            {
                                SyntaxToken token = first.FindToken(lineStartIndex);

                                if (!token.IsKind(SyntaxKind.None))
                                {
                                    SyntaxTriviaList leading = token.LeadingTrivia;

                                    if (leading.Any())
                                    {
                                        if (leading.FullSpan.Contains(lineStartIndex))
                                        {
                                            SyntaxTrivia trivia = leading.Last();

                                            if (trivia.IsWhitespaceTrivia() &&
                                                trivia.SpanStart == lineStartIndex &&
                                                trivia.Span.Length != indentationLength)
                                            {
                                                ReportDiagnostic();
                                                break;
                                            }
                                        }
                                    }
                                    else if (lineStartIndex == token.SpanStart)
                                    {
                                        ReportDiagnostic();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            void ReportDiagnostic()
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticDescriptors.FixFormattingOfList,
                    Location.Create(first.SyntaxTree, nodes.Span),
                    GetTitle());
            }
Exemplo n.º 3
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);
        }
Exemplo n.º 4
0
        public static Task <Document> FixBinaryExpressionAsync(
            Document document,
            BinaryExpressionSyntax binaryExpression,
            TextSpan span,
            CancellationToken cancellationToken)
        {
            IndentationAnalysis indentationAnalysis = AnalyzeIndentation(binaryExpression, cancellationToken);

            string indentation;

            if (indentationAnalysis.Indentation == binaryExpression.GetLeadingTrivia().LastOrDefault() &&
                AnalyzerOptions.AddNewLineAfterBinaryOperatorInsteadOfBeforeIt.IsEnabled(document, binaryExpression))
            {
                indentation = indentationAnalysis.Indentation.ToString();
            }
            else
            {
                indentation = indentationAnalysis.GetIncreasedIndentation();
            }

            string endOfLineAndIndentation = DetermineEndOfLine(binaryExpression).ToString() + indentation;

            var textChanges = new List <TextChange>();
            int prevIndex   = binaryExpression.Span.End;

            SyntaxKind binaryKind = binaryExpression.Kind();

            while (true)
            {
                SyntaxToken token = binaryExpression.OperatorToken;

                if (token.Span.End > span.End)
                {
                    continue;
                }

                if (token.SpanStart < span.Start)
                {
                    break;
                }

                ExpressionSyntax left          = binaryExpression.Left;
                ExpressionSyntax right         = binaryExpression.Right;
                SyntaxTriviaList leftTrailing  = left.GetTrailingTrivia();
                SyntaxTriviaList tokenTrailing = token.TrailingTrivia;

                if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(leftTrailing))
                {
                    if (!SetIndentation(token))
                    {
                        break;
                    }
                }
                else if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(tokenTrailing))
                {
                    if (!SetIndentation(right))
                    {
                        break;
                    }
                }
                else if (leftTrailing.IsEmptyOrWhitespace() &&
                         tokenTrailing.IsEmptyOrWhitespace())
                {
                    if (AnalyzerOptions.AddNewLineAfterBinaryOperatorInsteadOfBeforeIt.IsEnabled(document, binaryExpression))
                    {
                        if (!SetIndentation(right))
                        {
                            break;
                        }
                    }
                    else if (!SetIndentation(token))
                    {
                        break;
                    }
                }

                if (!left.IsKind(binaryKind))
                {
                    break;
                }

                binaryExpression = (BinaryExpressionSyntax)left;
            }

            if (textChanges.Count > 0)
            {
                SyntaxTriviaList leading = binaryExpression.GetLeadingTrivia();

                if (!leading.Any())
                {
                    SyntaxTrivia trivia = binaryExpression.GetFirstToken().GetPreviousToken().TrailingTrivia.LastOrDefault();

                    if (trivia.IsEndOfLineTrivia() &&
                        trivia.Span.End == binaryExpression.SpanStart)
                    {
                        textChanges.Add(new TextSpan(binaryExpression.SpanStart, 0), indentation);
                    }
                }
            }

            FormattingVerifier.VerifyChangedSpansAreWhitespace(binaryExpression, textChanges);

            return(document.WithTextChangesAsync(textChanges, cancellationToken));

            bool SetIndentation(SyntaxNodeOrToken nodeOrToken)
            {
                SyntaxTriviaList leading = nodeOrToken.GetLeadingTrivia();

                SyntaxTriviaList.Reversed.Enumerator en = leading.Reverse().GetEnumerator();

                if (!en.MoveNext())
                {
                    SyntaxTrivia trivia = binaryExpression.FindTrivia(nodeOrToken.SpanStart - 1);

                    string newText = (trivia.IsEndOfLineTrivia()) ? indentation : endOfLineAndIndentation;

                    int start = (trivia.IsWhitespaceTrivia()) ? trivia.SpanStart : nodeOrToken.SpanStart;

                    TextSpan span = (trivia.IsWhitespaceTrivia())
                        ? trivia.Span
                        : new TextSpan(nodeOrToken.SpanStart, 0);

                    textChanges.Add(span, newText);
                    SetIndendation(nodeOrToken, prevIndex);
                    prevIndex = start;
                    return(true);
                }

                SyntaxTrivia last = en.Current;

                SyntaxKind kind = en.Current.Kind();

                if (kind == SyntaxKind.WhitespaceTrivia)
                {
                    if (en.Current.Span.Length != indentation.Length)
                    {
                        if (!en.MoveNext() ||
                            en.Current.IsEndOfLineTrivia())
                        {
                            SyntaxTrivia trivia = binaryExpression.FindTrivia(nodeOrToken.FullSpan.Start - 1);

                            if (trivia.IsEndOfLineTrivia())
                            {
                                AddTextChange((leading.IsEmptyOrWhitespace()) ? leading.Span : last.Span);
                                SetIndendation(nodeOrToken, prevIndex);
                                prevIndex = trivia.SpanStart;
                                return(true);
                            }
                        }
                    }
                }
                else if (kind == SyntaxKind.EndOfLineTrivia)
                {
                    SyntaxTrivia trivia = binaryExpression.FindTrivia(nodeOrToken.FullSpan.Start - 1);

                    if (trivia.IsEndOfLineTrivia())
                    {
                        AddTextChange((leading.IsEmptyOrWhitespace()) ? leading.Span : last.Span);
                        SetIndendation(nodeOrToken, prevIndex);
                        prevIndex = trivia.SpanStart;
                        return(true);
                    }
                }

                prevIndex = leading.Span.Start - 1;
                return(true);

                void AddTextChange(TextSpan span) => textChanges.Add(span, indentation);
            }

            void SetIndendation(SyntaxNodeOrToken nodeOrToken, int endIndex)
            {
                ImmutableArray <IndentationInfo> indentations = FindIndentations(
                    binaryExpression,
                    TextSpan.FromBounds(nodeOrToken.SpanStart, endIndex))
                                                                .ToImmutableArray();

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

                int firstIndentationLength = indentations[0].Span.Length;

                for (int j = 0; j < indentations.Length; j++)
                {
                    IndentationInfo indentationInfo = indentations[j];

                    string replacement = indentation + indentationAnalysis.GetSingleIndentation();

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

                    if (indentationInfo.Span.Length != replacement.Length)
                    {
                        textChanges.Add(indentationInfo.Span, replacement);
                    }
                }
            }
        }
Exemplo n.º 5
0
        public static Task <Document> FixCallChainAsync(
            Document document,
            ExpressionSyntax expression,
            TextSpan span,
            CancellationToken cancellationToken = default)
        {
            IndentationAnalysis indentationAnalysis = AnalyzeIndentation(expression, cancellationToken);
            string indentation             = indentationAnalysis.GetIncreasedIndentation();
            string endOfLineAndIndentation = DetermineEndOfLine(expression).ToString() + indentation;

            var textChanges = new List <TextChange>();
            int prevIndex   = expression.Span.End;

            foreach (SyntaxNode node in new MethodChain(expression))
            {
                SyntaxKind kind = node.Kind();

                if (kind == SyntaxKind.SimpleMemberAccessExpression)
                {
                    var memberAccess = (MemberAccessExpressionSyntax)node;

                    if (!SetIndentation(memberAccess.OperatorToken))
                    {
                        break;
                    }
                }
                else if (kind == SyntaxKind.MemberBindingExpression)
                {
                    var memberBinding = (MemberBindingExpressionSyntax)node;

                    if (!SetIndentation(memberBinding.OperatorToken))
                    {
                        break;
                    }
                }
            }

            FormattingVerifier.VerifyChangedSpansAreWhitespace(expression, textChanges);

            return(document.WithTextChangesAsync(textChanges, cancellationToken));

            bool SetIndentation(SyntaxToken token)
            {
                if (token.Span.End > span.End)
                {
                    return(true);
                }

                if (token.SpanStart < span.Start)
                {
                    return(false);
                }

                SyntaxTriviaList leading = token.LeadingTrivia;

                SyntaxTriviaList.Reversed.Enumerator en = leading.Reverse().GetEnumerator();

                if (!en.MoveNext())
                {
                    SyntaxTrivia trivia = expression.FindTrivia(token.SpanStart - 1);

                    string newText = (trivia.IsEndOfLineTrivia()) ? indentation : endOfLineAndIndentation;

                    textChanges.Add(new TextSpan(token.SpanStart, 0), newText);

                    SetIndendation(token, prevIndex);
                    prevIndex = (trivia.IsEndOfLineTrivia()) ? trivia.SpanStart : token.SpanStart;
                    return(true);
                }

                SyntaxTrivia last = en.Current;

                SyntaxKind kind = en.Current.Kind();

                if (kind == SyntaxKind.WhitespaceTrivia)
                {
                    if (en.Current.Span.Length != indentation.Length)
                    {
                        if (!en.MoveNext() ||
                            en.Current.IsEndOfLineTrivia())
                        {
                            SyntaxTrivia trivia = expression.FindTrivia(token.FullSpan.Start - 1);

                            if (trivia.IsEndOfLineTrivia())
                            {
                                textChanges.Add((leading.IsEmptyOrWhitespace()) ? leading.Span : last.Span, indentation);
                                SetIndendation(token, prevIndex);
                                prevIndex = trivia.SpanStart;
                                return(true);
                            }
                        }
                    }
                }
                else if (kind == SyntaxKind.EndOfLineTrivia)
                {
                    SyntaxTrivia trivia = expression.FindTrivia(token.FullSpan.Start - 1);

                    if (trivia.IsEndOfLineTrivia())
                    {
                        textChanges.Add((leading.IsEmptyOrWhitespace()) ? leading.Span : last.Span, indentation);
                        SetIndendation(token, prevIndex);
                        prevIndex = trivia.SpanStart;
                        return(true);
                    }
                }

                prevIndex = leading.Span.Start - 1;
                return(true);
            }

            void SetIndendation(SyntaxToken token, int endIndex)
            {
                ImmutableArray <IndentationInfo> indentations = FindIndentations(
                    expression,
                    TextSpan.FromBounds(token.SpanStart, endIndex))
                                                                .ToImmutableArray();

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

                int firstIndentationLength = indentations[0].Span.Length;

                for (int j = 0; j < indentations.Length; j++)
                {
                    IndentationInfo indentationInfo = indentations[j];

                    string replacement = indentation + indentationAnalysis.GetSingleIndentation();

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

                    if (indentationInfo.Span.Length != replacement.Length)
                    {
                        textChanges.Add(indentationInfo.Span, replacement);
                    }
                }
            }
        }
Exemplo n.º 6
0
        private static void AnalyzeExpression(SyntaxNodeAnalysisContext context)
        {
            var expression = (ExpressionSyntax)context.Node;

            if (expression.IsParentKind(
                    SyntaxKind.ConditionalAccessExpression,
                    SyntaxKind.SimpleMemberAccessExpression,
                    SyntaxKind.ElementAccessExpression,
                    SyntaxKind.MemberBindingExpression,
                    SyntaxKind.InvocationExpression))
            {
                return;
            }

            MethodChain.Enumerator en = new MethodChain(expression).GetEnumerator();

            if (!en.MoveNext())
            {
                return;
            }

            TextLineCollection lines = null;
            int startLine            = -1;
            IndentationAnalysis indentationAnalysis = default;

            do
            {
                context.CancellationToken.ThrowIfCancellationRequested();

                SyntaxKind kind = en.Current.Kind();

                if (kind == SyntaxKind.SimpleMemberAccessExpression)
                {
                    var memberAccess = (MemberAccessExpressionSyntax)en.Current;

                    if (AnalyzeToken(memberAccess.OperatorToken))
                    {
                        return;
                    }
                }
                else if (en.Current.Kind() == SyntaxKind.MemberBindingExpression)
                {
                    var memberBinding = (MemberBindingExpressionSyntax)en.Current;

                    if (AnalyzeToken(memberBinding.OperatorToken))
                    {
                        return;
                    }
                }
            } while (en.MoveNext());

            bool AnalyzeToken(SyntaxToken token)
            {
                SyntaxTriviaList.Reversed.Enumerator en = token.LeadingTrivia.Reverse().GetEnumerator();

                if (!en.MoveNext())
                {
                    if (lines == null)
                    {
                        lines     = expression.SyntaxTree.GetText().Lines;
                        startLine = lines.IndexOf(expression.SpanStart);
                    }

                    int endLine = lines.IndexOf(token.SpanStart);

                    if (startLine != endLine)
                    {
                        ReportDiagnostic();
                    }

                    return(true);
                }

                switch (en.Current.Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                {
                    if (indentationAnalysis.IsDefault)
                    {
                        indentationAnalysis = AnalyzeIndentation(expression);
                    }

                    if (en.Current.Span.Length != indentationAnalysis.IncreasedIndentationLength)
                    {
                        if (!en.MoveNext() ||
                            en.Current.IsEndOfLineTrivia())
                        {
                            if (expression.FindTrivia(token.FullSpan.Start - 1).IsEndOfLineTrivia())
                            {
                                ReportDiagnostic();
                                return(true);
                            }
                        }

                        break;
                    }

                    break;
                }

                case SyntaxKind.EndOfLineTrivia:
                {
                    if (expression.FindTrivia(token.FullSpan.Start - 1).IsEndOfLineTrivia())
                    {
                        ReportDiagnostic();
                        return(true);
                    }

                    break;
                }
                }

                return(false);
            }

            void ReportDiagnostic()
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticDescriptors.FixFormattingOfCallChain,
                    expression);
            }
        }
        private static void AnalyzeBinaryExpression(SyntaxNodeAnalysisContext context)
        {
            var topBinaryExpression = (BinaryExpressionSyntax)context.Node;

            SyntaxKind binaryKind = topBinaryExpression.Kind();

            if (topBinaryExpression.IsParentKind(binaryKind))
            {
                return;
            }

            if (topBinaryExpression.IsSingleLine(includeExteriorTrivia: false))
            {
                return;
            }

            int?indentationLength = null;

            BinaryExpressionSyntax binaryExpression = topBinaryExpression;

            while (true)
            {
                context.CancellationToken.ThrowIfCancellationRequested();

                ExpressionSyntax left  = binaryExpression.Left;
                SyntaxToken      token = binaryExpression.OperatorToken;

                SyntaxTriviaList leftTrailing  = left.GetTrailingTrivia();
                SyntaxTriviaList tokenTrailing = token.TrailingTrivia;

                if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(leftTrailing))
                {
                    if (Analyze(token))
                    {
                        return;
                    }
                }
                else if (IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(tokenTrailing))
                {
                    if (Analyze(binaryExpression.Right))
                    {
                        return;
                    }
                }
                else if (leftTrailing.IsEmptyOrWhitespace() &&
                         tokenTrailing.IsEmptyOrWhitespace())
                {
                    ReportDiagnostic();
                    return;
                }

                if (!left.IsKind(binaryKind))
                {
                    break;
                }

                binaryExpression = (BinaryExpressionSyntax)left;
            }

            bool Analyze(SyntaxNodeOrToken nodeOrToken)
            {
                SyntaxTriviaList.Reversed.Enumerator en = nodeOrToken.GetLeadingTrivia().Reverse().GetEnumerator();

                if (!en.MoveNext())
                {
                    if ((indentationLength ??= GetIndentationLength()) == -1)
                    {
                        return(true);
                    }

                    ReportDiagnostic();
                    return(true);
                }

                switch (en.Current.Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                {
                    if ((indentationLength ??= GetIndentationLength()) == -1)
                    {
                        return(true);
                    }

                    if (en.Current.Span.Length != indentationLength)
                    {
                        if (!en.MoveNext() ||
                            en.Current.IsEndOfLineTrivia())
                        {
                            if (topBinaryExpression.FindTrivia(nodeOrToken.FullSpan.Start - 1).IsEndOfLineTrivia())
                            {
                                ReportDiagnostic();
                                return(true);
                            }
                        }

                        break;
                    }

                    break;
                }

                case SyntaxKind.EndOfLineTrivia:
                {
                    if (topBinaryExpression.FindTrivia(nodeOrToken.FullSpan.Start - 1).IsEndOfLineTrivia())
                    {
                        if ((indentationLength ??= GetIndentationLength()) == -1)
                        {
                            return(true);
                        }

                        ReportDiagnostic();
                        return(true);
                    }

                    break;
                }
                }

                return(false);
            }

            int GetIndentationLength()
            {
                IndentationAnalysis indentationAnalysis = AnalyzeIndentation(topBinaryExpression);

                if (indentationAnalysis.IndentSize == 0)
                {
                    return(-1);
                }

                SyntaxTriviaList leadingTrivia = topBinaryExpression.GetLeadingTrivia();

                if (leadingTrivia.Any() &&
                    leadingTrivia.Last() == indentationAnalysis.Indentation &&
                    context.GetConfigOptions().GetBinaryOperatorNewLinePosition() == NewLinePosition.After)
                {
                    return(indentationAnalysis.IndentationLength);
                }
                else
                {
                    return(indentationAnalysis.IncreasedIndentationLength);
                }
            }

            void ReportDiagnostic()
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticRules.FixFormattingOfBinaryExpressionChain,
                    topBinaryExpression);
            }
        }