如何使用新语法树部分更新编译?

时间:2015-06-05 15:57:57

标签: c# roslyn

我有以下编译:

Solution solutionToAnalyze = workspace.OpenSolutionAsync(pathToSolution).Result;
var projects = solutionToAnalyze.Projects;
Compilation compilation = projects.First().GetCompilationAsync().Result; 
var syntaxTrees = compilation.SyntaxTrees.First();
var semanticModel = compilation.GetSemanticModel(syntaxTree, true);
SyntaxNode newSource = semanticModel.SyntaxTree.GetRoot();
var methodRefactoringVisitor = new MethodRefactoringVisitor();

我修改了方法的主体

public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax method)
{
    var newBody = method.Body;
    //modify newBody
    var updatedMethod = method.ReplaceNode(method.Body, newBody);
    return updatedMethod;
}

newSource = methodRefactoringVisitor.Visit(newSource);

在对方法进行更改后,我想更新编译,以便例如我可以查询节点的类型:

var typeInfo = semanticModel.GetTypeInfo(node).Type;

我正在做的那一刻:

var oldSyntaxTree = semanticModel.SyntaxTree;
var newSyntaxTree = newSource.SyntaxTree;
var newCompilation = compilation.ReplaceSyntaxTree(oldSyntaxTree, newSyntaxTree);
var newSemanticModel = newCompilation.GetSemanticModel(newSyntaxTree);

我想在修改正文后立即更新编译,这样如果我从修改后的方法的父类调用访问者,我就可以看到更改。

是否可以在不编译整个项目/类的情况下部分更新编译?

更新

如果我理解正确,我认为不可能。 在Roslyn github的FAQ页面上,它说:

我可以在编译器管道中重写源代码吗?

Roslyn 在整个编译器管道中没有提供插件架构,因此在每个阶段都可以影响语法分析,语义分析,优化算法,代码发射等。[...]您可以使用Roslyn来解析代码并对其进行语义分析,然后重写树,更改引用等。然后将结果编译为新的编译。

1 个答案:

答案 0 :(得分:1)

  

是否可以在不编译整个项目/类的情况下部分更新编译?

不,SyntaxTree是作为ImmutableArray实现的。因此,您实际上是在创建一个新的SyntaxTree,而不是修改旧的SyntaxTree,同样,需要将新的SyntaxTree编译为新的编译。
你可以使用新的对象覆盖Compilation或SemanticModel对象,如果这使得代码更易于推理,但是在每次更换节点或者你有什么时,你会创建一个新的语法树实例,所以你的目前的做法似乎是恰当的 没什么大不了的,我不会太烦你。你只关心表现或最佳方法还是......?