コード例 #1
0
        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));
        }