/// <summary> /// Gets a value indicating whether the given trivia span multiple source text lines. /// </summary> /// <param name="trivia">The trivia to check.</param> /// <returns> /// <see langword="true"/> if the trivia spans multiple source text lines; otherwise, <see langword="false"/>. /// </returns> internal static bool SpansMultipleLines(this SyntaxTrivia trivia) { var lineSpan = trivia.GetLineSpan(); if (lineSpan == null) { return(false); } return(lineSpan.Value.StartLinePosition.Line < lineSpan.Value.EndLinePosition.Line); }
private static async Task <Document> GetTransformedDocumentAsync( Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); // For DocumentationCommentExteriorTrivia we must use findInsideTrivia: true so we don't get the entire XML comment trivia. SyntaxTrivia violatingTrivia = syntaxRoot.FindTrivia(diagnostic.Location.SourceSpan.Start, findInsideTrivia: true); string originalIndent = violatingTrivia.ToFullString(); int tabSize = GetTabSize(document); // If they've mixed tabs and spaces, then we need to figure out the original indent length in spaces. int startColumn = violatingTrivia.GetLineSpan().StartLinePosition.Character; int originalIndentColumn = startColumn; string nonWhitespaceSuffix = null; for (int i = 0; i < originalIndent.Length; i++) { char ch = originalIndent[i]; if (ch == '\t') { var offsetWithinTabColumn = originalIndentColumn % tabSize; var spaceCount = tabSize - offsetWithinTabColumn; originalIndentColumn += spaceCount; } else if (char.IsWhiteSpace(ch)) { originalIndentColumn++; } else { // For DocumentationCommentExteriorTrivia we must keep the /// suffix. nonWhitespaceSuffix = originalIndent.Substring(i); break; } } // We know that the violating trivia was leading whitespace trivia, and we NEVER want to use // spaces for indentation. So even if the indentation size isn't a multiple of the tab size, we'll // generate the new indentation string as only tabs. int originalIndentSpaceLength = originalIndentColumn - startColumn; int numTabs = originalIndentSpaceLength / tabSize; string tabIndent = new string('\t', numTabs) + nonWhitespaceSuffix; SyntaxTrivia newTrivia = violatingTrivia.IsKind(SyntaxKind.DocumentationCommentExteriorTrivia) ? SyntaxFactory.DocumentationCommentExterior(tabIndent) : SyntaxFactory.Whitespace(tabIndent); var newSyntaxRoot = syntaxRoot.ReplaceTrivia(violatingTrivia, newTrivia); return(document.WithSyntaxRoot(newSyntaxRoot)); }
private static bool AcceptableSingleLineTrivia(SyntaxTrivia trivia) { switch (trivia.Kind()) { case SyntaxKind.WhitespaceTrivia: case SyntaxKind.EndOfLineTrivia: return(true); case SyntaxKind.MultiLineCommentTrivia: var lineSpan = trivia.GetLineSpan(); return(lineSpan.StartLinePosition.Line == lineSpan.EndLinePosition.Line); default: return(false); } }
private static bool AcceptableSingleLineTrivia(SyntaxTrivia trivia) { switch (trivia.Kind()) { case SyntaxKind.WhitespaceTrivia: case SyntaxKind.EndOfLineTrivia: return true; case SyntaxKind.MultiLineCommentTrivia: var lineSpan = trivia.GetLineSpan(); return lineSpan.StartLinePosition.Line == lineSpan.EndLinePosition.Line; default: return false; } }
private static void HandleWhitespaceTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia) { // We can ignore structured trivia like directives (e.g., #region, #pragma) and XML comments. if (!trivia.HasStructure) { // We only need to look at leading trivia. It's ok to use spaces between keywords (e.g., private void Method()), // and those usually show up as trailing trivia. However, sometimes spaces between identifiers show up as leading // trivia (e.g., in <param name="X">). So we have to make sure the leading trivia is really at the beginning of a line. SyntaxToken token = trivia.Token; if (token.LeadingTrivia.IndexOf(trivia) >= 0 && trivia.ToFullString().IndexOf(' ') >= 0 && trivia.GetLineSpan().StartLinePosition.Character == 0) { context.ReportDiagnostic(Diagnostic.Create(Rule, trivia.GetLocation())); } } }
/// <summary> /// Gets the line on which the given trivia occurs. /// </summary> /// <param name="trivia">The trivia to use.</param> /// <returns>The line on which the given trivia occurs.</returns> internal static int?GetLine(this SyntaxTrivia trivia) { return(trivia.GetLineSpan()?.StartLinePosition.Line); }
/// <summary> /// Gets a value indicating whether the given trivia span multiple source text lines. /// </summary> /// <param name="trivia">The trivia to check.</param> /// <returns> /// <see langword="true"/> if the trivia spans multiple source text lines; otherwise, <see langword="false"/>. /// </returns> internal static bool SpansMultipleLines(this SyntaxTrivia trivia) { var lineSpan = trivia.GetLineSpan(); return(lineSpan.StartLinePosition.Line < lineSpan.EndLinePosition.Line); }
/// <summary> /// Gets the end line of the given trivia. /// </summary> /// <param name="trivia">The trivia to use.</param> /// <returns>The line on which the given trivia ends.</returns> internal static int GetEndLine(this SyntaxTrivia trivia) { return(trivia.GetLineSpan().EndLinePosition.Line); }