/// <summary>
        /// Gets a value indicating whether the <paramref name="token"/> is preceded by a whitespace.
        /// </summary>
        /// <param name="token">The token to process.</param>
        /// <returns>true if token is preceded by a whitespace, otherwise false.</returns>
        internal static bool IsPrecededByWhitespace(this SyntaxToken token)
        {
            SyntaxTriviaList triviaList = token.LeadingTrivia;

            if (triviaList.Count > 0)
            {
                return(triviaList.Last().IsKind(SyntaxKind.WhitespaceTrivia));
            }

            triviaList = token.GetPreviousToken().TrailingTrivia;
            return(triviaList.Count > 0 && triviaList.Last().IsKind(SyntaxKind.WhitespaceTrivia));
        }
Пример #2
0
        /// <summary>
        /// Remove all extra new lines from the begining of a close brace token.  This is only called in
        /// the case at least one new line is present hence we don't have to worry about the single line
        /// case.
        /// </summary>
        private static SyntaxTriviaList RemoveNewLinesFromBottom(SyntaxTriviaList triviaList)
        {
            var index     = triviaList.Count - 1;
            var searching = true;

            while (index >= 0 && searching)
            {
                var current = triviaList[index];
                switch (current.Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                case SyntaxKind.EndOfLineTrivia:
                    index--;
                    break;

                default:
                    searching = false;
                    break;
                }
            }

            // Nothing to adjust, the removal of new lines from the top of the list will handle all of the
            // important cases.
            if (index < 0)
            {
                return(triviaList);
            }

            var list = new List <SyntaxTrivia>(triviaList.Count);

            for (int i = 0; i <= index; i++)
            {
                list.Add(triviaList[i]);
            }

            // A directive has an implicit new line after it.
            if (!list[index].IsDirective)
            {
                list.Add(SyntaxUtil.GetBestNewLineTrivia(triviaList));
            }

            if (triviaList.Last().IsKind(SyntaxKind.WhitespaceTrivia))
            {
                list.Add(triviaList.Last());
            }

            return(SyntaxFactory.TriviaList(list));
        }
Пример #3
0
        private static void Analyze(
            SyntaxNodeAnalysisContext context,
            UsingDirectiveSyntax usingDirective,
            SyntaxToken nextToken)
        {
            SyntaxTriviaList trailingTrivia = usingDirective.GetTrailingTrivia();

            if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(triviaList: trailingTrivia))
            {
                return;
            }

            SyntaxTriviaList.Enumerator en = nextToken.LeadingTrivia.GetEnumerator();

            if (en.MoveNext())
            {
                if (en.Current.IsWhitespaceTrivia() &&
                    !en.MoveNext())
                {
                    ReportDiagnostic(trailingTrivia.Last().SpanStart);
                }
                else
                {
                    switch (en.Current.Kind())
                    {
                    case SyntaxKind.SingleLineCommentTrivia:
                    case SyntaxKind.SingleLineDocumentationCommentTrivia:
                    case SyntaxKind.MultiLineDocumentationCommentTrivia:
                    {
                        ReportDiagnostic(trailingTrivia.Last().SpanStart);
                        break;
                    }
                    }
                }
            }
            else
            {
                ReportDiagnostic(trailingTrivia.Last().SpanStart);
            }

            void ReportDiagnostic(int position)
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticRules.AddBlankLineAfterUsingDirectiveList,
                    Location.Create(usingDirective.SyntaxTree, new TextSpan(position, 0)));
            }
        }
Пример #4
0
        private static void AnalyzeElseClause(SyntaxNodeAnalysisContext context)
        {
            var elseClause = (ElseClauseSyntax)context.Node;

            StatementSyntax statement = elseClause.Statement;

            if (!statement.IsKind(SyntaxKind.IfStatement))
            {
                return;
            }

            SyntaxTriviaList trailingTrivia = elseClause.ElseKeyword.TrailingTrivia;

            if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenEndOfLineTrivia(trailingTrivia))
            {
                return;
            }

            if (!statement.GetLeadingTrivia().IsEmptyOrWhitespace())
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(
                context,
                DiagnosticDescriptors.RemoveNewLineBetweenIfKeywordAndElseKeyword,
                Location.Create(elseClause.SyntaxTree, new TextSpan(trailingTrivia.Last().SpanStart, 0)));
        }
Пример #5
0
        private static void AnalyzeDoStatement(SyntaxNodeAnalysisContext context)
        {
            var doStatement = (DoStatementSyntax)context.Node;

            StatementSyntax statement = doStatement.Statement;

            if (!statement.IsKind(SyntaxKind.Block))
            {
                return;
            }

            SyntaxTriviaList trailingTrivia = statement.GetTrailingTrivia();

            if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenEndOfLineTrivia(trailingTrivia))
            {
                return;
            }

            if (!doStatement.WhileKeyword.LeadingTrivia.IsEmptyOrWhitespace())
            {
                return;
            }

            context.ReportDiagnostic(
                DiagnosticDescriptors.RemoveNewLineBetweenClosingBraceAndWhileKeyword,
                Location.Create(doStatement.SyntaxTree, new TextSpan(trailingTrivia.Last().SpanStart, 0)));
        }
Пример #6
0
        private async Task <Document> AddSuppressionCommentAsync(CodeFixContext context, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var document = context.Document;
            var root     = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var node = root?.FindNode(context.Span);

            if (diagnostic == null || node == null || cancellationToken.IsCancellationRequested)
            {
                return(document);
            }

            var(diagnosticShortName, diagnosticJustification) = GetDiagnosticShortNameAndJustification(diagnostic);

            if (!string.IsNullOrWhiteSpace(diagnosticShortName))
            {
                SyntaxTriviaList commentNode = SyntaxFactory.TriviaList(
                    SyntaxFactory.SyntaxTrivia(SyntaxKind.SingleLineCommentTrivia,
                                               string.Format(_comment, diagnostic.Id, diagnosticShortName, diagnosticJustification)),
                    SyntaxFactory.ElasticEndOfLine(""));

                while (!(node == null || node is StatementSyntax || node is MemberDeclarationSyntax))
                {
                    node = node.Parent;
                }

                SyntaxTriviaList leadingTrivia = node.GetLeadingTrivia();
                var modifiedRoot = root.InsertTriviaAfter(leadingTrivia.Last(), commentNode);

                return(document.WithSyntaxRoot(modifiedRoot));
            }

            return(document);
        }
        private static void AnalyzeSwitchStatement(SyntaxNodeAnalysisContext context)
        {
            var switchStatement = (SwitchStatementSyntax)context.Node;

            SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections;

            SyntaxList <SwitchSectionSyntax> .Enumerator en = sections.GetEnumerator();

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

            SwitchSectionSyntax previousSection = en.Current;

            while (en.MoveNext())
            {
                SyntaxTriviaList leadingTrivia = en.Current.Labels[0].GetLeadingTrivia();

                if (SyntaxTriviaAnalysis.IsEmptyOrSingleWhitespaceTrivia(leadingTrivia))
                {
                    SyntaxTriviaList trailingTrivia = previousSection.GetTrailingTrivia();

                    if (SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia))
                    {
                        DiagnosticHelpers.ReportDiagnostic(
                            context,
                            DiagnosticDescriptors.AddEmptyLineBetweenSwitchSections,
                            Location.Create(switchStatement.SyntaxTree, trailingTrivia.Last().Span.WithLength(0)));
                    }
                }

                previousSection = en.Current;
            }
        }
 internal T WithPrependedLeadingTrivia <T>(T node, SyntaxTriviaList trivia) where T : SyntaxNode
 {
     if (trivia.Count == 0)
     {
         return(node);
     }
     if (trivia.Last().IsKind(VB.SyntaxKind.CommentTrivia))
     {
         trivia = trivia.Add(global::VisualBasicSyntaxFactory.VBEOLTrivia);
     }
     return(node.WithLeadingTrivia(trivia.Concat(node.GetLeadingTrivia())));
 }
Пример #9
0
        private static List <BaseFieldDeclarationSyntax> DeclarationSplitter(
            Document document,
            VariableDeclarationSyntax declaration,
            Func <VariableDeclarationSyntax, BaseFieldDeclarationSyntax> declarationFactory,
            SyntaxTriviaList declarationTrailingTrivia)
        {
            SeparatedSyntaxList <VariableDeclaratorSyntax> variables = declaration.Variables;
            VariableDeclaratorSyntax   first    = variables.First();
            BaseFieldDeclarationSyntax previous = null;
            var newFieldDeclarations            = new List <BaseFieldDeclarationSyntax>(variables.Count);

            foreach (SyntaxNodeOrToken nodeOrToken in variables.GetWithSeparators())
            {
                if (previous == null)
                {
                    VariableDeclaratorSyntax variable = (VariableDeclaratorSyntax)nodeOrToken.AsNode();
                    variable = variable.WithIdentifier(variable.Identifier.WithoutLeadingWhitespace());
                    var variableDeclarator = SyntaxFactory.SingletonSeparatedList(variable);
                    previous = declarationFactory(declaration.WithVariables(variableDeclarator));

                    if (variable != first)
                    {
                        var triviaList = previous.GetLeadingTrivia().WithoutDirectiveTrivia();
                        previous = previous.WithLeadingTrivia(triviaList);
                    }
                }
                else
                {
                    SyntaxToken      commaToken     = nodeOrToken.AsToken();
                    SyntaxTriviaList trailingTrivia = commaToken.TrailingTrivia;
                    if (trailingTrivia.Any())
                    {
                        if (!trailingTrivia.Last().IsKind(SyntaxKind.EndOfLineTrivia))
                        {
                            trailingTrivia = trailingTrivia.WithoutTrailingWhitespace().Add(FormattingHelper.GetNewLineTrivia(document));
                        }
                    }
                    else
                    {
                        trailingTrivia = SyntaxTriviaList.Create(FormattingHelper.GetNewLineTrivia(document));
                    }

                    newFieldDeclarations.Add(previous.WithTrailingTrivia(trailingTrivia));
                    previous = null;
                }
            }

            newFieldDeclarations.Add(previous.WithTrailingTrivia(declarationTrailingTrivia));
            return(newFieldDeclarations);
        }
        private static void AnalyzeDoStatement(SyntaxNodeAnalysisContext context)
        {
            var doStatement = (DoStatementSyntax)context.Node;

            StatementSyntax statement = doStatement.Statement;

            if (!statement.IsKind(SyntaxKind.Block))
            {
                return;
            }

            NewLineStyle newLineStyle = context.GetNewLineBeforeWhileInDoStatement();

            if (newLineStyle == NewLineStyle.None)
            {
                return;
            }

            SyntaxTriviaList trailingTrivia = statement.GetTrailingTrivia();

            if (!trailingTrivia.Any() ||
                trailingTrivia.SingleOrDefault(shouldThrow: false).IsWhitespaceTrivia())
            {
                if (!doStatement.WhileKeyword.LeadingTrivia.Any() &&
                    newLineStyle == NewLineStyle.Add)
                {
                    context.ReportDiagnostic(
                        DiagnosticRules.AddOrRemoveNewLineBeforeWhileInDoStatement,
                        Location.Create(doStatement.SyntaxTree, new TextSpan(statement.FullSpan.End, 0)),
                        "Add");
                }
            }
            else if (SyntaxTriviaAnalysis.IsOptionalWhitespaceThenEndOfLineTrivia(trailingTrivia))
            {
                if (doStatement.WhileKeyword.LeadingTrivia.IsEmptyOrWhitespace() &&
                    newLineStyle == NewLineStyle.Remove)
                {
                    context.ReportDiagnostic(
                        DiagnosticRules.AddOrRemoveNewLineBeforeWhileInDoStatement,
                        Location.Create(doStatement.SyntaxTree, new TextSpan(trailingTrivia.Last().SpanStart, 0)),
                        properties: DiagnosticProperties.AnalyzerOption_Invert,
                        "Remove");
                }
            }
        }
Пример #11
0
        private static void Analyze(SyntaxNodeAnalysisContext context, BaseListSyntax baseList, SyntaxToken previousToken)
        {
            SyntaxTriviaList trailingTrivia = previousToken.TrailingTrivia;

            if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenEndOfLineTrivia(trailingTrivia))
            {
                return;
            }

            if (!baseList.ColonToken.LeadingTrivia.IsEmptyOrWhitespace())
            {
                return;
            }

            context.ReportDiagnostic(
                DiagnosticDescriptors.RemoveNewLineBeforeBaseList,
                Location.Create(baseList.SyntaxTree, new TextSpan(trailingTrivia.Last().SpanStart, 0)));
        }
Пример #12
0
        internal static bool IsFixable(ExpressionSyntax expression, SyntaxToken token)
        {
            SyntaxTriviaList expressionTrailing = expression.GetTrailingTrivia();

            if (expressionTrailing.IsEmptyOrWhitespace())
            {
                SyntaxTriviaList tokenLeading = token.LeadingTrivia;

                if (tokenLeading.IsEmptyOrWhitespace())
                {
                    SyntaxTriviaList tokenTrailing = token.TrailingTrivia;

                    int count = tokenTrailing.Count;

                    if (count == 1)
                    {
                        if (tokenTrailing[0].IsEndOfLineTrivia())
                        {
                            return(true);
                        }
                    }
                    else if (count > 1)
                    {
                        for (int i = 0; i < count - 1; i++)
                        {
                            if (!tokenTrailing[i].IsWhitespaceTrivia())
                            {
                                return(false);
                            }
                        }

                        if (tokenTrailing.Last().IsEndOfLineTrivia())
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
        private static void AnalyzeSwitchStatement(SyntaxNodeAnalysisContext context)
        {
            var switchStatement = (SwitchStatementSyntax)context.Node;

            SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections;

            SyntaxList <SwitchSectionSyntax> .Enumerator en = sections.GetEnumerator();

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

            SwitchSectionSyntax previousSection = en.Current;

            var previousBlock = previousSection.Statements.SingleOrDefault(shouldThrow: false) as BlockSyntax;

            while (en.MoveNext())
            {
                SyntaxTriviaList leadingTrivia = en.Current.Labels[0].GetLeadingTrivia();

                if (SyntaxTriviaAnalysis.IsEmptyOrSingleWhitespaceTrivia(leadingTrivia))
                {
                    SyntaxTriviaList trailingTrivia = previousSection.GetTrailingTrivia();

                    if (SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia) &&
                        (context.GetBlankLineBetweenClosingBraceAndSwitchSection() != false ||
                         previousBlock == null))
                    {
                        DiagnosticHelpers.ReportDiagnostic(
                            context,
                            DiagnosticRules.AddBlankLineBetweenSwitchSections,
                            Location.Create(switchStatement.SyntaxTree, trailingTrivia.Last().Span.WithLength(0)));
                    }
                }

                previousSection = en.Current;

                previousBlock = en.Current.Statements.SingleOrDefault(shouldThrow: false) as BlockSyntax;
            }
        }
        private static Task <Document> AddBlankLineBeforeUsingDirectiveAsync(
            Document document,
            UsingDirectiveSyntax usingDirective,
            CancellationToken cancellationToken)
        {
            SyntaxTriviaList leadingTrivia = usingDirective.GetLeadingTrivia();

            int index = leadingTrivia.Count;

            if (index > 0 &&
                leadingTrivia.Last().IsWhitespaceTrivia())
            {
                index--;
            }

            SyntaxTriviaList newLeadingTrivia = leadingTrivia.Insert(index, SyntaxTriviaAnalysis.DetermineEndOfLine(usingDirective));

            UsingDirectiveSyntax newUsingDirective = usingDirective.WithLeadingTrivia(newLeadingTrivia);

            return(document.ReplaceNodeAsync(usingDirective, newUsingDirective, cancellationToken));
        }
Пример #15
0
        private static void AnalyzeDoStatement(SyntaxNodeAnalysisContext context)
        {
            var doStatement = (DoStatementSyntax)context.Node;

            StatementSyntax statement = doStatement.Statement;

            if (!statement.IsKind(SyntaxKind.Block))
            {
                return;
            }

            SyntaxTriviaList trailingTrivia = statement.GetTrailingTrivia();

            if (!trailingTrivia.Any() ||
                trailingTrivia.SingleOrDefault(shouldThrow: false).IsWhitespaceTrivia())
            {
                if (!doStatement.WhileKeyword.LeadingTrivia.Any() &&
                    !AnalyzerOptions.RemoveNewLineBetweenClosingBraceAndWhileKeyword.IsEnabled(context))
                {
                    context.ReportDiagnostic(
                        DiagnosticRules.AddNewLineBetweenClosingBraceAndWhileKeywordOrViceVersa,
                        Location.Create(doStatement.SyntaxTree, new TextSpan(statement.FullSpan.End, 0)),
                        AnalyzerOptions.RemoveNewLineBetweenClosingBraceAndWhileKeyword);
                }
            }
            else if (SyntaxTriviaAnalysis.IsOptionalWhitespaceThenEndOfLineTrivia(trailingTrivia))
            {
                if (doStatement.WhileKeyword.LeadingTrivia.IsEmptyOrWhitespace() &&
                    AnalyzerOptions.RemoveNewLineBetweenClosingBraceAndWhileKeyword.IsEnabled(context))
                {
                    context.ReportDiagnostic(
                        DiagnosticRules.ReportOnly.RemoveNewLineBetweenClosingBraceAndWhileKeyword,
                        Location.Create(doStatement.SyntaxTree, new TextSpan(trailingTrivia.Last().SpanStart, 0)),
                        properties: DiagnosticProperties.AnalyzerOption_Invert,
                        AnalyzerOptions.RemoveNewLineBetweenClosingBraceAndWhileKeyword);
                }
            }
        }
Пример #16
0
        private static SyntaxTrivia GetIndentation(SyntaxNode node, CancellationToken cancellationToken = default(CancellationToken))
        {
            SyntaxTree tree = node.SyntaxTree;

            if (tree != null)
            {
                TextSpan span = node.Span;

                int lineStartIndex = span.Start - tree.GetLineSpan(span, cancellationToken).StartLinePosition.Character;

                while (!node.FullSpan.Contains(lineStartIndex))
                {
                    node = node.Parent;
                }

                SyntaxToken token = node.FindToken(lineStartIndex);

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

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

                        if (trivia.IsWhitespaceTrivia())
                        {
                            return(trivia);
                        }
                    }
                }
            }

            return(EmptyWhitespace());
        }
Пример #17
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);
        }
Пример #18
0
        private static void AnalyzeAccessorList(SyntaxNodeAnalysisContext context)
        {
            var accessorList = (AccessorListSyntax)context.Node;

            SyntaxList <AccessorDeclarationSyntax> accessors = accessorList.Accessors;

            if (accessors.Count <= 1)
            {
                return;
            }

            Debug.Assert(accessors.Count == 2, accessors.Count.ToString());

            AccessorDeclarationSyntax accessor1 = accessors[0];

            if (accessor1.BodyOrExpressionBody() == null)
            {
                return;
            }

            AccessorDeclarationSyntax accessor2 = accessors[1];

            if (accessor2.BodyOrExpressionBody() == null)
            {
                return;
            }

            SyntaxTriviaList trailingTrivia = accessor1.GetTrailingTrivia();

            if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia))
            {
                return;
            }

            SyntaxTriviaList leadingTrivia = accessor2.GetLeadingTrivia();

            bool isEmptyLine = SyntaxTriviaAnalysis.StartsWithOptionalWhitespaceThenEndOfLineTrivia(leadingTrivia);

            if (accessorList.SyntaxTree.IsSingleLineSpan(accessor1.Span, context.CancellationToken) &&
                accessorList.SyntaxTree.IsSingleLineSpan(accessor2.Span, context.CancellationToken))
            {
                if (isEmptyLine)
                {
                    ReportDiagnostic(context, DiagnosticDescriptors.RemoveEmptyLineBetweenSingleLineAccessors, leadingTrivia[0]);
                }
                else
                {
                    ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenSingleLineAccessors, trailingTrivia.Last());
                }
            }
            else if (!isEmptyLine)
            {
                ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenAccessors, trailingTrivia.Last());
            }
        }
Пример #19
0
        public SyntaxNode TraverseAndConvert(SyntaxNode node, SyntaxNode newNode)
        {
            // Step 1: Handle current node
            // Find out if this node is a documentable API declaration
            // If not, skip to go to the child nodes.
            string docCommentId = GetAPIForNode(node);

            if (docCommentId != null)

            {
                // Look up the comment text
                string docCommentText = GetDocCommentForId(docCommentId);

                // Get the SyntaxTrivia for the comment
                SyntaxTree newTree   = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText(docCommentText);
                var        newTrivia = newTree.GetRoot().GetLeadingTrivia();
                // Read a doc comment from a syntax tree.
                //var classNode = (ClassDeclarationSyntax)newTree.GetRoot().ChildNodes().First();
                //var newTrivia = classNode.GetLeadingTrivia();
                //var docCommentTrivia = newTrivia.Single(t => t.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia ||
                //                                       t.Kind() == SyntaxKind.MultiLineDocumentationCommentTrivia);

                // Find out if there is an existing comment or doc comment
                if (node.HasLeadingTrivia)
                {
                    SyntaxTriviaList triviaList   = node.GetLeadingTrivia();
                    SyntaxTrivia     firstComment = triviaList.Last();
                    foreach (var trivia in triviaList.Reverse())
                    {
                        SyntaxKind kind = trivia.Kind();

                        switch (kind)
                        {
                        case SyntaxKind.SingleLineCommentTrivia:
                        case SyntaxKind.MultiLineCommentTrivia:
                            // Found existing comment
                            firstComment = trivia;
                            break;

                        case SyntaxKind.MultiLineDocumentationCommentTrivia:
                        case SyntaxKind.SingleLineDocumentationCommentTrivia:
                            // Found existing XML doc comment
                            firstComment = trivia;
                            break;

                        default:
                            break;
                        }
                    }


                    // Append the doc comment
                    newNode = node.InsertTriviaBefore(firstComment, newTrivia);
                }
                else // no leading trivia
                {
                    newNode = node.WithLeadingTrivia(newTrivia);
                }
            }
            else // not an API node
            {
                newNode = node;
            }

            if (node.ChildNodes().Count() > 0)
            {
                newNode = newNode.ReplaceNodes(newNode.ChildNodes(), TraverseAndConvert);
            }
            return(newNode);
        }
        private static void AnalyzeUsings(SyntaxNodeAnalysisContext context, SyntaxList <UsingDirectiveSyntax> usings)
        {
            int count = usings.Count;

            if (count <= 1)
            {
                return;
            }

            UsingDirectiveSyntax usingDirective1 = usings[0];

            for (int i = 1; i < count; i++, usingDirective1 = usings[i - 1])
            {
                if (usingDirective1.StaticKeyword.IsKind(SyntaxKind.StaticKeyword))
                {
                    return;
                }

                if (usingDirective1.Alias != null)
                {
                    return;
                }

                UsingDirectiveSyntax usingDirective2 = usings[i];

                if (usingDirective2.StaticKeyword.IsKind(SyntaxKind.StaticKeyword))
                {
                    return;
                }

                if (usingDirective2.Alias != null)
                {
                    return;
                }

                SyntaxTriviaList trailingTrivia = usingDirective1.GetTrailingTrivia();

                if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia))
                {
                    continue;
                }

                IdentifierNameSyntax rootNamespace1 = usingDirective1.GetRootNamespace();

                if (rootNamespace1 == null)
                {
                    continue;
                }

                IdentifierNameSyntax rootNamespace2 = usingDirective2.GetRootNamespace();

                if (rootNamespace2 == null)
                {
                    continue;
                }

                SyntaxTriviaList leadingTrivia = usingDirective2.GetLeadingTrivia();

                bool isEmptyLine = SyntaxTriviaAnalysis.StartsWithOptionalWhitespaceThenEndOfLineTrivia(leadingTrivia);

                if (string.Equals(rootNamespace1.Identifier.ValueText, rootNamespace2.Identifier.ValueText, StringComparison.Ordinal))
                {
                    if (isEmptyLine)
                    {
                        DiagnosticHelpers.ReportDiagnosticIfNotSuppressed(
                            context,
                            DiagnosticDescriptors.RemoveEmptyLineBetweenUsingDirectivesWithSameRootNamespace,
                            Location.Create(context.Node.SyntaxTree, leadingTrivia[0].Span.WithLength(0)));
                    }
                }
                else if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.AddEmptyLineBetweenUsingDirectivesWithDifferentRootNamespaceOrViceVersa))
                {
                    if (isEmptyLine)
                    {
                        if (!context.IsAnalyzerSuppressed(AnalyzerOptions.RemoveEmptyLineBetweenUsingDirectivesWithDifferentRootNamespace))
                        {
                            DiagnosticHelpers.ReportDiagnostic(
                                context,
                                DiagnosticDescriptors.ReportOnly.RemoveEmptyLineBetweenUsingDirectivesWithDifferentRootNamespace,
                                Location.Create(context.Node.SyntaxTree, leadingTrivia[0].Span.WithLength(0)),
                                properties: DiagnosticProperties.AnalyzerOption_Invert);
                        }
                    }
                    else if (context.IsAnalyzerSuppressed(AnalyzerOptions.RemoveEmptyLineBetweenUsingDirectivesWithDifferentRootNamespace))
                    {
                        DiagnosticHelpers.ReportDiagnostic(
                            context,
                            DiagnosticDescriptors.AddEmptyLineBetweenUsingDirectivesWithDifferentRootNamespaceOrViceVersa,
                            Location.Create(context.Node.SyntaxTree, trailingTrivia.Last().Span.WithLength(0)));
                    }
                }
            }
        }
Пример #21
0
        private static void HandleSemicolonToken(SyntaxTreeAnalysisContext context, SyntaxToken token)
        {
            if (token.IsMissing)
            {
                return;
            }

            // check for a following space
            bool missingFollowingSpace = true;

            if (token.HasTrailingTrivia)
            {
                if (token.TrailingTrivia.First().IsKind(SyntaxKind.WhitespaceTrivia))
                {
                    missingFollowingSpace = false;
                }
                else if (token.TrailingTrivia.First().IsKind(SyntaxKind.EndOfLineTrivia))
                {
                    missingFollowingSpace = false;
                }
            }
            else
            {
                SyntaxToken nextToken = token.GetNextToken();
                switch (nextToken.Kind())
                {
                case SyntaxKind.CloseParenToken:
                    // Special handling for the following case:
                    // for (; ;)
                    missingFollowingSpace = false;
                    break;

                case SyntaxKind.SemicolonToken:
                    // Special handling for the following case:
                    // Statement();;
                    if (nextToken.Parent.IsKind(SyntaxKind.EmptyStatement))
                    {
                        missingFollowingSpace = false;
                    }

                    break;

                case SyntaxKind.None:
                    // The semi colon is the last character in the file.
                    return;

                default:
                    break;
                }
            }

            bool hasPrecedingSpace    = false;
            bool ignorePrecedingSpace = false;

            if (!token.IsFirstInLine())
            {
                // only the first token on the line has leading trivia, and those are ignored
                SyntaxToken      precedingToken = token.GetPreviousToken();
                SyntaxTriviaList trailingTrivia = precedingToken.TrailingTrivia;
                if (trailingTrivia.Any() && trailingTrivia.Last().IsKind(SyntaxKind.WhitespaceTrivia))
                {
                    hasPrecedingSpace = true;
                }

                if (precedingToken.IsKind(SyntaxKind.SemicolonToken))
                {
                    // Special handling for the following case:
                    // for (; ;)
                    ignorePrecedingSpace = true;
                }
            }

            if (missingFollowingSpace)
            {
                // semicolon should{} be {followed} by a space
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), TokenSpacingProperties.InsertFollowing, string.Empty, "followed"));
            }

            if (hasPrecedingSpace && !ignorePrecedingSpace)
            {
                // semicolon should{ not} be {preceded} by a space
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), TokenSpacingProperties.RemoveImmediatePreceding, " not", "preceded"));
            }
        }
Пример #22
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out CompilationUnitSyntax compilationUnit))
            {
                return;
            }

            Document   document   = context.Document;
            Diagnostic diagnostic = context.Diagnostics[0];

            switch (diagnostic.Id)
            {
            case DiagnosticIdentifiers.NormalizeWhitespaceAtEndOfFile:
            {
                bool preferNewLineAtEndOfFile = document.GetConfigOptions(compilationUnit.SyntaxTree).PreferNewLineAtEndOfFile() ?? false;

                CodeAction codeAction = CodeAction.Create(
                    (preferNewLineAtEndOfFile) ? CodeFixTitles.AddNewLine : CodeFixTitles.RemoveNewLine,
                    ct =>
                    {
                        SyntaxToken endOfFile    = compilationUnit.EndOfFileToken;
                        SyntaxTriviaList leading = endOfFile.LeadingTrivia;
                        SyntaxToken oldToken;
                        SyntaxToken newToken;

                        if (!preferNewLineAtEndOfFile)
                        {
                            if (leading.Any())
                            {
                                SyntaxTrivia last = leading.Last();

                                if (last.GetStructure() is DirectiveTriviaSyntax directive)
                                {
                                    SyntaxTriviaList trailing = directive.GetTrailingTrivia();

                                    DirectiveTriviaSyntax newDirective = directive.WithTrailingTrivia(trailing.RemoveAt(trailing.Count - 1));

                                    return(document.ReplaceNodeAsync(directive, newDirective, ct));
                                }
                                else
                                {
                                    oldToken  = endOfFile;
                                    int index = leading.Count - 1;

                                    for (int i = leading.Count - 2; i >= 0; i--)
                                    {
                                        if (leading[i].IsWhitespaceOrEndOfLineTrivia())
                                        {
                                            index--;
                                        }
                                    }

                                    newToken = oldToken.WithLeadingTrivia(leading.RemoveRange(index, leading.Count - index));
                                }
                            }
                            else
                            {
                                oldToken = endOfFile.GetPreviousToken();
                                SyntaxTriviaList trailing = oldToken.TrailingTrivia;
                                newToken = oldToken.WithTrailingTrivia(trailing.RemoveAt(trailing.Count - 1));
                            }
                        }
                        else if (leading.Any())
                        {
                            oldToken = endOfFile;

                            if (leading.Span.Start == 0 &&
                                leading.All(f => f.IsWhitespaceOrEndOfLineTrivia()))
                            {
                                newToken = oldToken.WithoutLeadingTrivia();
                            }
                            else
                            {
                                newToken = oldToken.AppendEndOfLineToLeadingTrivia();
                            }
                        }
                        else
                        {
                            oldToken = endOfFile.GetPreviousToken();
                            newToken = oldToken.AppendEndOfLineToTrailingTrivia();
                        }

                        return(document.ReplaceTokenAsync(oldToken, newToken, ct));
                    },
                    GetEquivalenceKey(diagnostic));

                context.RegisterCodeFix(codeAction, diagnostic);
                break;
            }
            }
        }
        private static void AnalyzeEnumDeclaration(SyntaxNodeAnalysisContext context)
        {
            var enumDeclaration = (EnumDeclarationSyntax)context.Node;

            SeparatedSyntaxList <EnumMemberDeclarationSyntax> members = enumDeclaration.Members;

            int count = members.Count;

            if (count <= 1)
            {
                return;
            }

            SyntaxTree                  tree = enumDeclaration.SyntaxTree;
            CancellationToken           cancellationToken = context.CancellationToken;
            EnumMemberDeclarationSyntax member;
            bool?isSingleLine;
            bool?isPreviousSingleLine = null;

            for (int i = 1; i < count; i++, isPreviousSingleLine = isSingleLine)
            {
                member       = members[i];
                isSingleLine = null;
                SyntaxToken      commaToken     = members.GetSeparator(i - 1);
                SyntaxTriviaList trailingTrivia = commaToken.TrailingTrivia;

                if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia))
                {
                    continue;
                }

                SyntaxTriviaList leadingTrivia = member.GetLeadingTrivia();

                (bool emptyOrWhitespaceTrivia, bool documentationComment, bool emptyLine) = AnalyzeLeadingTrivia(leadingTrivia);

                if (documentationComment)
                {
                    ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenDeclarationAndDocumentationComment, trailingTrivia.Last());
                    continue;
                }

                if (!emptyOrWhitespaceTrivia &&
                    !emptyLine)
                {
                    continue;
                }

                if ((isSingleLine ?? (isSingleLine = tree.IsSingleLineSpan(member.Span, cancellationToken)).Value) &&
                    (isPreviousSingleLine ?? tree.IsSingleLineSpan(members[i - 1].Span, cancellationToken)))
                {
                    if (emptyLine)
                    {
                        ReportDiagnostic(context, DiagnosticDescriptors.RemoveEmptyLineBetweenSingleLineDeclarationsOfSameKind, leadingTrivia[0]);
                    }
                    else if (emptyOrWhitespaceTrivia)
                    {
                        ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenSingleLineDeclarations, trailingTrivia.Last());
                    }
                }
                else if (emptyOrWhitespaceTrivia)
                {
                    ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenDeclarations, trailingTrivia.Last());
                }
            }
        }
        private static void Analyze(SyntaxNodeAnalysisContext context, SyntaxList <MemberDeclarationSyntax> members)
        {
            int count = members.Count;

            if (count <= 1)
            {
                return;
            }

            SyntaxTree              tree = context.Node.SyntaxTree;
            CancellationToken       cancellationToken = context.CancellationToken;
            MemberDeclarationSyntax member;
            MemberDeclarationSyntax previousMember = members[0];
            bool?isSingleLine;
            bool?isPreviousSingleLine = null;

            for (int i = 1; i < count; i++, previousMember = member, isPreviousSingleLine = isSingleLine)
            {
                member       = members[i];
                isSingleLine = null;
                SyntaxTriviaList trailingTrivia = previousMember.GetTrailingTrivia();

                if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia))
                {
                    continue;
                }

                SyntaxTriviaList leadingTrivia = member.GetLeadingTrivia();

                (bool emptyOrWhitespaceTrivia, bool documentationComment, bool emptyLine) = AnalyzeLeadingTrivia(leadingTrivia);

                if (documentationComment)
                {
                    ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenDeclarationAndDocumentationComment, trailingTrivia.Last());
                    continue;
                }

                if (!emptyOrWhitespaceTrivia &&
                    !emptyLine)
                {
                    continue;
                }

                if ((isSingleLine ?? (isSingleLine = tree.IsSingleLineSpan(member.Span, cancellationToken)).Value) &&
                    (isPreviousSingleLine ?? tree.IsSingleLineSpan(members[i - 1].Span, cancellationToken)))
                {
                    if (emptyLine)
                    {
                        if (MemberKindEquals(previousMember, member))
                        {
                            ReportDiagnostic(context, DiagnosticDescriptors.RemoveEmptyLineBetweenSingleLineDeclarationsOfSameKind, leadingTrivia[0]);
                        }
                    }
                    else if (emptyOrWhitespaceTrivia)
                    {
                        ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenSingleLineDeclarations, trailingTrivia.Last());

                        if (!MemberKindEquals(previousMember, member))
                        {
                            ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenSingleLineDeclarationsOfDifferentKind, trailingTrivia.Last());
                        }
                    }
                }
                else if (emptyOrWhitespaceTrivia)
                {
                    ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenDeclarations, trailingTrivia.Last());
                }
            }
        }
 public static SyntaxTrivia LastOrDefault(this SyntaxTriviaList triviaList)
 => triviaList.Any() ? triviaList.Last() : default;
Пример #26
0
        private static void AnalyzeUsings(SyntaxNodeAnalysisContext context, SyntaxList <UsingDirectiveSyntax> usings)
        {
            int count = usings.Count;

            if (count <= 1)
            {
                return;
            }

            UsingDirectiveSyntax usingDirective1 = usings[0];

            for (int i = 1; i < count; i++, usingDirective1 = usings[i - 1])
            {
                if (usingDirective1.StaticKeyword.IsKind(SyntaxKind.StaticKeyword))
                {
                    return;
                }

                if (usingDirective1.Alias != null)
                {
                    return;
                }

                UsingDirectiveSyntax usingDirective2 = usings[i];

                if (usingDirective2.StaticKeyword.IsKind(SyntaxKind.StaticKeyword))
                {
                    return;
                }

                if (usingDirective2.Alias != null)
                {
                    return;
                }

                SyntaxTriviaList trailingTrivia = usingDirective1.GetTrailingTrivia();

                if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia))
                {
                    continue;
                }

                IdentifierNameSyntax rootNamespace1 = usingDirective1.GetRootNamespace();

                if (rootNamespace1 == null)
                {
                    continue;
                }

                IdentifierNameSyntax rootNamespace2 = usingDirective2.GetRootNamespace();

                if (rootNamespace2 == null)
                {
                    continue;
                }

                SyntaxTriviaList leadingTrivia = usingDirective2.GetLeadingTrivia();

                bool isEmptyLine = SyntaxTriviaAnalysis.StartsWithOptionalWhitespaceThenEndOfLineTrivia(leadingTrivia);

                if (string.Equals(rootNamespace1.Identifier.ValueText, rootNamespace2.Identifier.ValueText, StringComparison.Ordinal))
                {
                    if (isEmptyLine)
                    {
                        if (DiagnosticRules.RemoveBlankLineBetweenUsingDirectivesWithSameRootNamespace.IsEffective(context))
                        {
                            DiagnosticHelpers.ReportDiagnostic(
                                context,
                                DiagnosticRules.RemoveBlankLineBetweenUsingDirectivesWithSameRootNamespace,
                                Location.Create(context.Node.SyntaxTree, leadingTrivia[0].Span.WithLength(0)));
                        }

                        if (DiagnosticRules.BlankLineBetweenUsingDirectives.IsEffective(context) &&
                            context.GetBlankLineBetweenUsingDirectives() == UsingDirectiveBlankLineStyle.Never)
                        {
                            DiagnosticHelpers.ReportDiagnostic(
                                context,
                                DiagnosticRules.BlankLineBetweenUsingDirectives,
                                Location.Create(context.Node.SyntaxTree, leadingTrivia[0].Span.WithLength(0)),
                                properties: DiagnosticProperties.AnalyzerOption_Invert,
                                "Remove");
                        }
                    }
                }
                else if (DiagnosticRules.BlankLineBetweenUsingDirectives.IsEffective(context))
                {
                    UsingDirectiveBlankLineStyle style = context.GetBlankLineBetweenUsingDirectives();

                    if (isEmptyLine)
                    {
                        if (style == UsingDirectiveBlankLineStyle.Never)
                        {
                            DiagnosticHelpers.ReportDiagnostic(
                                context,
                                DiagnosticRules.BlankLineBetweenUsingDirectives,
                                Location.Create(context.Node.SyntaxTree, leadingTrivia[0].Span.WithLength(0)),
                                properties: DiagnosticProperties.AnalyzerOption_Invert,
                                "Remove");
                        }
                    }
                    else if (style == UsingDirectiveBlankLineStyle.SeparateGroups)
                    {
                        DiagnosticHelpers.ReportDiagnostic(
                            context,
                            DiagnosticRules.BlankLineBetweenUsingDirectives,
                            Location.Create(context.Node.SyntaxTree, trailingTrivia.Last().Span.WithLength(0)),
                            "Add");
                    }
                }
            }
        }
        /// <summary>
        /// Remove all extra new lines from the begining of a close brace token.  This is only called in
        /// the case at least one new line is present hence we don't have to worry about the single line
        /// case.
        /// </summary>
        private static SyntaxTriviaList RemoveNewLinesFromBottom(SyntaxTriviaList triviaList)
        {
            var index = triviaList.Count - 1;
            var searching = true;
            while (index >= 0 && searching)
            {
                var current = triviaList[index];
                switch (current.Kind())
                {
                    case SyntaxKind.WhitespaceTrivia:
                    case SyntaxKind.EndOfLineTrivia:
                        index--;
                        break;
                    default:
                        searching = false;
                        break;
                }
            }

            // Nothing to adjust, the removal of new lines from the top of the list will handle all of the
            // important cases.
            if (index < 0)
            {
                return triviaList;
            }

            var list = new List<SyntaxTrivia>(triviaList.Count);
            for (int i = 0; i <= index; i++)
            {
                list.Add(triviaList[i]);
            }

            // A directive has an implicit new line after it.
            if (!list[index].IsDirective)
            {
                list.Add(SyntaxUtil.GetBestNewLineTrivia(triviaList));
            }

            if (triviaList.Last().IsKind(SyntaxKind.WhitespaceTrivia))
            {
                list.Add(triviaList.Last());
            }

            return SyntaxFactory.TriviaList(list);
        }
Пример #28
0
        private static List <BaseFieldDeclarationSyntax> DeclarationSplitter(
            Document document,
            VariableDeclarationSyntax declaration,
            Func <VariableDeclarationSyntax, BaseFieldDeclarationSyntax> declarationFactory,
            SyntaxTriviaList declarationTrailingTrivia)
        {
            SeparatedSyntaxList <VariableDeclaratorSyntax> variables = declaration.Variables;
            VariableDeclaratorSyntax   first    = variables.First();
            BaseFieldDeclarationSyntax previous = null;
            var newFieldDeclarations            = new List <BaseFieldDeclarationSyntax>(variables.Count);

            foreach (SyntaxNodeOrToken nodeOrToken in variables.GetWithSeparators())
            {
                if (previous == null)
                {
                    VariableDeclaratorSyntax variable = (VariableDeclaratorSyntax)nodeOrToken.AsNode();
                    variable = variable.WithIdentifier(variable.Identifier.WithoutLeadingWhitespace());
                    var variableDeclarator = SyntaxFactory.SingletonSeparatedList(variable);
                    previous = declarationFactory(declaration.WithVariables(variableDeclarator));

                    if (variable != first)
                    {
                        var triviaList = previous.GetLeadingTrivia().WithoutDirectiveTrivia();

                        // Remove all leading blank lines
                        var nonBlankLinetriviaIndex = TriviaHelper.IndexOfFirstNonBlankLineTrivia(triviaList);
                        if (nonBlankLinetriviaIndex > 0)
                        {
                            triviaList = triviaList.RemoveRange(0, nonBlankLinetriviaIndex);
                        }

                        // Add a blank line if the first line contains a comment.
                        var nonWhitespaceTriviaIndex = TriviaHelper.IndexOfFirstNonWhitespaceTrivia(triviaList, false);
                        if (nonWhitespaceTriviaIndex >= 0)
                        {
                            switch (triviaList[nonWhitespaceTriviaIndex].Kind())
                            {
                            case SyntaxKind.SingleLineCommentTrivia:
                            case SyntaxKind.MultiLineCommentTrivia:
                                triviaList = triviaList.Insert(0, SyntaxFactory.CarriageReturnLineFeed);
                                break;
                            }
                        }

                        previous = previous.WithLeadingTrivia(triviaList);
                    }
                }
                else
                {
                    SyntaxToken      commaToken     = nodeOrToken.AsToken();
                    SyntaxTriviaList trailingTrivia = commaToken.TrailingTrivia;
                    if (trailingTrivia.Any())
                    {
                        if (!trailingTrivia.Last().IsKind(SyntaxKind.EndOfLineTrivia))
                        {
                            trailingTrivia = trailingTrivia.WithoutTrailingWhitespace().Add(FormattingHelper.GetNewLineTrivia(document));
                        }
                    }
                    else
                    {
                        trailingTrivia = SyntaxTriviaList.Create(FormattingHelper.GetNewLineTrivia(document));
                    }

                    newFieldDeclarations.Add(previous.WithTrailingTrivia(trailingTrivia));
                    previous = null;
                }
            }

            newFieldDeclarations.Add(previous.WithTrailingTrivia(declarationTrailingTrivia));
            return(newFieldDeclarations);
        }
        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);
            }
        }
        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());
            }
        private static void UpdateReplaceMap(Dictionary <SyntaxToken, SyntaxToken> replaceMap, SyntaxToken token, Diagnostic diagnostic)
        {
            string location;

            if (!diagnostic.Properties.TryGetValue(TokenSpacingProperties.LocationKey, out location))
            {
                return;
            }

            string action;

            if (!diagnostic.Properties.TryGetValue(TokenSpacingProperties.ActionKey, out action))
            {
                return;
            }

            string layout;

            if (!diagnostic.Properties.TryGetValue(TokenSpacingProperties.LayoutKey, out layout))
            {
                layout = TokenSpacingProperties.LayoutPack;
            }

            SyntaxTriviaList triviaList;

            switch (location)
            {
            case TokenSpacingProperties.LocationPreceding:
                var prevToken = token.GetPreviousToken();
                switch (action)
                {
                case TokenSpacingProperties.ActionInsert:
                    if (!replaceMap.ContainsKey(prevToken))
                    {
                        replaceMap[token] = token.WithLeadingTrivia(token.LeadingTrivia.Add(SyntaxFactory.Space));
                    }

                    break;

                case TokenSpacingProperties.ActionRemove:
                    bool tokenIsFirstInLine = token.IsFirstInLine();
                    bool preserveLayout     = layout == TokenSpacingProperties.LayoutPreserve;
                    triviaList = prevToken.TrailingTrivia.AddRange(token.LeadingTrivia);
                    if (triviaList.Any(t => t.IsDirective))
                    {
                        break;
                    }

                    replaceMap[prevToken] = prevToken.WithTrailingTrivia();
                    if ((!preserveLayout || !tokenIsFirstInLine) &&
                        triviaList.All(i => i.IsKind(SyntaxKind.WhitespaceTrivia) || i.IsKind(SyntaxKind.EndOfLineTrivia)))
                    {
                        replaceMap[token] = token.WithLeadingTrivia();
                    }
                    else if (tokenIsFirstInLine && token.IsLastInLine())
                    {
                        /* This block covers the case where `token` is the only non-trivia token on its line. However,
                         * the line may still contain non-whitespace trivia which we want the removal process to
                         * preserve. This code fix only removes the whitespace surrounding `token` if it is the only
                         * non-whitespace token on the line.
                         */
                        int  lastNewLineLeading    = token.LeadingTrivia.LastIndexOf(SyntaxKind.EndOfLineTrivia);
                        int  firstNewLineFollowing = token.TrailingTrivia.IndexOf(SyntaxKind.EndOfLineTrivia);
                        bool onlyWhitespace        = true;
                        for (int i = lastNewLineLeading + 1; i < token.LeadingTrivia.Count; i++)
                        {
                            onlyWhitespace &= token.LeadingTrivia[i].IsKind(SyntaxKind.WhitespaceTrivia);
                        }

                        firstNewLineFollowing = firstNewLineFollowing == -1 ? token.TrailingTrivia.Count : firstNewLineFollowing;
                        for (int i = 0; i < firstNewLineFollowing; i++)
                        {
                            onlyWhitespace &= token.TrailingTrivia[i].IsKind(SyntaxKind.WhitespaceTrivia);
                        }

                        if (onlyWhitespace)
                        {
                            // Move the token, and remove the other tokens from its line. Keep all other surrounding
                            // trivia. Keep the last newline that precedes token, but not the first that follows it.
                            SyntaxTriviaList trailingTrivia = prevToken.TrailingTrivia;
                            if (lastNewLineLeading >= 0)
                            {
                                trailingTrivia = trailingTrivia.AddRange(token.LeadingTrivia.Take(lastNewLineLeading + 1));
                            }

                            // firstNewLineFollowing was adjusted above to account for the missing case.
                            trailingTrivia = trailingTrivia.AddRange(token.TrailingTrivia.Take(firstNewLineFollowing));

                            replaceMap[token] = token.WithLeadingTrivia().WithTrailingTrivia(trailingTrivia);
                        }
                        else
                        {
                            // Just move the token and keep all surrounding trivia.
                            SyntaxTriviaList trailingTrivia = triviaList.AddRange(token.TrailingTrivia);
                            replaceMap[token] = token.WithLeadingTrivia().WithTrailingTrivia(trailingTrivia);
                        }
                    }
                    else
                    {
                        SyntaxTriviaList trailingTrivia = triviaList.AddRange(token.TrailingTrivia.WithoutLeadingWhitespace(endOfLineIsWhitespace: false));
                        replaceMap[token] = token.WithLeadingTrivia().WithTrailingTrivia(trailingTrivia);
                    }

                    break;

                case TokenSpacingProperties.ActionRemoveImmediate:
                    SyntaxTriviaList tokenLeadingTrivia = token.LeadingTrivia;
                    while (tokenLeadingTrivia.Any() && tokenLeadingTrivia.Last().IsKind(SyntaxKind.WhitespaceTrivia))
                    {
                        tokenLeadingTrivia = tokenLeadingTrivia.RemoveAt(tokenLeadingTrivia.Count - 1);
                    }

                    replaceMap[token] = token.WithLeadingTrivia(tokenLeadingTrivia);

                    if (!tokenLeadingTrivia.Any())
                    {
                        SyntaxTriviaList previousTrailingTrivia = prevToken.TrailingTrivia;
                        while (previousTrailingTrivia.Any() && previousTrailingTrivia.Last().IsKind(SyntaxKind.WhitespaceTrivia))
                        {
                            previousTrailingTrivia = previousTrailingTrivia.RemoveAt(previousTrailingTrivia.Count - 1);
                        }

                        replaceMap[prevToken] = prevToken.WithTrailingTrivia(previousTrailingTrivia);
                    }

                    break;
                }

                break;

            case TokenSpacingProperties.LocationFollowing:
                var nextToken = token.GetNextToken();
                switch (action)
                {
                case TokenSpacingProperties.ActionInsert:
                    if (!replaceMap.ContainsKey(nextToken))
                    {
                        replaceMap[token] = token.WithTrailingTrivia(token.TrailingTrivia.Insert(0, SyntaxFactory.Space));
                    }

                    break;

                case TokenSpacingProperties.ActionRemove:
                    triviaList = token.TrailingTrivia.AddRange(nextToken.LeadingTrivia);

                    replaceMap[token]     = token.WithTrailingTrivia();
                    replaceMap[nextToken] = nextToken.WithLeadingTrivia(triviaList.WithoutLeadingWhitespace(true));
                    break;
                }

                break;
            }
        }