private static SyntaxNode FixComment(Document document, SyntaxNode syntax, DocumentationCommentTriviaSyntax comment) { foreach (var part in comment.Content) { if (part is XmlElementSyntax e && e.GetName() == Constants.XmlTag.Exception) { foreach (var attribute in e.GetAttributes <XmlCrefAttributeSyntax>()) { switch (attribute.Cref) { case QualifiedCrefSyntax q when IsObjectDisposedException(q.ToString()): case NameMemberCrefSyntax m when IsObjectDisposedException(m.ToString()): { var symbol = GetSymbol(document, syntax); var phrase = MiKo_2056_ObjectDisposedExceptionPhraseAnalyzer.GetEndingPhrase(symbol); var exceptionComment = CommentEndingWith(e, phrase); return(comment.ReplaceNode(part, exceptionComment)); } } } } } return(null); }
private DocumentationCommentTriviaSyntax ProcessTag( DocumentationCommentTriviaSyntax documentationNode, IMethodOrAccessorTransformationResult methodTransformResult, string tagName, Func <IMethodSymbol, string> addOrReplace, Predicate <IMethodSymbol> canRemove, bool prepend) { if (addOrReplace == null && canRemove == null) { return(documentationNode); } var methodSymbol = methodTransformResult.AnalyzationResult.Symbol; var tagContent = addOrReplace?.Invoke(methodSymbol); var removeTag = canRemove?.Invoke(methodSymbol); var tagNode = documentationNode.Content.OfType <XmlElementSyntax>() .FirstOrDefault(o => o.StartTag.Name.ToString() == tagName); if (!string.IsNullOrEmpty(tagContent)) { var indent = methodTransformResult.LeadingWhitespaceTrivia.ToFullString(); var eol = methodTransformResult.EndOfLineTrivia.ToFullString(); var tagComment = CreateTagContent(tagName, tagContent, indent, eol); // When prepending a new tag before an existing tag we have to add the indentation at the end otherwise on start if (prepend && tagNode == null && documentationNode.Content.Any()) { var lastComment = tagComment.Content.Last(); tagComment = tagComment.ReplaceNode(lastComment, lastComment .WithTrailingTrivia(lastComment.GetTrailingTrivia() .Add(methodTransformResult.LeadingWhitespaceTrivia))); } else { var startComment = tagComment.Content.First(); tagComment = tagComment.ReplaceNode(startComment, startComment .WithLeadingTrivia(DocumentationCommentExterior($"{indent}///"))); } if (tagNode != null) { documentationNode = documentationNode.ReplaceNode(tagNode, tagComment.Content.OfType <XmlElementSyntax>().First()); } else { documentationNode = documentationNode.WithContent(prepend ? documentationNode.Content.InsertRange(0, tagComment.Content) : documentationNode.Content.AddRange(tagComment.Content)); } } else if (removeTag == true && tagNode != null) { // We need to remove the "///" XmlText and the tag itself var index = documentationNode.Content.IndexOf(tagNode); documentationNode = documentationNode.RemoveNode(tagNode, SyntaxRemoveOptions.KeepNoTrivia); documentationNode = documentationNode.RemoveNode(documentationNode.Content[index - 1], SyntaxRemoveOptions.KeepNoTrivia); } return(documentationNode); }
private static SyntaxNode FixTypeSummary(DocumentationCommentTriviaSyntax comment) { const string Phrase = Constants.Comments.ExceptionTypeSummaryStartingPhrase; var summary = GetXmlSyntax(Constants.XmlTag.Summary, comment).FirstOrDefault(); if (summary is null) { var newSummary = Comment(SyntaxFactory.XmlSummaryElement(), Phrase).WithTrailingXmlComment(); return(comment.InsertNodeAfter(comment.Content[0], newSummary)); } else { var newSummary = CommentStartingWith(summary, Phrase); return(comment.ReplaceNode(summary, newSummary)); } }
/// <summary> /// Add <paramref name="summary"/> element to <paramref name="comment"/> /// Replace if a summary element exists. /// </summary> /// <param name="comment">The <see cref="DocumentationCommentTriviaSyntax"/>.</param> /// <param name="summary"> The <see cref="XmlElementSyntax"/>.</param> /// <returns><paramref name="comment"/> with <paramref name="summary"/>.</returns> public static DocumentationCommentTriviaSyntax WithSummary(this DocumentationCommentTriviaSyntax comment, XmlElementSyntax summary) { if (comment is null) { throw new ArgumentNullException(nameof(comment)); } if (comment.TryGetSummary(out var old)) { return(comment.ReplaceNode(old, summary)); } if (comment.Content.TryFirstOfType(out XmlElementSyntax existing)) { return(comment.InsertBefore(existing, summary)); } return(comment.WithContent(comment.Content.Add(summary))); }
/// <summary> /// Add <paramref name="typeparam"/> element to <paramref name="comment"/> /// Replace if a summary element exists. /// If the comment is attached to a method the param element is inserted at the correct position. /// </summary> /// <param name="comment">The <see cref="DocumentationCommentTriviaSyntax"/>.</param> /// <param name="typeparam"> The <see cref="XmlElementSyntax"/>.</param> /// <returns><paramref name="comment"/> with <paramref name="typeparam"/>.</returns> public static DocumentationCommentTriviaSyntax WithTypeParam(this DocumentationCommentTriviaSyntax comment, XmlElementSyntax typeparam) { if (comment is null) { throw new ArgumentNullException(nameof(comment)); } if (typeparam.TryGetNameAttribute(out var attribute) && attribute.Identifier is { } identifierName) { if (comment.TryGetTypeParam(identifierName.Identifier.ValueText, out var old)) { return(comment.ReplaceNode(old, typeparam)); } if (TryGetPositionFromTypeParam(out var before, out var after)) { if (after is { }) { return(comment.InsertBefore(after, typeparam)); } return(comment.InsertAfter(before, typeparam)); } foreach (var node in comment.Content) { if (node is XmlElementSyntax e && (e.HasLocalName("param") || e.HasLocalName("returns") || e.HasLocalName("exception"))) { return(comment.InsertBefore(e, typeparam)); } } return(comment.InsertAfter(comment.Content.OfType <XmlElementSyntax>().Last(), typeparam)); }
/// <summary> /// Add <paramref name="typeparam"/> element to <paramref name="comment"/> /// Replace if a summary element exists. /// If the comment is attached to a method the param element is inserted at the correct position. /// </summary> /// <param name="comment">The <see cref="DocumentationCommentTriviaSyntax"/>.</param> /// <param name="typeparam"> The <see cref="XmlElementSyntax"/>.</param> /// <returns><paramref name="comment"/> with <paramref name="typeparam"/>.</returns> public static DocumentationCommentTriviaSyntax WithTypeParam(this DocumentationCommentTriviaSyntax comment, XmlElementSyntax typeparam) { if (comment is null) { throw new ArgumentNullException(nameof(comment)); } if (typeparam.TryGetNameAttribute(out var attribute) && attribute.Identifier is IdentifierNameSyntax identifierName) { if (comment.TryGetTypeParam(identifierName.Identifier.ValueText, out var old)) { return(comment.ReplaceNode(old, typeparam)); } if (TryGetPositionFromTypeParam(out var before, out var after)) { if (after != null) { return(comment.InsertBefore(after, typeparam)); } return(comment.InsertAfter(before, typeparam)); } foreach (var node in comment.Content) { if (node is XmlElementSyntax e && (e.HasLocalName("param") || e.HasLocalName("returns") || e.HasLocalName("exception"))) { return(comment.InsertBefore(e, typeparam)); } } return(comment.InsertAfter(comment.Content.OfType <XmlElementSyntax>().Last(), typeparam)); } throw new ArgumentException("Element does not have a name attribute.", nameof(typeparam)); bool TryGetPositionFromTypeParam(out XmlElementSyntax before, out XmlElementSyntax after) { before = null !; after = null !; if (comment.TryFirstAncestor(out MemberDeclarationSyntax? member) && TryGetTypeParameterList(member, out var typeParameterList) && typeParameterList.Parameters.TrySingle(x => x.Identifier.ValueText == identifierName.Identifier.ValueText, out var parameter) && typeParameterList.Parameters.IndexOf(parameter) is var ordinal && ordinal >= 0) { foreach (var node in comment.Content) { if (node is XmlElementSyntax e && e.HasLocalName("typeparam") && e.TryGetNameAttribute(out var nameAttribute) && typeParameterList.Parameters.TrySingle(x => x.Identifier.ValueText == nameAttribute.Identifier.Identifier.ValueText, out var other)) { before = e; if (ordinal < typeParameterList.Parameters.IndexOf(other)) { after = e; return(true); } } } } return(before != null);