Example #1
0
        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);
        }
Example #3
0
        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));
            }
        }
Example #4
0
        /// <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)));
        }
Example #5
0
        /// <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));
            }
Example #6
0
        /// <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);