private void Format(DocumentationCommentTriviaSyntax node, CancellationToken cancellationToken = default) { // Only single line comments are supported. if (node.Kind() != SyntaxKind.SingleLineDocumentationCommentTrivia) { return; } _text = node.SyntaxTree.GetText(cancellationToken); _column = GetInitialColumn(node.GetFirstToken(), _tabSize, cancellationToken); _exteriorIndent = _column; _interiorLinePrefix = GetInteriorLinePrefix(node); _interiorIndent = 0; _breakStart = node.FullSpan.Start; _wordStart = _breakStart; _wordEnd = _wordStart; _breakMode = BreakMode.FirstBreak; FormatXmlNodes(node.Content); BreakFinal(node.EndOfComment); }
private static string GetInteriorLinePrefix(DocumentationCommentTriviaSyntax node) { switch (node.Kind()) { case SyntaxKind.SingleLineDocumentationCommentTrivia: { var firstToken = node.GetFirstToken(); char firstChar; if (!TryGetFirstChar(firstToken, out firstChar)) { return(string.Empty); } if (!IsWhitespace(firstChar)) { return(string.Empty); } // Check for a matching whitespace character on every line. foreach (var token in node.DescendantTokens()) { if (token.Kind() == SyntaxKind.XmlTextLiteralNewLineToken) { var nextToken = token.GetNextToken(); // If the next token is beyond the end of the comment then the new // line was the end of the comment. if (!node.Span.Contains(nextToken.Span)) { break; } if (!TryGetFirstChar(nextToken, out char c) || c != firstChar) { return(string.Empty); } } } return(firstChar.ToString(System.Globalization.CultureInfo.InvariantCulture)); } case SyntaxKind.MultiLineDocumentationCommentTrivia: { string whitespace = null; // Check for a matching whitespace prefix on every line after the first. foreach (var token in node.DescendantTokens()) { if (token.Kind() == SyntaxKind.XmlTextLiteralNewLineToken) { var nextToken = token.GetNextToken(); // If the next token is beyond the end of the comment then the new // line was the end of the comment. if (!node.Span.Contains(nextToken.Span)) { break; } string text; if (!TryGetLiteralText(nextToken, out text)) { return(string.Empty); } if (whitespace == null) { // The whitespace prefix is the leading whitespace of the text. for (int i = 0; i < text.Length; ++i) { if (!IsWhitespace(text[i])) { text = text.Substring(0, i - 1); } } whitespace = text; } else if (!text.StartsWith(whitespace, StringComparison.Ordinal)) { // The new whitespace prefix is the common prefix of the text // and the old whitespace prefix. for (int i = 0; i < text.Length; ++i) { if (text[i] != whitespace[i]) { text = text.Substring(0, i - 1); } } whitespace = text; } } } return(whitespace ?? string.Empty); } default: throw new InvalidOperationException("Unreachable."); } bool TryGetFirstChar(SyntaxToken token, out char c) { string text; if (!TryGetLiteralText(token, out text) || text.Length < 1) { c = default; return(false); } c = text[0]; return(true); } bool TryGetLiteralText(SyntaxToken token, out string text) { if (token.Kind() != SyntaxKind.XmlTextLiteralToken) { text = default; return(false); } text = token.ToString(); return(true); } }