private bool ContainsNoisyTrivia(SyntaxTriviaList list)
 {
     return(list.Any(t => !_nonNoisySet.Contains(t.RawKind)));
 }
示例#2
0
 private static bool ContainsComment(SyntaxTriviaList trivias)
 {
     return(trivias.Any(trivia => trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) || trivia.IsKind(SyntaxKind.MultiLineCommentTrivia)));
 }
示例#3
0
 private bool HasDocumentationComment(SyntaxTriviaList existingTrivia)
 {
     return existingTrivia.Any(SyntaxKind.DocumentationCommentTrivia) ||
            existingTrivia.Any(x => x.ToFullString().IndexOf("<summary>") != -1);
 }
        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--)
                {
                    context.CancellationToken.ThrowIfCancellationRequested();

                    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,
                    DiagnosticRules.FixFormattingOfList,
                    Location.Create(first.SyntaxTree, nodes.Span),
                    GetTitle());
            }
示例#5
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 bool ShouldPreserveTrivia(SyntaxTriviaList trivia)
 {
     return(trivia.Any(t => !t.IsWhitespaceOrEndOfLine()));
 }
示例#7
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;
            }
            }
        }
示例#8
0
        private static Task <Document> FixAsync(
            Document document,
            BinaryExpressionSyntax binaryExpression,
            CancellationToken cancellationToken)
        {
            IndentationAnalysis indentationAnalysis = AnalyzeIndentation(binaryExpression, cancellationToken);

            string indentation;

            if (indentationAnalysis.Indentation == binaryExpression.GetLeadingTrivia().LastOrDefault() &&
                document.IsAnalyzerOptionEnabled(AnalyzerOptions.AddNewLineAfterBinaryOperatorInsteadOfBeforeIt))
            {
                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)
            {
                ExpressionSyntax left  = binaryExpression.Left;
                SyntaxToken      token = binaryExpression.OperatorToken;
                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 (document.IsAnalyzerOptionEnabled(AnalyzerOptions.AddNewLineAfterBinaryOperatorInsteadOfBeforeIt))
                    {
                        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);
                    }
                }
            }
        }
 private static bool ShouldPreserve(SyntaxTriviaList trivia)
 {
     return(trivia.Any(t => t.IsRegularComment() || t.IsDirective));
 }
示例#10
0
        public static async Task ComputeRefactoringAsync(RefactoringContext context, LocalDeclarationStatementSyntax localDeclaration)
        {
            VariableDeclarationSyntax declaration = localDeclaration.Declaration;

            TypeSyntax type = declaration?.Type;

            if (type?.IsVar != false)
            {
                return;
            }

            VariableDeclaratorSyntax declarator = declaration.Variables.FirstOrDefault();

            if (declarator == null)
            {
                return;
            }

            if (context.Span.Start < type.SpanStart)
            {
                return;
            }

            SyntaxTriviaList triviaList = type.GetTrailingTrivia();

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

            SyntaxTrivia trivia = triviaList
                                  .SkipWhile(f => f.IsWhitespaceTrivia())
                                  .FirstOrDefault();

            if (!trivia.IsEndOfLineTrivia())
            {
                return;
            }

            if (context.Span.End > trivia.SpanStart)
            {
                return;
            }

            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

            ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, context.CancellationToken);

            string name = NameGenerator.Default.CreateUniqueLocalName(
                typeSymbol,
                semanticModel,
                declarator.SpanStart,
                cancellationToken: context.CancellationToken);

            if (name == null)
            {
                return;
            }

            context.RegisterRefactoring(
                $"Add identifier '{name}'",
                c => RefactorAsync(context.Document, type, name, c),
                RefactoringIdentifiers.AddIdentifierToVariableDeclaration);
        }
示例#11
0
        public TNode InsertModifier(TNode node, SyntaxToken modifier, IModifierComparer comparer = null)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            SyntaxTokenList modifiers = GetModifiers(node);

            int insertIndex = (comparer ?? ModifierComparer.Instance).GetInsertIndex(modifiers, modifier);

            var token = default(SyntaxToken);

            if (!modifiers.Any() ||
                insertIndex == modifiers.Count)
            {
                SyntaxNodeOrToken nodeOrToken = FindNodeOrTokenAfterModifiers(node);

                if (nodeOrToken.IsToken)
                {
                    token = nodeOrToken.AsToken();
                }
                else if (nodeOrToken.IsNode)
                {
                    token = nodeOrToken.AsNode().GetFirstToken();
                }
            }
            else
            {
                token = modifiers[insertIndex];
            }

            if (token != default(SyntaxToken))
            {
                SyntaxTriviaList newLeadingTrivia = token.LeadingTrivia;

                if (newLeadingTrivia.Any())
                {
                    SyntaxTriviaList leadingTrivia = modifier.LeadingTrivia;

                    if (!leadingTrivia.IsSingleElasticMarker())
                    {
                        newLeadingTrivia = newLeadingTrivia.AddRange(leadingTrivia);
                    }

                    modifier = modifier.WithLeadingTrivia(newLeadingTrivia);

                    SyntaxToken newToken = token.WithoutLeadingTrivia();

                    if (!modifiers.Any() ||
                        insertIndex == modifiers.Count)
                    {
                        node = node.ReplaceToken(token, newToken);
                    }
                    else
                    {
                        modifiers = modifiers.ReplaceAt(insertIndex, newToken);
                    }
                }

                if (modifier.TrailingTrivia.IsSingleElasticMarker())
                {
                    modifier = modifier.WithTrailingTrivia(TriviaList(Space));
                }
            }

            modifiers = modifiers.Insert(insertIndex, modifier);

            return(WithModifiers(node, modifiers));
        }
示例#12
0
 public static string GetNewLineIfExist(SyntaxTriviaList triviaList)
 {
     return(triviaList.Any(f => f.IsKind(SyntaxKind.EndOfLineTrivia)) ? Environment.NewLine : "");
 }
示例#13
0
        private SyntaxFactoryWriter WriteArgument(string parameter, SyntaxTriviaList triviaList, bool closeArgumentList = false)
        {
            _ = this.writer
                .WriteArgumentStart(parameter);
            switch (triviaList.Count)
            {
            case 0:
                this.Append("default").WriteArgumentEnd(closeArgumentList);
                return(this);

            case 1 when TryGetSingleLine(out var text):
                return(this.Append(text !)
                       .WriteArgumentEnd(closeArgumentList));

            default:
                this.AppendLine("SyntaxFactory.TriviaList(")
                .PushIndent();
                for (var i = 0; i < triviaList.Count; i++)
                {
                    _ = this.Write(triviaList[i]);
                    if (i < triviaList.Count - 1)
                    {
                        this.AppendLine(",");
                    }
                }

                this.writer.Append(")");
                return(this.WriteArgumentEnd(closeArgumentList)
                       .PopIndent());
            }

            bool TryGetSingleLine(out string?result)
            {
                if (!triviaList.Any())
                {
                    result = "default";
                    return(true);
                }

                if (triviaList.TrySingle(out var trivia))
                {
                    switch (trivia.Kind())
                    {
                    case SyntaxKind.None:
                        result = "default";
                        return(true);

                    case SyntaxKind.WhitespaceTrivia:
                        result = trivia.Span.Length == 1
                                ? "SyntaxFactory.TriviaList(SyntaxFactory.Space)"
                                : $"SyntaxFactory.TriviaList(SyntaxFactory.Whitespace(\"{trivia.ToString()}\"))";
                        return(true);

                    case SyntaxKind.EndOfLineTrivia:
                        result = "SyntaxFactory.TriviaList(SyntaxFactory.LineFeed)";
                        return(true);
                    }
                }

                result = null;
                return(false);
            }
        }
示例#14
0
 public bool Any(SyntaxKind kind)
 {
     return(part1.Any(kind) || part2.Any(kind));
 }
示例#15
0
        private static void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            SyntaxTree tree = context.Tree;

            if (!tree.TryGetText(out SourceText sourceText))
            {
                return;
            }

            int maxLength = AnalyzerSettings.Current.MaxLineLength;

            if (context.Options.AnalyzerConfigOptionsProvider.GetOptions(tree).TryGetValue("roslynator.max_line_length", out string maxLengthText) &&
                int.TryParse(maxLengthText, NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite, CultureInfo.CurrentCulture, out int maxLength2))
            {
                maxLength = maxLength2;
            }

            if (maxLength <= 0)
            {
                return;
            }

            SyntaxNode root = tree.GetRoot(context.CancellationToken);

            int i = 0;

            SyntaxTrivia trivia = root.FindTrivia(0);

            if (trivia.SpanStart == 0 &&
                trivia.IsKind(SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia))
            {
                SyntaxTriviaList leadingTrivia = trivia.Token.LeadingTrivia;

                int count = leadingTrivia.Count;

                if (count > 1)
                {
                    int j = 0;

                    while (j < leadingTrivia.Count - 1 &&
                           leadingTrivia[j].IsKind(SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia) &&
                           leadingTrivia[j + 1].IsKind(SyntaxKind.EndOfLineTrivia))
                    {
                        i++;

                        j += 2;
                    }
                }
            }

            TextLineCollection lines = sourceText.Lines;

            for (; i < lines.Count; i++)
            {
                TextLine line = lines[i];

                if (line.Span.Length <= maxLength)
                {
                    continue;
                }

                int end = line.End;

                SyntaxToken token = root.FindToken(end);

                if (token.IsKind(SyntaxKind.StringLiteralToken))
                {
                    TextSpan span = token.Span;

                    if (span.End == end)
                    {
                        if (span.Length >= maxLength)
                        {
                            continue;
                        }
                    }
                    else if (span.Contains(end) &&
                             end - span.Start >= maxLength)
                    {
                        continue;
                    }
                }

                SyntaxTriviaList list = default;

                if (token.LeadingTrivia.Span.Contains(end))
                {
                    list = token.LeadingTrivia;
                }
                else if (token.TrailingTrivia.Span.Contains(end))
                {
                    list = token.TrailingTrivia;
                }

                if (list.Any())
                {
                    int index = -1;

                    for (int j = 0; j < list.Count; j++)
                    {
                        if (list[j].Span.Contains(end))
                        {
                            trivia = list[j];
                            index  = j;
                        }
                    }

                    if (index >= 0)
                    {
                        SyntaxKind kind = trivia.Kind();

                        if (kind == SyntaxKind.MultiLineCommentTrivia ||
                            kind == SyntaxKind.SingleLineDocumentationCommentTrivia ||
                            kind == SyntaxKind.MultiLineDocumentationCommentTrivia)
                        {
                            continue;
                        }

                        if (kind == SyntaxKind.EndOfLineTrivia &&
                            index > 0 &&
                            list[index - 1].IsKind(SyntaxKind.SingleLineCommentTrivia))
                        {
                            continue;
                        }
                    }
                }

                ImmutableDictionary <string, string> properties = _properties;

                if (properties == null ||
                    int.Parse(properties[PropertyKey]) != maxLength)
                {
                    properties = ImmutableDictionary.CreateRange(
                        new[]
                    {
                        new KeyValuePair <string, string>(PropertyKey, maxLength.ToString())
                    });

                    _properties = properties;
                }

                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticDescriptors.LineIsTooLong,
                    Location.Create(tree, line.Span),
                    properties,
                    line.Span.Length);
            }
        }
示例#16
0
        private TNode InsertModifier(TNode node, SyntaxTokenList modifiers, SyntaxToken modifier, int index)
        {
            SyntaxToken token;

            if (!modifiers.Any() ||
                index == modifiers.Count)
            {
                if (modifiers.Any())
                {
                    token = modifiers.Last().GetNextToken();
                }
                else
                {
                    AttributeListSyntax attributeList = GetAttributeLists(node).LastOrDefault();

                    if (attributeList != null)
                    {
                        token = attributeList.GetLastToken().GetNextToken();
                    }
                    else
                    {
                        token = node.GetFirstToken();
                    }
                }
            }
            else
            {
                token = modifiers[index];
            }

            if (token != default(SyntaxToken))
            {
                SyntaxTriviaList newLeadingTrivia = token.LeadingTrivia;

                if (newLeadingTrivia.Any())
                {
                    SyntaxTriviaList leadingTrivia = modifier.LeadingTrivia;

                    if (!leadingTrivia.IsSingleElasticMarker())
                    {
                        newLeadingTrivia = newLeadingTrivia.AddRange(leadingTrivia);
                    }

                    modifier = modifier.WithLeadingTrivia(newLeadingTrivia);

                    SyntaxToken newToken = token.WithoutLeadingTrivia();

                    if (!modifiers.Any() ||
                        index == modifiers.Count)
                    {
                        node = node.ReplaceToken(token, newToken);
                    }
                    else
                    {
                        modifiers = modifiers.ReplaceAt(index, newToken);
                    }
                }

                if (modifier.TrailingTrivia.IsSingleElasticMarker())
                {
                    modifier = modifier.WithTrailingTrivia(TriviaList(Space));
                }
            }

            modifiers = modifiers.Insert(index, modifier);

            return(WithModifiers(node, modifiers));
        }
        public static void AnalyzeInitializer(SyntaxNodeAnalysisContext context)
        {
            var initializer = (InitializerExpressionSyntax)context.Node;

            SeparatedSyntaxList <ExpressionSyntax> expressions = initializer.Expressions;

            ExpressionSyntax first = expressions.FirstOrDefault();

            if (first == null)
            {
                return;
            }

            if (IsExpectedTrailingTrivia(initializer.OpenBraceToken.TrailingTrivia))
            {
                SyntaxTriviaList leading = first.GetLeadingTrivia();

                if (leading.Any())
                {
                    TextSpan?span = GetEmptyLineSpan(leading, isEnd: false);

                    if (span != null)
                    {
                        ReportDiagnostic(context, span.Value);
                    }
                }
            }

            if (IsExpectedTrailingTrivia(expressions.GetTrailingTrivia()))
            {
                SyntaxTriviaList leading = initializer.CloseBraceToken.LeadingTrivia;

                if (leading.Any())
                {
                    TextSpan?span = GetEmptyLineSpan(leading, isEnd: true);

                    if (span != null)
                    {
                        ReportDiagnostic(context, span.Value);
                    }
                }
            }

            bool IsExpectedTrailingTrivia(SyntaxTriviaList triviaList)
            {
                foreach (SyntaxTrivia trivia in triviaList)
                {
                    switch (trivia.Kind())
                    {
                    case SyntaxKind.WhitespaceTrivia:
                        break;

                    case SyntaxKind.EndOfLineTrivia:
                        return(true);

                    default:
                        return(false);
                    }
                }

                return(false);
            }
        }
        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;
            }
        }
 public static SyntaxTrivia LastOrDefault(this SyntaxTriviaList triviaList)
 => triviaList.Any() ? triviaList.Last() : default;
示例#20
0
            PropertyDeclarationSyntax ConvertProperty(PropertyDeclarationSyntax propertyDeclaration, FieldDeclarationSyntax relatedField)
            {
                var leadingList = new SyntaxTriviaList();

                if (relatedField.Declaration.Variables.Count == 1)
                {
                    leadingList = leadingList.AddRange(relatedField.GetLeadingTrivia());
                }

                var propertyDeclaration_GetLeadingTrivia = propertyDeclaration.GetLeadingTrivia();

                if (leadingList.Any() && propertyDeclaration_GetLeadingTrivia.First().IsKind(SyntaxKind.EndOfLineTrivia) == false)
                {
                    var endOfLine = relatedField.GetLeadingTrivia().FirstOrDefault(x => x.IsKind(SyntaxKind.EndOfLineTrivia));

                    if (endOfLine != null)
                    {
                        leadingList = leadingList.Add(endOfLine);
                    }
                }

                leadingList = leadingList.AddRange(propertyDeclaration.GetLeadingTrivia());

                var getNode = propertyDeclaration.AccessorList.Accessors.FirstOrDefault(x => x.Keyword.IsKind(SyntaxKind.GetKeyword));
                var setNode = propertyDeclaration.AccessorList.Accessors.FirstOrDefault(x => x.Keyword.IsKind(SyntaxKind.SetKeyword));

                propertyDeclaration =
                    propertyDeclaration
                    .WithAccessorList
                    (
                        propertyDeclaration.AccessorList.WithAccessors(

                            new SyntaxList <AccessorDeclarationSyntax>()
                            .Add(
                                getNode
                                .WithBody(null)
                                .WithTrailingTrivia()
                                .WithSemicolonToken(
                                    SyntaxFactory.ParseToken(";")
                                    .WithTrailingTrivia(SyntaxFactory.Space)
                                    )
                                .WithLeadingTrivia(SyntaxFactory.Space)

                                )
                            .Add(
                                setNode
                                .WithBody(null)
                                .WithTrailingTrivia()
                                .WithSemicolonToken(
                                    SyntaxFactory.ParseToken(";")
                                    .WithTrailingTrivia(SyntaxFactory.Space)

                                    )
                                .WithLeadingTrivia(SyntaxFactory.Space)
                                )
                            )
                        .WithOpenBraceToken(propertyDeclaration.AccessorList.OpenBraceToken.WithLeadingTrivia().WithTrailingTrivia())
                        .WithCloseBraceToken(propertyDeclaration.AccessorList.CloseBraceToken.WithLeadingTrivia())
                    )
                    .WithIdentifier(propertyDeclaration.Identifier.WithTrailingTrivia(SyntaxFactory.Space))
                    .WithLeadingTrivia(leadingList);

                return(propertyDeclaration);
            }
        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"));
            }
        }
 private static bool ShouldPreserveTrivia(SyntaxTriviaList trivia)
 => trivia.Any(t => !t.IsWhitespaceOrEndOfLine());
        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);
            }
        }
示例#24
0
        private static void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            SyntaxTree tree = context.Tree;

            if (!tree.TryGetText(out SourceText sourceText))
            {
                return;
            }

            int maxLength = CSharp.AnalyzerOptions.MaxLineLength.GetInt32Value(context.Tree, context.Options, AnalyzerSettings.Current.MaxLineLength);

            if (maxLength <= 0)
            {
                return;
            }

            SyntaxNode root = tree.GetRoot(context.CancellationToken);

            int i = 0;

            SyntaxTrivia trivia = root.FindTrivia(0);

            if (trivia.SpanStart == 0 &&
                trivia.IsKind(SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia))
            {
                SyntaxTriviaList leadingTrivia = trivia.Token.LeadingTrivia;

                int count = leadingTrivia.Count;

                if (count > 1)
                {
                    int j = 0;

                    while (j < leadingTrivia.Count - 1 &&
                           leadingTrivia[j].IsKind(SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia) &&
                           leadingTrivia[j + 1].IsKind(SyntaxKind.EndOfLineTrivia))
                    {
                        i++;

                        j += 2;
                    }
                }
            }

            TextLineCollection lines = sourceText.Lines;

            for (; i < lines.Count; i++)
            {
                TextLine line = lines[i];

                if (line.Span.Length <= maxLength)
                {
                    continue;
                }

                int end = line.End;

                SyntaxToken token = root.FindToken(end);

                if (token.IsKind(SyntaxKind.StringLiteralToken))
                {
                    TextSpan span = token.Span;

                    if (span.End == end)
                    {
                        if (span.Length >= maxLength)
                        {
                            continue;
                        }
                    }
                    else if (span.Contains(end) &&
                             end - span.Start >= maxLength)
                    {
                        continue;
                    }
                }

                SyntaxTriviaList list = default;

                if (token.LeadingTrivia.Span.Contains(end))
                {
                    list = token.LeadingTrivia;
                }
                else if (token.TrailingTrivia.Span.Contains(end))
                {
                    list = token.TrailingTrivia;
                }

                if (list.Any())
                {
                    int index = -1;

                    for (int j = 0; j < list.Count; j++)
                    {
                        if (list[j].Span.Contains(end))
                        {
                            trivia = list[j];
                            index  = j;
                        }
                    }

                    if (index >= 0)
                    {
                        SyntaxKind kind = trivia.Kind();

                        if (kind == SyntaxKind.MultiLineCommentTrivia ||
                            kind == SyntaxKind.SingleLineDocumentationCommentTrivia ||
                            kind == SyntaxKind.MultiLineDocumentationCommentTrivia)
                        {
                            continue;
                        }

                        if (kind == SyntaxKind.EndOfLineTrivia &&
                            index > 0 &&
                            list[index - 1].IsKind(SyntaxKind.SingleLineCommentTrivia))
                        {
                            continue;
                        }
                    }
                }

                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticDescriptors.LineIsTooLong,
                    Location.Create(tree, line.Span),
                    line.Span.Length);
            }
        }
示例#25
0
        private static async Task <StatementListInfo> RefactorAsync <TStatement>(
            Document document,
            TStatement statement,
            StatementListInfo statementsInfo,
            Func <TStatement, TStatement> createNewStatement,
            int count,
            bool removeReturnStatement,
            CancellationToken cancellationToken) where TStatement : StatementSyntax
        {
            int statementIndex = statementsInfo.IndexOf(statement);

            var returnStatement = (ReturnStatementSyntax)statementsInfo[statementIndex + 1];

            ExpressionSyntax returnExpression    = returnStatement.Expression;
            ExpressionSyntax newReturnExpression = null;
            SyntaxTriviaList newTrailingTrivia   = default;

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

            ISymbol symbol = semanticModel.GetSymbol(returnExpression, cancellationToken);

            if (symbol.Kind == SymbolKind.Local &&
                statementIndex > 0 &&
                statementsInfo[statementIndex - 1] is LocalDeclarationStatementSyntax localDeclarationStatement &&
                !localDeclarationStatement.ContainsDiagnostics &&
                !localDeclarationStatement.SpanOrTrailingTriviaContainsDirectives() &&
                !statement.GetLeadingTrivia().Any(f => f.IsDirective))
            {
                SeparatedSyntaxList <VariableDeclaratorSyntax> declarators = localDeclarationStatement.Declaration.Variables;

                VariableDeclaratorSyntax declarator = declarators.FirstOrDefault(f => semanticModel.GetDeclaredSymbol(f, cancellationToken)?.Equals(symbol) == true);

                if (declarator != null)
                {
                    ExpressionSyntax value = declarator.Initializer?.Value;

                    if (removeReturnStatement || value != null)
                    {
                        IEnumerable <ReferencedSymbol> referencedSymbols = await SymbolFinder.FindReferencesAsync(symbol, document.Solution(), cancellationToken).ConfigureAwait(false);

                        if (referencedSymbols.First().Locations.Count() == count + 1)
                        {
                            newReturnExpression = value;

                            if (declarators.Count == 1)
                            {
                                if (!removeReturnStatement &&
                                    returnStatement.GetTrailingTrivia().IsEmptyOrWhitespace())
                                {
                                    SyntaxTriviaList trailingTrivia = localDeclarationStatement.GetTrailingTrivia();

                                    if (trailingTrivia
                                        .SkipWhile(f => f.IsWhitespaceTrivia())
                                        .FirstOrDefault()
                                        .IsKind(SyntaxKind.SingleLineCommentTrivia))
                                    {
                                        newTrailingTrivia = trailingTrivia;
                                    }
                                }

                                SyntaxRemoveOptions removeOptions = SyntaxRefactorings.GetRemoveOptions(localDeclarationStatement);

                                if (newTrailingTrivia.Any())
                                {
                                    removeOptions &= ~SyntaxRemoveOptions.KeepTrailingTrivia;
                                }

                                statementsInfo = statementsInfo.RemoveNode(localDeclarationStatement, removeOptions);
                                statementIndex--;
                            }
                            else
                            {
                                statementsInfo = statementsInfo.ReplaceNode(localDeclarationStatement, localDeclarationStatement.RemoveNode(declarator, SyntaxRefactorings.GetRemoveOptions(declarator)));
                            }

                            returnStatement = (ReturnStatementSyntax)statementsInfo[statementIndex + 1];
                        }
                    }
                }
            }

            if (removeReturnStatement)
            {
                statementsInfo = statementsInfo.RemoveNode(returnStatement, SyntaxRefactorings.GetRemoveOptions(returnStatement));
            }
            else if (newReturnExpression != null)
            {
                ReturnStatementSyntax newReturnStatement = returnStatement.WithExpression(newReturnExpression.WithTriviaFrom(returnExpression));

                if (newTrailingTrivia.Any())
                {
                    newReturnStatement = newReturnStatement.WithTrailingTrivia(newTrailingTrivia);
                }

                statementsInfo = statementsInfo.ReplaceNode(returnStatement, newReturnStatement);
            }

            StatementSyntax oldNode = statementsInfo[statementIndex];

            TStatement newNode = createNewStatement((TStatement)oldNode).WithFormatterAnnotation();

            return(statementsInfo.ReplaceNode(oldNode, newNode));
        }
示例#26
0
 private static bool SpansPreprocessorDirective(SyntaxTriviaList list)
 {
     return(list.Any(t => t.GetStructure() is DirectiveTriviaSyntax));
 }
示例#27
0
 private static bool SpansPreprocessorDirective(SyntaxTriviaList list)
 {
     return list.Any(t => t.GetStructure() is DirectiveTriviaSyntax);
 }
示例#28
0
        public static Task <Document> RemoveParenthesesAsync(
            Document document,
            ParenthesizedExpressionSyntax parenthesizedExpression,
            CancellationToken cancellationToken = default)
        {
            ExpressionSyntax expression = parenthesizedExpression.Expression;

            SyntaxTriviaList leading = parenthesizedExpression.GetLeadingTrivia()
                                       .Concat(parenthesizedExpression.OpenParenToken.TrailingTrivia)
                                       .Concat(expression.GetLeadingTrivia())
                                       .ToSyntaxTriviaList();

            SyntaxTriviaList trailing = expression.GetTrailingTrivia()
                                        .Concat(parenthesizedExpression.CloseParenToken.LeadingTrivia)
                                        .Concat(parenthesizedExpression.GetTrailingTrivia())
                                        .ToSyntaxTriviaList();

            ExpressionSyntax newExpression = expression
                                             .WithLeadingTrivia(leading)
                                             .WithTrailingTrivia(trailing)
                                             .WithFormatterAnnotation();

            if (!leading.Any())
            {
                SyntaxNode parent = parenthesizedExpression.Parent;

                switch (parent.Kind())
                {
                case SyntaxKind.ReturnStatement:
                {
                    var returnStatement = (ReturnStatementSyntax)parent;

                    SyntaxToken returnKeyword = returnStatement.ReturnKeyword;

                    if (!returnKeyword.TrailingTrivia.Any())
                    {
                        ReturnStatementSyntax newNode = returnStatement.Update(returnKeyword.WithTrailingTrivia(Space), newExpression, returnStatement.SemicolonToken);

                        return(document.ReplaceNodeAsync(returnStatement, newNode, cancellationToken));
                    }

                    break;
                }

                case SyntaxKind.YieldReturnStatement:
                {
                    var yieldReturn = (YieldStatementSyntax)parent;

                    SyntaxToken returnKeyword = yieldReturn.ReturnOrBreakKeyword;

                    if (!returnKeyword.TrailingTrivia.Any())
                    {
                        YieldStatementSyntax newNode = yieldReturn.Update(yieldReturn.YieldKeyword, returnKeyword.WithTrailingTrivia(Space), newExpression, yieldReturn.SemicolonToken);

                        return(document.ReplaceNodeAsync(yieldReturn, newNode, cancellationToken));
                    }

                    break;
                }

                case SyntaxKind.AwaitExpression:
                {
                    var awaitExpression = (AwaitExpressionSyntax)parent;

                    SyntaxToken awaitKeyword = awaitExpression.AwaitKeyword;

                    if (!awaitKeyword.TrailingTrivia.Any())
                    {
                        AwaitExpressionSyntax newNode = awaitExpression.Update(awaitKeyword.WithTrailingTrivia(Space), newExpression);

                        return(document.ReplaceNodeAsync(awaitExpression, newNode, cancellationToken));
                    }

                    break;
                }
                }
            }

            return(document.ReplaceNodeAsync(parenthesizedExpression, newExpression, cancellationToken));
        }
示例#29
0
        private static Task <Document> FixAsync <TNode>(
            Document document,
            SyntaxNode containingNode,
            SyntaxNodeOrToken openNodeOrToken,
            SeparatedSyntaxList <TNode> nodes,
            CancellationToken cancellationToken) where TNode : SyntaxNode
        {
            IndentationAnalysis indentationAnalysis = AnalyzeIndentation(containingNode, cancellationToken);

            string increasedIndentation = indentationAnalysis.GetIncreasedIndentation();

            if (nodes.IsSingleLine(includeExteriorTrivia: false, cancellationToken: cancellationToken))
            {
                TNode node = nodes[0];

                SyntaxTriviaList leading = node.GetLeadingTrivia();

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

                return(document.WithTextChangeAsync(
                           new TextChange(span, increasedIndentation),
                           cancellationToken));
            }

            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 = nodes.GetSeparator(i - 1);
                }

                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 &&
                        (i > 0 || !containingNode.IsKind(SyntaxKind.AttributeList)))
                    {
                        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(document.WithTextChangesAsync(textChanges, cancellationToken));
        }
示例#30
0
 private static bool ContainsComment(SyntaxTriviaList trivias)
 {
     return trivias.Any(trivia => trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) || trivia.IsKind(SyntaxKind.MultiLineCommentTrivia));
 }
        private static void AnalyzeCompilationUnit(SyntaxNodeAnalysisContext context)
        {
            var compilationUnit = (CompilationUnitSyntax)context.Node;

            SyntaxToken endOfFile = compilationUnit.EndOfFileToken;

            SyntaxTriviaList.Reversed.Enumerator en = endOfFile.LeadingTrivia.Reverse().GetEnumerator();

            bool?preferNewLineAtEndOfFile = context.PreferNewLineAtEndOfFile();

            if (preferNewLineAtEndOfFile == null)
            {
                return;
            }

            if (preferNewLineAtEndOfFile == false)
            {
                if (en.MoveNext() &&
                    (!en.Current.IsWhitespaceTrivia() ||
                     en.MoveNext()))
                {
                    if (en.Current.IsEndOfLineTrivia())
                    {
                        ReportDiagnostic(context, endOfFile);
                    }
                    else if (SyntaxFacts.IsPreprocessorDirective(en.Current.Kind()) &&
                             en.Current.GetStructure() is DirectiveTriviaSyntax directiveTrivia &&
                             directiveTrivia.GetTrailingTrivia().LastOrDefault().IsEndOfLineTrivia())
                    {
                        ReportDiagnostic(context, endOfFile);
                    }
                }
                else
                {
                    SyntaxTriviaList trailing = endOfFile.GetPreviousToken().TrailingTrivia;

                    if (trailing.Any())
                    {
                        Debug.Assert(endOfFile.FullSpan.Start == trailing.Span.End);

                        if (endOfFile.FullSpan.Start == trailing.Span.End &&
                            trailing.LastOrDefault().IsEndOfLineTrivia())
                        {
                            ReportDiagnostic(context, endOfFile);
                        }
                    }
                }
            }
            else if (en.MoveNext())
            {
                if (CSharpFacts.IsCommentTrivia(en.Current.Kind()) ||
                    SyntaxFacts.IsPreprocessorDirective(en.Current.Kind()))
                {
                    ReportDiagnostic(context, endOfFile);
                }
                else if (en.Current.IsWhitespaceOrEndOfLineTrivia() &&
                         endOfFile.LeadingTrivia.Span.Start == 0)
                {
                    while (en.MoveNext())
                    {
                        if (!en.Current.IsWhitespaceOrEndOfLineTrivia())
                        {
                            return;
                        }
                    }

                    ReportDiagnostic(context, endOfFile);
                }
            }
            else if (endOfFile.SpanStart > 0)
            {
                SyntaxTriviaList trailing = endOfFile.GetPreviousToken().TrailingTrivia;

                if (!trailing.Any())
                {
                    ReportDiagnostic(context, endOfFile);
                }
                else
                {
                    Debug.Assert(endOfFile.FullSpan.Start == trailing.Span.End);

                    if (endOfFile.FullSpan.Start == trailing.Span.End &&
                        !trailing.Last().IsEndOfLineTrivia())
                    {
                        ReportDiagnostic(context, endOfFile);
                    }
                }
            }