如何从 AST 创建编译单元

How to create a compilation unit from an AST

我正在编写一个需要生成 AST 的解决方案,然后应该解析该 AST 以生成具有可用语义的有效编译单元。

  1. AST是通过SyntaxFactoryclass.
  2. 生成的
  3. 然后我需要以某种方式得到一个Compilation
  4. 然后我会从编译单元中获取对SemanticModel的引用

创建 AST

我 运行 生成 AST 的代码是这样的:

var classNode = SyntaxFactory.ClassDeclaration("MyCLass");
classNode = classNode.AddMembers(
  SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("string"), "DoIt")
    .WithBody(...));
...

缺少部分

如您所见,第一部分还不错。我可以获得我的 AST。但是现在我需要把它转换成代码? 如何在AST上调用编译器?:

              Compiler                Compilation.GetSemanticModel(AST)
              |                       |
     +-----+  v  +-----------------+  v  +---------------+
+----> AST +-----> CompilationUnit +-----> SemanticModel |
  ^  +-----+     +-----------------+     +---------------+
  |              ^                 ^
  |              |-----------------|
  Factories              ???

请注意,与获取 SemanticModel 相关的部分已涵盖,因为我只需要使用 Compilation 对象并通过传递 CSharpSyntaxTree 对其调用 GetSemanticModel .

如果你想知道为什么会这样,那是因为我正在编写一个测试工具。不管用什么,这个场景应该是可以的。怎么样?

要在 Roslyn 中创建 Compilation,您需要一个有效的语法树,要获得一个有效的语法树,您可以像这样解析文本:

var tree = CSharpSyntaxTree.ParseText(@"using System;
              namespace HelloWorld
              {
                public class MyType{public void MyMethod(){} public void MySecondMethod(){}}
              }"));

或者你可以像你写的那样使用SyntaxFactory(或SyntaxGenerator)。 (只需添加 usingsnamespace 除非你写一个 CSharpScript,它是必需的,你也可以检查 RoslynQuoter 以获得有效的 SyntaxTree

当你有一个有效的 SyntaxTree 时,你可以写这个以获得 CompilationSemanticModel

 var options = new CSharpCompilationOptions(kind);
 var root = (CompilationUnitSyntax)tree.GetRoot();
 var compilation = CSharpCompilation.Create("HelloWorld", options: options).
                   AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)).
                   AddSyntaxTrees(tree);
 var model = compilation.GetSemanticModel(tree);