/// <summary> /// Have the comment. /// </summary> /// <param name="commentTriviaSyntax">The comment trivia syntax.</param> /// <returns>A bool.</returns> public static bool HasComment(DocumentationCommentTriviaSyntax commentTriviaSyntax) { bool hasSummary = commentTriviaSyntax .ChildNodes() .OfType <XmlElementSyntax>() .Any(o => o.StartTag.Name.ToString().Equals(DocumentationHeaderHelper.Summary)); bool hasInheritDoc = commentTriviaSyntax .ChildNodes() .OfType <XmlEmptyElementSyntax>() .Any(o => o.Name.ToString().Equals(DocumentationHeaderHelper.InheritDoc)); return(hasSummary || hasInheritDoc); }
/// <summary> /// Analyzes node. /// </summary> /// <param name="context">The context.</param> private static void AnalyzeNode(SyntaxNodeAnalysisContext context) { ConstructorDeclarationSyntax node = context.Node as ConstructorDeclarationSyntax; DocumentationCommentTriviaSyntax commentTriviaSyntax = node .GetLeadingTrivia() .Select(o => o.GetStructure()) .OfType <DocumentationCommentTriviaSyntax>() .FirstOrDefault(); if (commentTriviaSyntax != null) { bool hasSummary = commentTriviaSyntax .ChildNodes() .OfType <XmlElementSyntax>() .Any(o => o.StartTag.Name.ToString().Equals(DocumentationHeaderHelper.Summary)); if (hasSummary) { return; } } context.ReportDiagnostic(Diagnostic.Create(Rule, node.Identifier.GetLocation())); }
/// <summary> /// Analyzes node. /// </summary> /// <param name="context">The context.</param> private static void AnalyzeNode(SyntaxNodeAnalysisContext context) { FieldDeclarationSyntax node = context.Node as FieldDeclarationSyntax; // Only const. if (!node.Modifiers.Any(SyntaxKind.ConstKeyword)) { return; } DocumentationCommentTriviaSyntax commentTriviaSyntax = node .GetLeadingTrivia() .Select(o => o.GetStructure()) .OfType <DocumentationCommentTriviaSyntax>() .FirstOrDefault(); if (commentTriviaSyntax != null) { bool hasSummary = commentTriviaSyntax .ChildNodes() .OfType <XmlElementSyntax>() .Any(o => o.StartTag.Name.ToString().Equals(DocumentationHeaderHelper.Summary)); if (hasSummary) { return; } } VariableDeclaratorSyntax field = node.DescendantNodes().OfType <VariableDeclaratorSyntax>().First(); context.ReportDiagnostic(Diagnostic.Create(Rule, field.GetLocation())); }
internal static IEnumerable <CrefSyntax> GetDocumentedExceptions(this DocumentationCommentTriviaSyntax @this) { return(@this .ChildNodes() .OfType <XmlElementSyntax>() .Select(element => element.StartTag) .Where(tag => String.Equals("exception", tag.Name.LocalName.ValueText, StringComparison.Ordinal)) .SelectMany(tag => tag.Attributes.OfType <XmlCrefAttributeSyntax>()) .Select(attribute => attribute.Cref)); }
private static string GetSummary(CSharpSyntaxNode node) { DocumentationCommentTriviaSyntax xmlTrivia = node.GetLeadingTrivia() .Select(i => i.GetStructure()) .OfType <DocumentationCommentTriviaSyntax>() .FirstOrDefault(); //TODO: fix bool?isSummary = xmlTrivia?.ChildNodes() .OfType <XmlElementSyntax>() .Any(i => i.StartTag.Name.ToString().Equals("summary")); return(isSummary == true?xmlTrivia.ToString() : null); }
private string Extract(DocumentationCommentTriviaSyntax xmlComment, string tagName) { string extracted = null; XmlElementSyntax summary = xmlComment.ChildNodes().OfType <XmlElementSyntax>().FirstOrDefault(x => x.StartTag.Name.ToString() == tagName); if (summary != null) { extracted = string.Empty; for (int index = 0; index < summary.Content.Count; index++) { XmlNodeSyntax xmlNodeSyntax = summary.Content[index]; extracted += (index == 0 ? Clean(xmlNodeSyntax) : $"\n<p>{Clean(xmlNodeSyntax)}</p>"); } } return(extracted); }
private XmlElementSyntax GetSummaryTag(DocumentationCommentTriviaSyntax xmlComment) => xmlComment .ChildNodes() .OfType <XmlElementSyntax>() .FirstOrDefault(n => XmlCommentSummaryTag.Equals(n.StartTag?.Name?.ToString(), StringComparison.Ordinal));
private XmlEmptyElementSyntax GetXmlExcludeTag(DocumentationCommentTriviaSyntax xmlComment) => xmlComment .ChildNodes() .OfType <XmlEmptyElementSyntax>() .FirstOrDefault(s => XmlCommentExcludeTag.Equals(s.Name?.ToString(), StringComparison.Ordinal));
public static XmlElementSyntax GetXmlCommentParam(this DocumentationCommentTriviaSyntax documentationSyntax, string xmlParamName) => documentationSyntax?.ChildNodes() .OfType <XmlElementSyntax>() .FirstOrDefault(xmlElementSyntax => xmlElementSyntax.IsXmlCommentParam(xmlParamName));
private async Task <Document> CreateChangedDocumentAsync(CodeFixContext context, DocumentationCommentTriviaSyntax documentationCommentTriviaSyntax, CancellationToken cancellationToken) { StringBuilder leadingTriviaBuilder = new StringBuilder(); SyntaxToken parentToken = documentationCommentTriviaSyntax.ParentTrivia.Token; int documentationCommentIndex = parentToken.LeadingTrivia.IndexOf(documentationCommentTriviaSyntax.ParentTrivia); for (int i = 0; i < documentationCommentIndex; i++) { SyntaxTrivia trivia = parentToken.LeadingTrivia[i]; switch (trivia.Kind()) { case SyntaxKind.EndOfLineTrivia: leadingTriviaBuilder.Clear(); break; case SyntaxKind.WhitespaceTrivia: leadingTriviaBuilder.Append(trivia.ToFullString()); break; default: break; } } leadingTriviaBuilder.Append(documentationCommentTriviaSyntax.GetLeadingTrivia().ToFullString()); // this is the trivia that should appear at the beginning of each line of the comment. SyntaxTrivia leadingTrivia = SyntaxFactory.DocumentationCommentExterior(leadingTriviaBuilder.ToString()); string newLineText = context.Document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp); var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken); var documentedSymbol = semanticModel.GetDeclaredSymbol(parentToken.Parent.FirstAncestorOrSelf <SyntaxNode>(SyntaxNodeExtensionsEx.IsSymbolDeclaration), context.CancellationToken); DocumentationCommentTriviaSyntax contentsOnly = RemoveExteriorTrivia(documentationCommentTriviaSyntax); contentsOnly = contentsOnly.ReplaceNodes(contentsOnly.ChildNodes(), (originalNode, rewrittenNode) => RenderBlockElementAsMarkdown(originalNode, rewrittenNode, newLineText, documentedSymbol)); string renderedContent = contentsOnly.Content.ToFullString(); string[] lines = renderedContent.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None); SyntaxList <XmlNodeSyntax> newContent = XmlSyntaxFactory.List(); for (int i = 0; i < lines.Length; i++) { string line = lines[i]; if (string.IsNullOrWhiteSpace(line)) { if (i == lines.Length - 1) { break; } line = string.Empty; } if (newContent.Count > 0) { newContent = newContent.Add(XmlSyntaxFactory.NewLine(newLineText).WithTrailingTrivia(SyntaxFactory.DocumentationCommentExterior("///"))); } newContent = newContent.Add(XmlSyntaxFactory.Text(line.TrimEnd(), xmlEscape: false)); } contentsOnly = contentsOnly.WithContent(newContent); contentsOnly = contentsOnly .ReplaceExteriorTrivia(leadingTrivia) .WithLeadingTrivia(SyntaxFactory.DocumentationCommentExterior("///")) .WithTrailingTrivia(SyntaxFactory.EndOfLine(Environment.NewLine)); string fullContent = contentsOnly.ToFullString(); SyntaxTriviaList parsedTrivia = SyntaxFactory.ParseLeadingTrivia(fullContent); SyntaxTrivia documentationTrivia = parsedTrivia.FirstOrDefault(i => i.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia)); contentsOnly = documentationTrivia.GetStructure() as DocumentationCommentTriviaSyntax; if (contentsOnly == null) { return(context.Document); } // Remove unnecessary nested paragraph elements contentsOnly = contentsOnly.ReplaceNodes(contentsOnly.DescendantNodes().OfType <XmlElementSyntax>(), MarkUnnecessaryParagraphs); contentsOnly = contentsOnly.ReplaceNodes(contentsOnly.DescendantNodes().OfType <XmlElementSyntax>(), RemoveUnnecessaryParagraphs); SyntaxNode root = await context.Document.GetSyntaxRootAsync(cancellationToken); SyntaxNode newRoot = root.ReplaceNode(documentationCommentTriviaSyntax, contentsOnly); if (documentationCommentTriviaSyntax.IsEquivalentTo(contentsOnly)) { return(context.Document); } if (documentationCommentTriviaSyntax.ToFullString().Equals(contentsOnly.ToFullString(), StringComparison.Ordinal)) { return(context.Document); } return(context.Document.WithSyntaxRoot(newRoot)); }