【问题标题】:SemanticModel GetSymbolInfo().Symbol is Null in Constructed Code but not Parsed CodeSemanticModel GetSymbolInfo().Symbol 在构造代码中为空,但在解析代码中为空
【发布时间】:2020-04-14 08:49:18
【问题描述】:

给定以下代码

var forText = "int i;for(i=0;i<3;i++){}";

我希望在i=0 中获取对i 的引用,然后请求其符号信息以查看它的声明位置(如果在任何地方)!要使用上面的字符串执行此操作,您将执行以下操作

var forText = "int i;for(i=0;i<3;i++){}";
var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
var options = CSharpParseOptions.Default.WithKind(SourceCodeKind.Script);

var goodTree = CSharpSyntaxTree.ParseText(forText, options);
var goodCompilation = CSharpCompilation.CreateScriptCompilation("GoodCompilation", syntaxTree: goodTree, references: new[] { mscorlib });
var goodModel = goodCompilation.GetSemanticModel(goodTree);

var goodLeft = goodTree.GetRoot().DescendantNodes().OfType<AssignmentExpressionSyntax>().First().Left;

var goodSymbol = goodModel.GetSymbolInfo(goodLeft).Symbol;

这可以正常工作,并且goodSymbol 已成功分配值。但是,在我的程序中,我需要做的是对现有的语法树进行语义分析。然而,由于某种原因,如果上面的树是通过SyntaxFactory 节点手动创建的,GetSymbolInfo().Symbol 返回null

//using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;

var manualTree = CompilationUnit()
    .WithMembers(
        List(new MemberDeclarationSyntax[] {
            GlobalStatement(
                LocalDeclarationStatement(
                    VariableDeclaration(
                        PredefinedType(Token(SyntaxKind.IntKeyword)),
                        SingletonSeparatedList(
                            VariableDeclarator("i")
                        )
                     )
                ).NormalizeWhitespace()
            ),
            GlobalStatement(
                ForStatement(
                    null,
                    SingletonSeparatedList<ExpressionSyntax>(
                        AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                            IdentifierName("i"),
                            LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0))
                        )
                    ),
                    BinaryExpression(
                        SyntaxKind.LessThanExpression,
                        IdentifierName("i"),
                        LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(3))
                    ),
                    SingletonSeparatedList<ExpressionSyntax>(
                        PostfixUnaryExpression(SyntaxKind.PostIncrementExpression,
                            IdentifierName("i")
                        )
                    ),
                    Block()
                )
            )}
        ));

var badTree = CSharpSyntaxTree.Create(manualTree, CSharpParseOptions.Default.WithKind(SourceCodeKind.Script));

var badCompilation = CSharpCompilation.CreateScriptCompilation("BadCompilation", syntaxTree: badTree, references: new[] { mscorlib });
var badModel = badCompilation.GetSemanticModel(badTree);

var badLeft = badTree.GetRoot().DescendantNodes().OfType<AssignmentExpressionSyntax>().First().Left;

var badSymbol = badModel.GetSymbolInfo(badLeft).Symbol;

两棵树中的节点和标记看起来完全一样; goodTree 中似乎没有任何节点在多个地方重复使用(每个 SyntaxNode 都有一个唯一的对象引用) - 解析的树与构造的树有根本的不同,但我没有想法什么!两棵树都具有完全相同的字符串表示,因此必须在 SyntaxTree 或某些 SyntaxNode 对象上存在某种元数据,这使得它在但不是坏的情况下工作

【问题讨论】:

    标签: c# roslyn roslyn-code-analysis


    【解决方案1】:

    事实上,goodbad 树之间是有区别的——而不是将变量 i 包装为 GlobalStatement/LocalDeclarationStatement ,它应该被包装成FieldDeclaration

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-27
      • 2011-08-18
      • 1970-01-01
      • 1970-01-01
      • 2018-01-13
      • 1970-01-01
      相关资源
      最近更新 更多