Roslyn CSharpCompilation.Create 在通过 CompilationUnit.SyntaxTree 时失败

问题描述 投票:0回答:1

我遇到了这个问题,我肯定遗漏了一些东西。我已经设法将问题减少到可以在此处发布的可复制示例。

这段使用 Microsoft.CodeAnalysis.CSharp.SyntaxFactory 的示例代码

var compilationUnit = CompilationUnit()
.AddMembers(
    NamespaceDeclaration(ParseName("TopNSpace"))
        .AddMembers(
            InterfaceDeclaration("IInterfaceUsing")
                .AddModifiers(Token(SyntaxKind.PublicKeyword))
                .AddMembers(
                    PropertyDeclaration(IdentifierName("ChildNSpace.IInterfaceUsed"), "UsingProperty")
                        .AddAccessorListAccessors(
                            AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                                .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))
                            )
                )
            )
        )
.AddMembers(
    NamespaceDeclaration(ParseName("TopNSpace.ChildNSpace"))
        .AddMembers(
            InterfaceDeclaration("IInterfaceUsed")
                .AddModifiers(Token(SyntaxKind.PublicKeyword))
        )
    );

创建一个 CompilationUnitSyntax,在调用 NormalizeWhitespace().ToFullString() 时产生这个:

namespace TopNSpace
{
    public interface IInterfaceUsing
    {
        ChildNSpace.IInterfaceUsed UsingProperty { get; }
    }
}

namespace TopNSpace.ChildNSpace
{
    public interface IInterfaceUsed
    {
    }
}

我的问题是,当我尝试直接从这个 CompilationUint 的 SyntaxTree 创建 CSharpCompilation 时,它会产生一个错误:

var compilationFailed = CSharpCompilation.Create("Fails")
    .AddSyntaxTrees(compilationUnit.SyntaxTree) // Using SyntaxTree directly
    .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

以上会产生此诊断错误: 找不到类型或命名空间名称“ChildNSpace.IInterfaceUsed”(是否缺少 using 指令或程序集引用?)

但是如果我解析 CompilationUnit 的 ToString() 来创建一个新的语法树,它会起作用:

var tree = CSharpSyntaxTree.ParseText(compilationUnit.NormalizeWhitespace().ToFullString());

var compilationSucceeded = CSharpCompilation.Create("Succeeds")
    .AddSyntaxTrees(tree) // Now from the re-parsed string
    .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

这工作正常,不会产生任何错误。

在这两种情况下,CSharpCompilation 的 LanguageVersion 都是 CSharp11。

我在这里错过了什么?我不应该能够直接从语法树创建 CSharpCompilation 吗?

在我的实际用例中,CompilationUnit 的语法树非常大,从 CompilationUnit.ToString() 解析新树时性能会受到显着影响。所以我真的很想避免它。

非常感谢任何帮助!

roslyn
1个回答
0
投票

感谢 StackOverflow 成为橡皮鸭!发布问题后就想通了。

IdentifierName 在为 PropertyDeclationSyntax 指定点分类型时并不适用。符合要求的是 QualifiedNameSyntax。

从以下位置更改 PropertyDeclaration 的类型:

PropertyDeclaration(IdentifierName("ChildNSpace.IInterfaceUsed")

至:

PropertyDeclaration(QualifiedName(
        IdentifierName("ChildNSpace"),
        IdentifierName("IInterfaceUsed")
        )

修好了!

是的,我觉得自己很蠢!我会在辩护中说,当检查从 ToString() 生成的代码时,它看起来完全一样。

生活和学习!

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.