Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to partially update compilation with new syntax tree?

Tags:

c#

roslyn

I have the following compilation:

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();

I have modified the body of a method

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);

After I made the changes to the method, I would like to update the compilation so that for example I can query for the type of a node:

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

At the moment I am doing:

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

I would like to update the compilation right after I modified the body, so that I can see the changes if I am calling the visitor from the parent class of the modified method.

Is it possible to partially update the compilation without compiling the entire project/class?

Update

If I understood correctly, I don't think it is possible. On the FAQ page on Roslyn github it says:

Can I rewrite source code within the compiler pipeline?

Roslyn does not provide a plug-in architecture throughout the compiler pipeline so that at each stage you can affect syntax parsed, semantic analysis, optimization algorithms, code emission, etc. [...] You can use Roslyn to parse code and semantically analyze it, and then rewrite the trees, change references, etc. Then compile the result as a new compilation.

like image 850
cipri.l Avatar asked Sep 11 '25 00:09

cipri.l


1 Answers

Is it possible to partially update the compilation without compiling the entire project/class?

   No, the SyntaxTree is implemented as an ImmutableArray. Thus, you are actually creating a new SyntaxTree, not modifying the old one, and similarly, will need to compile the new SyntaxTree into a new compilation.
   You can overwrite the Compilation or SemanticModel object with the new one if that makes the code easier to reason about, but under the hood, you are creating a new instance of the syntax tree each time you replace a node or what have you, so your current approach seems appropriate.
   No big deal, I wouldn't let it bother you too much. Were you just concerned about performance or the best approach or...?

like image 93
Adam White Avatar answered Sep 12 '25 16:09

Adam White