我有以下编译:
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();
Run Code Online (Sandbox Code Playgroud)
我修改了一个方法的主体
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);
Run Code Online (Sandbox Code Playgroud)
在对方法进行更改后,我想更新编译,以便例如我可以查询节点的类型:
var typeInfo = semanticModel.GetTypeInfo(node).Type;
Run Code Online (Sandbox Code Playgroud)
目前我正在做的事情:
var oldSyntaxTree = semanticModel.SyntaxTree;
var newSyntaxTree = newSource.SyntaxTree;
var newCompilation = compilation.ReplaceSyntaxTree(oldSyntaxTree, newSyntaxTree);
var newSemanticModel = newCompilation.GetSemanticModel(newSyntaxTree);
Run Code Online (Sandbox Code Playgroud)
我想在修改主体后立即更新编译,这样如果我从修改后的方法的父类调用访问者,我就可以看到更改.
是否可以在不编译整个项目/类的情况下部分更新编译?
更新
如果我理解正确,我认为不可能.在Roslyn github的FAQ页面上,它说:
我可以在编译器管道中重写源代码吗?
Roslyn 没有在整个编译器管道中提供插件架构,因此在每个阶段都可以影响语法分析,语义分析,优化算法,代码发射等.[...]您可以使用Roslyn来解析代码并进行语义分析它,然后重写树,更改引用等.然后将结果编译为新的编译.
是否可以在不编译整个项目/类的情况下部分更新编译?
不,SyntaxTree 是作为 ImmutableArray 实现的。因此,您实际上是在创建一个新的 SyntaxTree,而不是修改旧的 SyntaxTree,同样,需要将新的 SyntaxTree 编译为新的编译。
您可以用新的对象覆盖 Compilation 或 SemanticModel 对象,如果这样可以使代码更容易推理,但在幕后,您每次替换节点或其他节点时都会创建语法树的新实例,因此您的目前的做法似乎是合适的。
没什么大不了的,我不会让它太打扰你。您只是关心性能或最佳方法还是......?