如何在Roslyn中为ClassDeclarationSyntax添加XML文档注释?

3

我有一些构建类的代码:

return SyntaxFactory
    .ClassDeclaration(name)
    .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
    .WithMembers(GetProperties());

这一切都有效,并输出我期望的类。我想在此基础上添加一个XML文档:
/// <summary>
/// Some plain text here.
/// </summary>

我不需要任何花哨的东西,只需要简单的文本。我很难找到任何相关示例,并且已经尝试了各种AnnotationsTrivia和许多方法(例如SyntaxFactoryXmlCommentXmlElementStartTagDocumentationCommentExteriorDocumentationCommentTrivia),但都没有成功(具有讽刺意味的是,这些中没有 XML 注释!)。我最接近的一次编译成功了,但在运行时崩溃并出现了Unexpected false
我正在使用 VS 2015 RC 和 Roslyn 的 1.0.0-rc2 版本,目标为 .NET 4.5。
4个回答

8
尝试这个:
var doc = @"
/// <summary>
/// Some plain text here.
/// </summary>
";
return SyntaxFactory.Comment(doc);

最好使用 SyntaxFactory.ParseLeadingTrivia(doc) - Kris Vandermotten

7
您可以使用 RoslynQuoter 查看如何实现此操作:
        SyntaxFactory.ClassDeclaration(
            @"C")
        .WithKeyword(
            SyntaxFactory.Token(
                SyntaxFactory.TriviaList(
                    SyntaxFactory.Trivia(
                        SyntaxFactory.DocumentationCommentTrivia(
                            SyntaxKind.SingleLineDocumentationCommentTrivia,
                            SyntaxFactory.List<XmlNodeSyntax>(
                                new XmlNodeSyntax[]{
                                    SyntaxFactory.XmlText()
                                    .WithTextTokens(
                                        SyntaxFactory.TokenList(
                                            SyntaxFactory.XmlTextLiteral(
                                                SyntaxFactory.TriviaList(
                                                    SyntaxFactory.DocumentationCommentExterior(
                                                        @"///")),
                                                @" ",
                                                @" ",
                                                SyntaxFactory.TriviaList()))),
                                    SyntaxFactory.XmlElement(
                                        SyntaxFactory.XmlElementStartTag(
                                            SyntaxFactory.XmlName(
                                                SyntaxFactory.Identifier(
                                                    @"summary"))),
                                        SyntaxFactory.XmlElementEndTag(
                                            SyntaxFactory.XmlName(
                                                SyntaxFactory.Identifier(
                                                    @"summary"))))
                                    .WithContent(
                                        SyntaxFactory.SingletonList<XmlNodeSyntax>(
                                            SyntaxFactory.XmlText()
                                            .WithTextTokens(
                                                SyntaxFactory.TokenList(
                                                    new []{
                                                        SyntaxFactory.XmlTextNewLine(
                                                            SyntaxFactory.TriviaList(),
                                                            @"
",
                                                            @"
",
                                                            SyntaxFactory.TriviaList()),
                                                        SyntaxFactory.XmlTextLiteral(
                                                            SyntaxFactory.TriviaList(
                                                                SyntaxFactory.DocumentationCommentExterior(
                                                                    @"///")),
                                                            @" Some plain text here.",
                                                            @" Some plain text here.",
                                                            SyntaxFactory.TriviaList()),
                                                        SyntaxFactory.XmlTextNewLine(
                                                            SyntaxFactory.TriviaList(),
                                                            @"
",
                                                            @"
",
                                                            SyntaxFactory.TriviaList()),
                                                        SyntaxFactory.XmlTextLiteral(
                                                            SyntaxFactory.TriviaList(
                                                                SyntaxFactory.DocumentationCommentExterior(
                                                                    @"///")),
                                                            @" ",
                                                            @" ",
                                                            SyntaxFactory.TriviaList())})))),
                                    SyntaxFactory.XmlText()
                                    .WithTextTokens(
                                        SyntaxFactory.TokenList(
                                            SyntaxFactory.XmlTextNewLine(
                                                SyntaxFactory.TriviaList(),
                                                @"
",
                                                @"
",
                                                SyntaxFactory.TriviaList())))})))),
                SyntaxKind.ClassKeyword,
                SyntaxFactory.TriviaList()))))

太好了,感谢您!(比我希望的稍微详细一些!) - Danny Tuppeny
1
@DannyTuppeny:你可能可以省略很多内容。 - SLaks
是的,我可以看到很多不必要的东西(比如换行符),但这是一个很好的起点(而且这个工具将会节省很多类似的问题!)我在将其写入磁盘之前会通过格式化程序进行处理。 - Danny Tuppeny
@DannyTuppeny,你有没有找到更简短的方法来完成这个任务? - LOST
@LOST 我觉得我最终只用字符串构建我的代码。APIs感觉比它们值得的工作还多 :( - Danny Tuppeny

4
这是我最终采取的做法:
var tokens = docText.Split('\n')
    .Select(line => XmlTextLiteral(line))
    .ToList();
for(int i = 1; i < tokens.Count; i += 2)
    tokens.Insert(i, XmlTextNewLine("\n"));

var summary = XmlElement("summary",
    SingletonList<XmlNodeSyntax>(XmlText(TokenList(tokens))));
SyntaxTriviaList doc = TriviaList(
    Trivia(DocumentationComment(summary, XmlText("\n"))));
return member.WithLeadingTrivia(doc);

正如您所注意到的,每个汇总中的行分隔符都需要手动插入XmlTextNewLine。最终的 XmlText("\n") 是为了确保成员定义实际上是在 /// </summary> 之后的新行上开始的。

我实际上没有在Visual Studio中进行过测试(例如,还没有检查过工具提示)。您可能需要在每个换行符周围生成<p><para><br/>或类似的内容。


0

如已经注意到的那样,解析工作正常,您可以使用必要的XmlText换行符进行构建。

这里有一个扩展方法类,您可以基于它。请注意,不同的文档xml元素有不同的类。例如下面的XmlValueElement和XmlSummaryElement。

public static class XmlComments
{
    private static TMember AddSimple<TMember>(this TMember member,XmlElementSyntax xmlElement) where TMember:MemberDeclarationSyntax
    {
        return member.WithLeadingTrivia(
                TriviaList(
                    Trivia(
                        DocumentationComment(
                            xmlElement,
                            XmlText().WithTextTokens(
                                TokenList(
                                    Token(
                                        TriviaList(),
                                        SyntaxKind.XmlTextLiteralNewLineToken,
                                        Environment.NewLine,
                                        Environment.NewLine,
                                        TriviaList()
                                    )
                                )
                            )
                        )
                    )
                )
            );
    }
    public static PropertyDeclarationSyntax AddValue(this PropertyDeclarationSyntax property,string value)
    {
        return property.AddSimple(
            XmlValueElement(
                XmlText(value)
            ));
    }
    public static TMember AddSummary<TMember>(this TMember member, string value) where TMember: MemberDeclarationSyntax
    {
        return member.AddSimple(
            XmlSummaryElement(
                XmlText(value)
            ));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接