【问题标题】:"ArgumentException: Syntax node is not within Syntax tree" when using semantic model in roslyn“ArgumentException:语法节点不在语法树中”在 roslyn 中使用语义模型时
【发布时间】:2015-03-01 19:46:54
【问题描述】:

我正在使用 Roslyn 收集方法中的所有方法调用,并在该方法的相应测试方法中将它们替换为 shim。问题是,尽管使用项目的所有引用和语法树适当地初始化了编译对象,它还是会抛出一个 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);
            }
        }
    }

这就是我使用语义模型为所有调用生成填充程序的方式:

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

第二个代码 sn-p 中突出显示的区域是发生异常并且执行流向 catch 块的地方。有什么问题,我在这里错过了什么?

【问题讨论】:

    标签: c# roslyn


    【解决方案1】:

    为什么要解析自己的文件并构建自己的编译?如果您已经有 WorkspaceSolutionProjects 和 Documents,您可以使用 document.GetSyntaxTreeAsync()document.GetSemanticModelAsync()document.Project.GetCompilationAsync() 来获得这些。

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

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

    无论如何,我怀疑您的代码存在问题,因为您存储的语义模型与您在syntaxTreesOfDocuments 中的 first 语法树相对应,但您从未添加 @ 987654331@(您拥有的 code 字符串的树)添加到该列表,因此它不是编译的一部分,也绝对不是 SemanticModel 操作的树。

    【讨论】:

    • 我在您的回答中得到第一点,并将其纳入。但是,关于第三点(您在我的代码中提到了这个问题),我已经获得了始终作为编译一部分的代码的语义模型。在 if 子句中,我从项目中获得了编译,在 else 子句中,我从提供的代码字符串中生成了编译。因此,我仍然无法理解问题中提到的异常的原因。
    • 语义模型绑定到特定的语法树。如果您要为不同的树请求语义信息,则需要获取它的语义模型。异常意味着您从一棵树传递一个节点,但语义模型最初是从另一棵树创建的。归根结底,只需调试您的代码——您可能只是在某处传递了错误的值。
    猜你喜欢
    • 2015-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多