SemanticModel GetSymbolInfo (). Символ равен нулю в созданном коде, но не в разобранном коде - PullRequest
0 голосов
/ 14 апреля 2020

Учитывая следующий код

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

I wi sh, чтобы получить ссылку на i в i=0, а затем запросить информацию о его символе, чтобы увидеть, где он был объявлен, если угодно ! Чтобы сделать это, используя приведенную выше строку, вы должны сделать следующее

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 успешно присвоено значение. Однако в моей программе мне нужно выполнить анализ semanti c на основе существующего синтаксического дерева. Однако по какой-то причине, если вышеприведенное дерево создано вручную с помощью 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 должны быть какие-то метаданные, которые делают эту работу хорошей , но не плохой

1 Ответ

0 голосов
/ 14 апреля 2020

Фактически, существует разница между хорошими и плохими деревьями - вместо того, чтобы вместо того, чтобы оборачивать переменную i в GlobalStatement / LocalDeclarationStatement, она следует обернуть как FieldDeclaration.

...