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 <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); }
/// <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 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); }