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