/// <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);