/// <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);
    }
Example #2
0
        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));
        }
Example #3
0
        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;
            }
        }
Example #5
0
 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);
 }
Example #7
0
        /// <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);
        }
Example #8
0
 /// <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);
 }