2012-08-28 17 views
7

Estoy tratando de modificar el árbol de sintaxis y luego obtener el modelo semántico actualizado. Aquí es lo que tengo hasta ahora:modificar el árbol de sintaxis, luego obtener el modelo semántico actualizado

var tree = Roslyn.Compilers.CSharp.SyntaxTree.ParseCompilationUnit(code); 
var compilation = Roslyn.Compilers.CSharp.Compilation.Create(
         "MyCompilation", 
         syntaxTrees: new[] { tree }, 
         references: new[] { mscorlib }); 
var semanticModel = compilation.GetSemanticModel(tree); 
... 
var oldStatementNode = (parent as ExpressionStatementSyntax); //some SyntaxNode in the tree 
var oldExpressionNode = oldStatementNode.Expression; 
var newExpressionNode = Syntax.ParenthesizedExpression(oldExpressionNode); 
var newRootNode = tree.GetRoot().ReplaceNode(oldExpressionNode, newExpressionNode); 

var semanticInfo = semanticModel.GetTypeInfo(newExpressionNode); //throws exception "Syntax node is not within syntax tree" 

Si trato de llamar semanticModel = compilation.GetSemanticModel(tree); o incluso hacer nueva compilación con tree antes de llamar GetTypeInfo() - misma excepción.

Entonces, ¿cómo me actualizo SemanticModel? (Por supuesto que podría obtener una fuente modificada y hacer todo desde el principio, pero supongo que hay una manera más eficiente).

Me falta algo obvio aquí estoy seguro, ¿tal vez hay un nuevo árbol de sintaxis creado en alguna parte?

Respuesta

14

tipos Roslyn son inmutables, por lo que necesita para construir un nuevo SyntaxTree para su newRootNode, y luego llamar a compilation.UpdateSyntaxTree para obtener una nueva Compilation, y entonces usted puede llamar newCompilation.GetSemanticModel(newTree) para obtener una nueva SemanticModel.

Considere pasar al nivel Servicios y utilizando una ISolution en su lugar. Algo como:

var doc = Solution.Create(SolutionId.CreateNewId()).AddCSharpProject("MyCompilation", "MyCompilation").AddMetadataReference(mscorlib).AddDocument("MyFile", code); 

var semanticModel = (SemanticModel)doc.GetSemanticModel(); 
var root = (CompilationUnitSyntax)doc.GetSyntaxRoot(); 

SyntaxNode parent = null; 
var oldStatementNode = (parent as ExpressionStatementSyntax); //some SyntaxNode in the tree 
var oldExpressionNode = oldStatementNode.Expression; 
var newExpressionNode = Syntax.ParenthesizedExpression(oldExpressionNode); 
var newRootNode = root.ReplaceNode(oldExpressionNode, newExpressionNode); 

doc = doc.UpdateSyntaxRoot(newRootNode); 
semanticModel = (SemanticModel)doc.GetSemanticModel(); 
Cuestiones relacionadas