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

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);或什至在调用tree之前使用GetTypeInfo()进行新的编译-同样的异常(exception)。

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

我确定这里可能缺少明显的东西,也许某个地方创建了新的语法树?

最佳答案

Roslyn类型是不可变的,因此您需要为自己的SyntaxTree构造一个新的newRootNode,然后调用compilation.UpdateSyntaxTree以获得一个新的Compilation,然后可以调用newCompilation.GetSemanticModel(newTree)以获得一个新的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();

关于c# - 修改语法树,然后获取更新的语义模型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12164769/

10-13 06:26