private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            if (context.Tree.IsWhitespaceOnly(context.CancellationToken))
            {
                // Handling of empty documents is now the responsibility of the analyzers
                return;
            }

            var firstToken = context.Tree.GetRoot().GetFirstToken(includeZeroWidth: true);

            if (firstToken.HasLeadingTrivia)
            {
                var leadingTrivia = firstToken.LeadingTrivia;

                var firstNonBlankLineTriviaIndex = TriviaHelper.IndexOfFirstNonBlankLineTrivia(leadingTrivia);
                switch (firstNonBlankLineTriviaIndex)
                {
                case 0:
                    // no blank lines
                    break;

                case -1:
                    // only blank lines
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, leadingTrivia.Span)));
                    break;

                default:
                    var textSpan = TextSpan.FromBounds(leadingTrivia[0].Span.Start, leadingTrivia[firstNonBlankLineTriviaIndex].Span.Start);
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, textSpan)));
                    break;
                }
            }
        }
        private static void HandleUsings(SyntaxNodeAnalysisContext context, SyntaxList <UsingDirectiveSyntax> usings, StyleCopSettings settings)
        {
            if (usings.Count < 2)
            {
                return;
            }

            var blankLinesBetweenUsingGroups = settings.OrderingRules.BlankLinesBetweenUsingGroups;

            var previousGroupType = usings[0].GetUsingGroupType(settings);
            var previousLineSpan  = usings[0].GetLineSpan();

            for (var i = 1; i < usings.Count; i++)
            {
                var currentGroupType = usings[i].GetUsingGroupType(settings);
                var currentLineSpan  = usings[i].GetLineSpan();

                var partOfSameGroup = previousGroupType == currentGroupType;
                var lineDistance    = currentLineSpan.StartLinePosition.Line - previousLineSpan.EndLinePosition.Line;

                previousGroupType = currentGroupType;
                previousLineSpan  = currentLineSpan;

                if (partOfSameGroup)
                {
                    // if the using statements are part of the same group, there is no need to check.
                    continue;
                }

                if (blankLinesBetweenUsingGroups == OptionSetting.Require)
                {
                    if (lineDistance > 1)
                    {
                        var separatingTrivia = TriviaHelper.MergeTriviaLists(usings[i - 1].GetTrailingTrivia(), usings[i].GetLeadingTrivia());
                        if (separatingTrivia.ContainsBlankLines(false))
                        {
                            continue;
                        }
                    }

                    context.ReportDiagnostic(Diagnostic.Create(DescriptorRequire, usings[i].UsingKeyword.GetLocation(), DiagnosticPropertiesRequire));
                }
                else if (blankLinesBetweenUsingGroups == OptionSetting.Omit)
                {
                    if (lineDistance < 2)
                    {
                        // no point in checking the trivia if the using statements are not separated.
                        continue;
                    }

                    var separatingTrivia = TriviaHelper.MergeTriviaLists(usings[i - 1].GetTrailingTrivia(), usings[i].GetLeadingTrivia());
                    if (!separatingTrivia.ContainsBlankLines(false))
                    {
                        continue;
                    }

                    context.ReportDiagnostic(Diagnostic.Create(DescriptorOmit, usings[i].UsingKeyword.GetLocation(), DiagnosticPropertiesOmit));
                }
            }
        }
        private static void HandleNullableType(SyntaxNodeAnalysisContext context)
        {
            var nullableType  = (NullableTypeSyntax)context.Node;
            var questionToken = nullableType.QuestionToken;

            if (questionToken.IsMissing)
            {
                return;
            }

            if (nullableType.ElementType.IsMissing)
            {
                return;
            }

            /* Do not test for the first character on the line!
             * The StyleCop documentation is wrong there, the actual StyleCop code does not accept it.
             */

            SyntaxToken precedingToken = questionToken.GetPreviousToken();
            var         triviaList     = TriviaHelper.MergeTriviaLists(precedingToken.TrailingTrivia, questionToken.LeadingTrivia);

            if (triviaList.Any(t => t.IsKind(SyntaxKind.WhitespaceTrivia) || t.IsKind(SyntaxKind.EndOfLineTrivia)))
            {
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, questionToken.GetLocation()));
            }
        }
예제 #4
0
        private static void HandleSyntaxTreeAnalysis(SyntaxTreeAnalysisContext context)
        {
            var firstToken = context.Tree.GetRoot().GetFirstToken(includeZeroWidth: true);

            if (firstToken.HasLeadingTrivia)
            {
                var leadingTrivia = firstToken.LeadingTrivia;

                var firstNonBlankLineTriviaIndex = TriviaHelper.IndexOfFirstNonBlankLineTrivia(leadingTrivia);
                switch (firstNonBlankLineTriviaIndex)
                {
                case 0:
                    // no blank lines
                    break;

                case -1:
                    // only blank lines
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, leadingTrivia.Span)));
                    break;

                default:
                    var textSpan = TextSpan.FromBounds(leadingTrivia[0].Span.Start, leadingTrivia[firstNonBlankLineTriviaIndex].Span.Start);
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, textSpan)));
                    break;
                }
            }
        }
        private static async Task <SyntaxNode> GetTransformedSyntaxRootAsync(Document document, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var settings = document.Project.AnalyzerOptions.GetStyleCopSettings(root.SyntaxTree, cancellationToken);

            var        fileHeader = FileHeaderHelpers.ParseFileHeader(root);
            SyntaxNode newSyntaxRoot;

            if (fileHeader.IsMissing)
            {
                newSyntaxRoot = AddHeader(document, root, GetFileName(document), settings);
            }
            else
            {
                var trivia       = root.GetLeadingTrivia();
                var commentIndex = TriviaHelper.IndexOfFirstNonWhitespaceTrivia(trivia, false);

                // Safe to do this as fileHeader.IsMissing is false.
                var isMultiLineComment = trivia[commentIndex].IsKind(SyntaxKind.MultiLineCommentTrivia);

                var xmlFileHeader = FileHeaderHelpers.ParseXmlFileHeader(root);
                if (isMultiLineComment && !xmlFileHeader.IsMalformed)
                {
                    newSyntaxRoot = ReplaceWellFormedMultiLineCommentHeader(document, root, settings, commentIndex, xmlFileHeader);
                }
                else
                {
                    newSyntaxRoot = ReplaceHeader(document, root, settings, xmlFileHeader.IsMalformed);
                }
            }

            return(newSyntaxRoot);
        }
        private static BlockSyntax ReformatBodyAsMultipleLines(BlockSyntax body, SyntaxTrivia indentation, SyntaxTrivia indentationStatements)
        {
            SyntaxTriviaList reformattedOpenBraceTrailingTrivia;
            SyntaxTriviaList reformattedCloseBraceLeadingTrivia;

            SyntaxList <StatementSyntax> newStatements;

            if (body.Statements.Count > 0)
            {
                var reformattedStatement = body.Statements[0]
                                           .WithLeadingTrivia(ReformatTriviaListNoLeadingSpace(body.Statements[0].GetLeadingTrivia()).Insert(0, indentationStatements))
                                           .WithTrailingTrivia(ReformatTriviaListNoTrailingSpace(body.Statements[0].GetTrailingTrivia()).Add(SyntaxFactory.CarriageReturnLineFeed));

                reformattedOpenBraceTrailingTrivia = ReformatTriviaListNoTrailingSpace(body.OpenBraceToken.TrailingTrivia);
                newStatements = SyntaxFactory.List <StatementSyntax>().Add(reformattedStatement);
                reformattedCloseBraceLeadingTrivia = ReformatTriviaListNoLeadingSpace(body.CloseBraceToken.LeadingTrivia);
            }
            else
            {
                var triviaBetweenBraces = TriviaHelper.MergeTriviaLists(body.OpenBraceToken.TrailingTrivia, body.CloseBraceToken.LeadingTrivia);
                reformattedOpenBraceTrailingTrivia = ReformatTriviaListNoTrailingSpace(triviaBetweenBraces);
                newStatements = body.Statements;
                reformattedCloseBraceLeadingTrivia = SyntaxFactory.TriviaList();
            }

            var newOpenBraceToken = body.OpenBraceToken
                                    .WithLeadingTrivia(ReformatTriviaListNoLeadingSpace(body.OpenBraceToken.LeadingTrivia).Insert(0, indentation))
                                    .WithTrailingTrivia(reformattedOpenBraceTrailingTrivia.Add(SyntaxFactory.CarriageReturnLineFeed));

            var newCloseBraceToken = body.CloseBraceToken
                                     .WithLeadingTrivia(reformattedCloseBraceLeadingTrivia.Insert(0, indentation))
                                     .WithTrailingTrivia(ReformatTriviaListNoTrailingSpace(body.CloseBraceToken.TrailingTrivia).Add(SyntaxFactory.CarriageReturnLineFeed));

            return(body.Update(newOpenBraceToken, newStatements, newCloseBraceToken));
        }
예제 #7
0
        private static void HandleSingleLineComment(SyntaxTreeAnalysisContext context, SyntaxTrivia singleLineComment)
        {
            int index = 0;

            // PERF: Explicitly cast to IReadOnlyList so we only box once.
            IReadOnlyList <SyntaxTrivia> list = TriviaHelper.GetContainingTriviaList(singleLineComment, out index);
            var firstNonWhiteSpace            = TriviaHelper.IndexOfFirstNonWhitespaceTrivia(list);

            // When we encounter a block of single line comments, we only want to raise this diagnostic
            // on the first or last line.  This ensures that whitespace in code commented out using
            // the Comment Selection option in Visual Studio will not raise the diagnostic for every
            // blank line in the code which is commented out.
            bool isFirst = index == firstNonWhiteSpace;

            if (!isFirst)
            {
                // This is -2 because we need to go back past the end of line trivia as well.
                var lastNonWhiteSpace = TriviaHelper.IndexOfTrailingWhitespace(list) - 2;
                if (index != lastNonWhiteSpace)
                {
                    return;
                }
            }

            if (IsNullOrWhiteSpace(singleLineComment.ToString(), 2))
            {
                var diagnostic = Diagnostic.Create(Descriptor, singleLineComment.GetLocation());
                context.ReportDiagnostic(diagnostic);
            }
        }
        private static async Task <Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var accessorToken = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start);
            var accessorList  = (AccessorListSyntax)accessorToken.Parent.Parent;

            var firstAccesor         = accessorList.Accessors[0];
            var secondAccessor       = accessorList.Accessors[1];
            var trackedRoot          = syntaxRoot.TrackNodes(firstAccesor, secondAccessor);
            var trackedFirstAccessor = trackedRoot.GetCurrentNode(firstAccesor);
            var newAccessor          = GetNewAccessor(accessorList, firstAccesor, secondAccessor);

            syntaxRoot = trackedRoot.InsertNodesBefore(trackedFirstAccessor, new[] { newAccessor });

            trackedFirstAccessor = syntaxRoot.GetCurrentNode(firstAccesor);
            if (secondAccessor.GetFirstToken().HasLeadingBlankLines())
            {
                var newFirstAccessor = trackedFirstAccessor.WithLeadingTrivia(
                    TriviaHelper.MergeTriviaLists(new[] { SyntaxFactory.CarriageReturnLineFeed }, trackedFirstAccessor.GetLeadingTrivia()));
                syntaxRoot = syntaxRoot.ReplaceNode(trackedFirstAccessor, newFirstAccessor);
            }

            var trackedLastAccessor = syntaxRoot.GetCurrentNode(secondAccessor);
            var keepTriviaOptions   = AccessorsAreOnTheSameLine(firstAccesor, secondAccessor)
                ? SyntaxRemoveOptions.KeepEndOfLine
                : SyntaxRemoveOptions.KeepNoTrivia;

            syntaxRoot = syntaxRoot.RemoveNode(trackedLastAccessor, keepTriviaOptions);

            return(document.WithSyntaxRoot(syntaxRoot));
        }
예제 #9
0
            public override SyntaxNode VisitUsingDirective(UsingDirectiveSyntax node)
            {
                // The strip list is used to remove using directives that will be moved.
                if (this.stripList.Contains(node))
                {
                    var nextToken = node.SemicolonToken.GetNextToken();

                    if (!nextToken.IsKind(SyntaxKind.None))
                    {
                        var index = TriviaHelper.IndexOfFirstNonBlankLineTrivia(nextToken.LeadingTrivia);
                        if (index != 0)
                        {
                            this.tokensToStrip.AddLast(nextToken);
                        }
                    }

                    return(null);
                }

                // The replacement map is used to replace using declarations in place in sorted order (inside directive trivia)
                UsingDirectiveSyntax replacementNode;

                if (this.replaceMap.TryGetValue(node, out replacementNode))
                {
                    return(replacementNode);
                }

                return(base.VisitUsingDirective(node));
            }
예제 #10
0
        /// <inheritdoc/>
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            foreach (Diagnostic diagnostic in context.Diagnostics.Where(d => FixableDiagnostics.Contains(d.Id)))
            {
                var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

                var firstToken    = syntaxRoot.GetFirstToken(includeZeroWidth: true);
                var leadingTrivia = firstToken.LeadingTrivia;

                var newTriviaList = SyntaxFactory.TriviaList();

                var firstNonBlankLineTriviaIndex = TriviaHelper.IndexOfFirstNonBlankLineTrivia(leadingTrivia);
                if (firstNonBlankLineTriviaIndex != -1)
                {
                    for (var index = firstNonBlankLineTriviaIndex; index < leadingTrivia.Count; index++)
                    {
                        newTriviaList = newTriviaList.Add(leadingTrivia[index]);
                    }
                }

                var newFirstToken = firstToken.WithLeadingTrivia(newTriviaList);
                var newSyntaxRoot = syntaxRoot.ReplaceToken(firstToken, newFirstToken);
                var newDocument   = context.Document.WithSyntaxRoot(newSyntaxRoot);

                context.RegisterCodeFix(CodeAction.Create("Remove blank lines at the start of the file", token => Task.FromResult(newDocument)), diagnostic);
            }
        }
예제 #11
0
        // If you want a full implementation of this analyzer with system tests and a code fix, go to
        // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1120CommentsMustContainText.cs

        private void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            SyntaxNode root = context.Tree.GetCompilationUnitRoot(context.CancellationToken);

            foreach (var node in root.DescendantTrivia())
            {
                switch (node.Kind())
                {
                case SyntaxKind.SingleLineCommentTrivia:
                    // Remove the leading // from the comment
                    var commentText = node.ToString().Substring(2);
                    int index       = 0;

                    var  list    = TriviaHelper.GetContainingTriviaList(node, out index);
                    bool isFirst = IsFirstComment(list, index);
                    bool isLast  = IsLastComment(list, index);

                    if (string.IsNullOrWhiteSpace(commentText) && (isFirst || isLast))
                    {
                        var diagnostic = Diagnostic.Create(Rule, node.GetLocation());
                        context.ReportDiagnostic(diagnostic);
                    }

                    break;
                }
            }
        }
        /// <summary>
        /// Checks if a given <see cref="SyntaxTree"/> only contains whitespaces. We don't want to analyze empty files.
        /// </summary>
        /// <param name="tree">The syntax tree to examine.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> that the task will observe.</param>
        /// <returns>
        /// <para><see langword="true"/> if <paramref name="tree"/> only contains whitespaces; otherwise, <see langword="false"/>.</para>
        /// </returns>
        private static bool IsEmpty(SyntaxTree tree, CancellationToken cancellationToken)
        {
            var root       = tree.GetRoot(cancellationToken);
            var firstToken = root.GetFirstToken(includeZeroWidth: true);

            return(firstToken.IsKind(SyntaxKind.EndOfFileToken) &&
                   TriviaHelper.IndexOfFirstNonWhitespaceTrivia(firstToken.LeadingTrivia, true) == -1);
        }
        private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
        {
            var syntaxRoot = context.Tree.GetRoot(context.CancellationToken);

            foreach (var trivia in syntaxRoot.DescendantTrivia().Where(trivia => trivia.IsKind(SyntaxKind.SingleLineCommentTrivia)))
            {
                if (trivia.FullSpan.Start == 0)
                {
                    // skip the trivia if it is at the start of the file
                    continue;
                }

                if (trivia.ToString().StartsWith("////", StringComparison.Ordinal))
                {
                    // ignore commented out code
                    continue;
                }

                int triviaIndex;

                // PERF: Explicitly cast to IReadOnlyList so we only box once.
                var triviaList = TriviaHelper.GetContainingTriviaList(trivia, out triviaIndex);

                if (!IsOnOwnLine(triviaList, triviaIndex))
                {
                    // ignore comments after other code elements.
                    continue;
                }

                if (IsPrecededByBlankLine(triviaList, triviaIndex))
                {
                    // allow properly formatted blank line comments.
                    continue;
                }

                if (IsPrecededBySingleLineCommentOrDocumentation(triviaList, triviaIndex))
                {
                    // allow consecutive single line comments.
                    continue;
                }

                if (IsAtStartOfScope(trivia))
                {
                    // allow single line comment at scope start.
                    continue;
                }

                if (IsPrecededByDirectiveTrivia(triviaList, triviaIndex))
                {
                    // allow single line comment that is preceded by some directive trivia (if, elif, else)
                    continue;
                }

                var diagnosticSpan = TextSpan.FromBounds(trivia.SpanStart, trivia.SpanStart + 2);
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, diagnosticSpan)));
            }
        }
예제 #14
0
        private void AddQuestion_Click(object sender, EventArgs e)
        {
            string message = "";

            if (!TriviaHelper.AddQuestion(this, ref message))
            {
                MessageBox.Show(message);
            }
        }
예제 #15
0
        private void DeleteButton_Click(object sender, EventArgs e)
        {
            string message = "";

            if (TriviaHelper.DeleteCourse(this, ref message))
            {
                MessageBox.Show(message);
            }
        }
        private static void AnalyzeCloseBrace(SyntaxNodeAnalysisContext context, SyntaxToken closeBraceToken)
        {
            if (closeBraceToken.IsKind(SyntaxKind.None))
            {
                return;
            }

            var previousToken = closeBraceToken.GetPreviousToken();

            if ((closeBraceToken.GetLineSpan().StartLinePosition.Line - previousToken.GetLineSpan().EndLinePosition.Line) < 2)
            {
                // there will be no blank lines when the closing brace and the preceding token are not at least two lines apart.
                return;
            }

            var separatingTrivia = TriviaHelper.MergeTriviaLists(previousToken.TrailingTrivia, closeBraceToken.LeadingTrivia);

            // skip all leading whitespace for the close brace
            // the index must be checked because two tokens can be more than two lines apart and
            // still only be separated by whitespace trivia due to compilation errors
            var index = separatingTrivia.Count - 1;

            while (index >= 0 && separatingTrivia[index].IsKind(SyntaxKind.WhitespaceTrivia))
            {
                index--;
            }

            var done     = false;
            var eolCount = 0;

            while (!done && index >= 0)
            {
                switch (separatingTrivia[index].Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                    break;

                case SyntaxKind.EndOfLineTrivia:
                    eolCount++;
                    break;

                default:
                    done = true;
                    break;
                }

                index--;
            }

            if (eolCount > 1)
            {
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, closeBraceToken.GetLocation()));
            }
        }
        private async Task <Document> FixCommentSpacingAsync(Document document, SyntaxToken token, CancellationToken cancellationToken)
        {
            var newDeclaration = token
                                 .WithLeadingTrivia(TriviaHelper.FixSingleLineCommentSpacing(token.LeadingTrivia))
                                 .WithTrailingTrivia(TriviaHelper.FixSingleLineCommentSpacing(token.TrailingTrivia));

            var root = await document.GetSyntaxRootAsync();

            var newRoot = root.ReplaceToken(token, newDeclaration);

            return(document.WithSyntaxRoot(newRoot));
        }
예제 #18
0
        private static void HandlePrefixUnaryExpression(SyntaxNodeAnalysisContext context)
        {
            var unaryExpression = (PrefixUnaryExpressionSyntax)context.Node;
            var precedingToken  = unaryExpression.OperatorToken.GetPreviousToken();
            var followingToken  = unaryExpression.OperatorToken.GetNextToken();
            var followingTrivia = TriviaHelper.MergeTriviaLists(unaryExpression.OperatorToken.TrailingTrivia, followingToken.LeadingTrivia);

            /* let the outer operator handle things like the following, so no error is reported for '++':
             *   c ^= *++buf4;
             *
             * if the unary expression is inside parenthesis or an indexer, there should be no leading space
             */
            var mustHaveLeadingWhitespace = !(unaryExpression.Parent is PrefixUnaryExpressionSyntax) &&
                                            !(unaryExpression.Parent is CastExpressionSyntax) &&
                                            !precedingToken.IsKind(SyntaxKind.OpenParenToken) &&
                                            !precedingToken.IsKind(SyntaxKind.OpenBracketToken) &&
                                            !(precedingToken.IsKind(SyntaxKind.OpenBraceToken) && (precedingToken.Parent is InterpolationSyntax));

            bool analyze;

            switch (unaryExpression.OperatorToken.Kind())
            {
            case SyntaxKind.PlusToken:
                analyze = context.IsAnalyzerSuppressed(SA1022PositiveSignsMustBeSpacedCorrectly.DiagnosticId);
                break;

            case SyntaxKind.MinusToken:
                analyze = context.IsAnalyzerSuppressed(SA1021NegativeSignsMustBeSpacedCorrectly.DiagnosticId);
                break;

            case SyntaxKind.PlusPlusToken:
            case SyntaxKind.MinusMinusToken:
                analyze = context.IsAnalyzerSuppressed(SA1020IncrementDecrementSymbolsMustBeSpacedCorrectly.DiagnosticId);
                break;

            default:
                analyze = true;
                break;
            }

            if (analyze)
            {
                if (followingTrivia.Any(t => t.IsKind(SyntaxKind.SingleLineCommentTrivia)) || followingTrivia.Any(t => t.IsKind(SyntaxKind.MultiLineCommentTrivia)))
                {
                    context.ReportDiagnostic(Diagnostic.Create(DescriptorNotFollowedByComment, unaryExpression.OperatorToken.GetLocation(), unaryExpression.OperatorToken.Text));
                }
                else
                {
                    CheckToken(context, unaryExpression.OperatorToken, mustHaveLeadingWhitespace, false, false);
                }
            }
        }
예제 #19
0
        private static void AnalyzeOpenBrace(SyntaxNodeAnalysisContext context, SyntaxToken openBraceToken)
        {
            var nextToken = openBraceToken.GetNextToken();

            if (nextToken.IsMissingOrDefault())
            {
                return;
            }

            if ((GetLine(nextToken) - GetLine(openBraceToken)) < 2)
            {
                // there will be no blank lines when the opening brace and the following token are not at least two lines apart.
                return;
            }

            var separatingTrivia = TriviaHelper.MergeTriviaLists(openBraceToken.TrailingTrivia, nextToken.LeadingTrivia);

            // skip everything until the first end of line (as this is considered part of the line of the opening brace)
            var startIndex = 0;

            while ((startIndex < separatingTrivia.Count) && !separatingTrivia[startIndex].IsKind(SyntaxKind.EndOfLineTrivia))
            {
                startIndex++;
            }

            startIndex = (startIndex == separatingTrivia.Count) ? 0 : startIndex + 1;

            var done     = false;
            var eolCount = 0;

            for (var i = startIndex; !done && (i < separatingTrivia.Count); i++)
            {
                switch (separatingTrivia[i].Kind())
                {
                case SyntaxKind.WhitespaceTrivia:
                    break;

                case SyntaxKind.EndOfLineTrivia:
                    eolCount++;
                    break;

                default:
                    done = true;
                    break;
                }
            }

            if (eolCount > 0)
            {
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, openBraceToken.GetLocation()));
            }
        }
예제 #20
0
            public override SyntaxToken VisitToken(SyntaxToken token)
            {
                if (this.tokensToStrip.Contains(token))
                {
                    this.tokensToStrip.Remove(token);

                    var index            = TriviaHelper.IndexOfFirstNonBlankLineTrivia(token.LeadingTrivia);
                    var newLeadingTrivia = (index == -1) ? SyntaxFactory.TriviaList() : SyntaxFactory.TriviaList(token.LeadingTrivia.Skip(index));
                    return(token.WithLeadingTrivia(newLeadingTrivia));
                }

                return(base.VisitToken(token));
            }
        private static SyntaxToken StripViolatingWhitespace(SyntaxToken token)
        {
            SyntaxToken result = token;

            var trailingWhitespaceIndex = TriviaHelper.IndexOfTrailingWhitespace(token.LeadingTrivia);

            if (trailingWhitespaceIndex != -1)
            {
                var newTriviaList = SyntaxFactory.TriviaList(token.LeadingTrivia.Take(trailingWhitespaceIndex));
                result = token.WithLeadingTrivia(newTriviaList);
            }

            return(result);
        }
예제 #22
0
        private static async Task <Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var node = root.FindTrivia(diagnostic.Location.SourceSpan.Start, true);

            int diagnosticIndex = 0;
            var triviaList      = TriviaHelper.GetContainingTriviaList(node, out diagnosticIndex);

            var nodesToRemove = new List <SyntaxTrivia>();

            nodesToRemove.Add(node);

            // If there is trialing content on the line, we don't want to remove the leading whitespace
            bool hasTrailingContent = TriviaHasTrailingContentOnLine(root, triviaList);

            if (diagnosticIndex > 0 && !hasTrailingContent)
            {
                var previousStart = triviaList[diagnosticIndex - 1].SpanStart;
                var previousNode  = root.FindTrivia(previousStart, true);
                nodesToRemove.Add(previousNode);
            }

            // If there is leading content on the line, then we don't want to remove the trailing end of lines
            bool hasLeadingContent = TriviaHasLeadingContentOnLine(root, triviaList);

            if (diagnosticIndex < triviaList.Count - 1)
            {
                var nextStart = triviaList[diagnosticIndex + 1].SpanStart;
                var nextNode  = root.FindTrivia(nextStart, true);

                if (nextNode.IsKind(SyntaxKind.EndOfLineTrivia) && !hasLeadingContent)
                {
                    nodesToRemove.Add(nextNode);
                }
            }

            // Replace all roots with an empty node
            var newRoot = root.ReplaceTrivia(nodesToRemove, (original, rewritten) =>
            {
                return(new SyntaxTrivia());
            });

            newRoot = newRoot.NormalizeWhitespace();

            Document updatedDocument = document.WithSyntaxRoot(newRoot);

            return(updatedDocument);
        }
        private static async Task <Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var indentationOptions = IndentationOptions.FromDocument(document);
            var newLine            = TriviaHelper.GetNewLineTrivia(document);

            var constructorInitializer = (ConstructorInitializerSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan);
            var constructorDeclaration = (ConstructorDeclarationSyntax)constructorInitializer.Parent;

            var newConstructorDeclaration = ReformatConstructorDeclaration(constructorDeclaration, indentationOptions, newLine);

            var newSyntaxRoot = syntaxRoot.ReplaceNode(constructorDeclaration, newConstructorDeclaration);

            return(document.WithSyntaxRoot(newSyntaxRoot));
        }
        private static void HandleSyntaxTreeAction(SyntaxTreeAnalysisContext context)
        {
            var lastToken = context.Tree.GetRoot().GetLastToken(includeZeroWidth: true);

            if (lastToken.HasLeadingTrivia)
            {
                var leadingTrivia = lastToken.LeadingTrivia;

                var trailingWhitespaceIndex = TriviaHelper.IndexOfTrailingWhitespace(leadingTrivia);
                if (trailingWhitespaceIndex != -1)
                {
                    var textSpan = TextSpan.FromBounds(leadingTrivia[trailingWhitespaceIndex].SpanStart, leadingTrivia[leadingTrivia.Count - 1].Span.End);
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.Create(context.Tree, textSpan)));
                }
            }
        }
        private static AccessorDeclarationSyntax GetNewAccessor(AccessorListSyntax accessorList, AccessorDeclarationSyntax firstAccessor, AccessorDeclarationSyntax secondAccessor)
        {
            var newLeadingTrivia = GetLeadingTriviaWithoutLeadingBlankLines(secondAccessor);

            if (AccessorsAreOnTheSameLine(firstAccessor, secondAccessor))
            {
                var leadingWhitespace = firstAccessor.GetLeadingTrivia().Where(x => x.IsKind(SyntaxKind.WhitespaceTrivia));
                newLeadingTrivia = SyntaxFactory.TriviaList(TriviaHelper.MergeTriviaLists(newLeadingTrivia, SyntaxTriviaList.Empty.AddRange(leadingWhitespace)));
            }

            var newAccessor = accessorList.Accessors[1]
                              .WithBody(secondAccessor.Body)
                              .WithLeadingTrivia(newLeadingTrivia);

            return(newAccessor);
        }
예제 #26
0
        private static async Task <Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var trivia = root.FindTrivia(diagnostic.Location.SourceSpan.Start, true);

            int diagnosticIndex = 0;
            var triviaList      = TriviaHelper.GetContainingTriviaList(trivia, out diagnosticIndex);

            var triviaToRemove = new List <SyntaxTrivia>();

            triviaToRemove.Add(trivia);

            bool hasTrailingContent = TriviaHasTrailingContentOnLine(root, trivia);

            if (!hasTrailingContent && diagnosticIndex > 0)
            {
                var previousTrivia = triviaList[diagnosticIndex - 1];
                if (previousTrivia.IsKind(SyntaxKind.WhitespaceTrivia))
                {
                    triviaToRemove.Add(previousTrivia);
                }
            }

            bool hasLeadingContent = TriviaHasLeadingContentOnLine(root, trivia);

            if (!hasLeadingContent && diagnosticIndex < triviaList.Count - 1)
            {
                var nextTrivia = triviaList[diagnosticIndex + 1];
                if (nextTrivia.IsKind(SyntaxKind.EndOfLineTrivia))
                {
                    triviaToRemove.Add(nextTrivia);
                }
            }

            // Replace all roots with an empty node
            var newRoot = root.ReplaceTrivia(triviaToRemove, (original, rewritten) =>
            {
                return(default(SyntaxTrivia));
            });

            Document updatedDocument = document.WithSyntaxRoot(newRoot);

            return(updatedDocument);
        }
            protected override async Task <SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document)
            {
                var diagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false);

                if (diagnostics.IsEmpty)
                {
                    return(null);
                }

                var syntaxRoot = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false);

                var indentationOptions = IndentationOptions.FromDocument(document);
                var newLine            = TriviaHelper.GetNewLineTrivia(document);

                var nodes = diagnostics.Select(diagnostic => syntaxRoot.FindNode(diagnostic.Location.SourceSpan).Parent);

                return(syntaxRoot.ReplaceNodes(nodes, (originalNode, rewrittenNode) => ReformatConstructorDeclaration((ConstructorDeclarationSyntax)rewrittenNode, indentationOptions, newLine)));
            }
예제 #28
0
        private static SyntaxNode GetReplacement(ParenthesizedExpressionSyntax oldNode)
        {
            var leadingTrivia  = SyntaxFactory.TriviaList(oldNode.OpenParenToken.GetAllTrivia().Concat(oldNode.Expression.GetLeadingTrivia()));
            var trailingTrivia = oldNode.Expression.GetTrailingTrivia().AddRange(oldNode.CloseParenToken.GetAllTrivia());

            // Workaround for Roslyn not handling elastic markers for directive trivia correctly.
            if (!leadingTrivia.Any())
            {
                var previousToken = oldNode.OpenParenToken.GetPreviousToken();
                if (!previousToken.IsKind(SyntaxKind.OpenParenToken) && (TriviaHelper.IndexOfTrailingWhitespace(previousToken.TrailingTrivia) == -1))
                {
                    leadingTrivia = SyntaxFactory.TriviaList(SyntaxFactory.Space);
                }
            }

            return(oldNode.Expression
                   .WithLeadingTrivia(leadingTrivia)
                   .WithTrailingTrivia(trailingTrivia.Any() ? trailingTrivia : SyntaxFactory.TriviaList(SyntaxFactory.ElasticMarker)));
        }
        private static AccessorDeclarationSyntax GetNewAccessor(AccessorListSyntax accessorList, AccessorDeclarationSyntax firstAccessor, AccessorDeclarationSyntax secondAccessor)
        {
            var newLeadingTrivia = GetLeadingTriviaWithoutLeadingBlankLines(secondAccessor);

            if (AccessorsAreOnTheSameLine(firstAccessor, secondAccessor))
            {
                var leadingWhitespace = firstAccessor.GetLeadingTrivia().Where(x => x.IsKind(SyntaxKind.WhitespaceTrivia)).ToList();
                newLeadingTrivia = SyntaxFactory.TriviaList(TriviaHelper.MergeTriviaLists(newLeadingTrivia, leadingWhitespace));
            }

            var newAccessor = accessorList.Accessors[1]
                              .WithBody(secondAccessor.Body)
                              .WithLeadingTrivia(newLeadingTrivia);

            if (secondAccessor.GetFirstToken().HasLeadingBlankLines())
            {
                newAccessor.WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed, SyntaxFactory.CarriageReturnLineFeed);
            }

            return(newAccessor);
        }
예제 #30
0
        private static async Task <Document> RemoveSemicolonTextAsync(Document document, SyntaxToken token, CancellationToken cancellationToken)
        {
            TextChange textChange;

            SourceText sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            TextLine line = sourceText.Lines.GetLineFromPosition(token.SpanStart);

            if (sourceText.ToString(line.Span).Trim() == token.Text)
            {
                // remove the line containing the semicolon token
                textChange = new TextChange(line.SpanIncludingLineBreak, string.Empty);
                return(document.WithText(sourceText.WithChanges(textChange)));
            }

            TextSpan spanToRemove;
            var      whitespaceIndex = TriviaHelper.IndexOfTrailingWhitespace(token.LeadingTrivia);

            if (whitespaceIndex >= 0)
            {
                spanToRemove = TextSpan.FromBounds(token.LeadingTrivia[whitespaceIndex].Span.Start, token.Span.End);
            }
            else
            {
                var previousToken = token.GetPreviousToken();
                whitespaceIndex = TriviaHelper.IndexOfTrailingWhitespace(previousToken.TrailingTrivia);
                if (whitespaceIndex >= 0)
                {
                    spanToRemove = TextSpan.FromBounds(previousToken.TrailingTrivia[whitespaceIndex].Span.Start, token.Span.End);
                }
                else
                {
                    spanToRemove = token.Span;
                }
            }

            textChange = new TextChange(spanToRemove, string.Empty);
            return(document.WithText(sourceText.WithChanges(textChange)));
        }