【发布时间】: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