9

我正在尝试修改语法树,然后更新语义模型。这是我到目前为止所拥有的:

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"

如果我在调用之前尝试调用semanticModel = compilation.GetSemanticModel(tree);甚至进行新的编译- 相同的异常。treeGetTypeInfo()

那么我该如何更新SemanticModel呢?(当然我可以得到修改后的源代码并从头开始做所有事情,但我想有更有效的方法)。

我敢肯定,我在这里遗漏了一些明显的东西,也许在某处创建了一个新的语法树?

4

1 回答 1

15

Roslyn 类型是不可变的,所以你需要为SyntaxTree你的 构造一个 new newRootNode,然后调用compilation.UpdateSyntaxTree来获取一个 new Compilation,然后你可以调用newCompilation.GetSemanticModel(newTree)来获取一个 new SemanticModel

考虑升级到服务级别并改用 ISolution。就像是:

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();
于 2012-08-28T23:05:41.913 回答