c# - 在 roslyn 中使用语义模型时出现 "ArgumentException: Syntax node is not within Syntax tree"

标签 c# roslyn

我正在使用 Roslyn 收集方法中所有方法的调用,并在该方法的相应测试方法中用垫片替换它们。问题在于,尽管使用项目的所有引用和语法树适本地初始化了编译对象,它仍会抛出一个 ArgumentException,表示“语法节点不在语法树中”。

这是我用来初始化语义模型的代码:

   public TestMethodCodeGenerator(string code, Project project = null)
    {
        if (!string.IsNullOrWhiteSpace(code))
        {
            var syntaxTree = CSharpSyntaxTree.ParseText(code);

            if (null != project)
            {
                var syntaxTreesOfDocumentsInProject = new List<SyntaxTree>();
                foreach (var document in project.Documents)
                {
                    syntaxTreesOfDocumentsInProject.Add(CSharpSyntaxTree.ParseFile(document.FilePath));
                }

                var compilation = CSharpCompilation.Create("Demo").AddReferences(project.MetadataReferences).AddSyntaxTrees(syntaxTreesOfDocumentsInProject);
                this.semanticModel = compilation.GetSemanticModel(syntaxTreesOfDocumentsInProject[0]);
                }
            }
            else 
            {                
                var compilation = CSharpCompilation.Create("Demo").AddSyntaxTrees(syntaxTree);
                this.semanticModel = compilation.GetSemanticModel(syntaxTree);
            }
        }
    }

这就是我使用 semanticModel 为所有调用生成垫片的方式:

private string PopulateMethodBodyWithShims(MethodDeclarationSyntax methodDeclarationSyntax)
    {
        if (null != methodDeclarationSyntax)
        {
            var stringBuilder = new StringBuilder();
            var methodBlock = methodDeclarationSyntax.Body;
            foreach (var statement in methodBlock.Statements)
            {
                var invocationSyntax = this.ExtractMethodInvocationSyntaxFromStatement(statement);
                if (null != invocationSyntax)
                {
                    var call = invocationSyntax.Expression as MemberAccessExpressionSyntax;
                    if (null != call)
                    {
                        try
                        {
                            IMethodSymbol methodSymbol;
                            **methodSymbol = this.semanticModel.GetSymbolInfo(call).Symbol as IMethodSymbol;**
                            if (null != methodSymbol)
                            {
                                var shimMethod = this.GenerateShimMethod(methodSymbol);
                                stringBuilder.AppendLine(GeneratedTestClassConstants.IndentationSpaceToken + GeneratedTestClassConstants.IndentationSpaceToken + shimMethod);
                            }
                        }
                        catch (ArgumentException ex)
                        {
                            ////This exception can be thrown if the syntax node is not within the syntax tree
                            var message = ex.Message;
                            throw new ArgumentException(message + " : " + call);
                        }                           
                    }
                }
            }
.
.
.

第二个代码片段中突出显示的区域是异常发生的地方,执行流向 catch block 。问题是什么,我在这里错过了什么?

最佳答案

为什么要解析自己的文件并构建自己的编译?如果您已经有一个包含SolutionProjectDocumentWorkspace,您可以只使用document.GetSyntaxTreeAsync()document.GetSemanticModelAsync()document.Project.GetCompilationAsync() 获取这些内容。

您似乎正在为您拥有的一些新代码添加语法树,但您可以通过添加该语法树并获取新的 Project 来实现。例如

project = project.AddDocument("generatedfile", code).Project;

无论如何,我怀疑你的代码的问题在于你存储的语义模型对应于你在 syntaxTreesOfDocuments 中的第一个语法树,但是您永远不会将 syntaxTree (您拥有的 code 字符串的树)添加到该列表中,因此它不是编译的一部分,而且绝对不是那棵树SemanticModel 操作。

关于c# - 在 roslyn 中使用语义模型时出现 "ArgumentException: Syntax node is not within Syntax tree",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27759766/

相关文章:

c# - 如何调用所有事件处理程序订阅者并获得他们的结果?

c# - 根据 web.config 检查 sqlce 数据库是否存在

c# - MSBuildWorkspace.Create 似乎无法正常工作

c# - Roslyn 没有引用 System.Runtime

javascript - 将字符串从 javascript 代码发布到服务器上的 ApiController

c# - Xamarin.Android : How to capture Button events defined in the OnClick XML attribute?

c# - 处理嵌套属性值

c# - 为什么 roslyn 在放入数组时将对象包装在结构中?

c# - Roslyn SDK 预览中的代码格式化

c# - Roslyn 的 GetTypeByMetadataName() 和通用类型