我需要解析用户编写的C#代码片段,并用方法调用替换本地未定义的所有变量.即
public class Foo { public dynamic Bar() { return Math.Min(x + width, maxWidth); } }
必须成为:
public class Foo { public dynamic Bar() { return Math.Min(Resolve("x") + Resolve("width"), Resolve("maxWidth")); } }
我正在使用Microsoft.CodeAnalysis.CSharp和CSharpSyntaxTree来检查字符串,但它没有给我足够的信息来执行替换.或者如果确实如此,我不知道在哪里寻找它.我已粘贴下面的SyntaxTree布局.所有变量都以IdentifierName节点的形式出现,但我不知道如何区分不同的IdentifierNames.然后去哪儿?
CompilationUnit[0..99) { code: public class Foo\n{\n public dynamic Bar()\n {\n return Math.Min(x + width, maxWidth);\n }\n} tokens: EndOfFileToken[] nodes{ ClassDeclaration[0..99) { code: public class Foo\n{\n public dynamic Bar()\n {\n return Math.Min(x + width, maxWidth);\n }\n} tokens: PublicKeyword[public ] ClassKeyword[class ] IdentifierToken[Foo\n] OpenBraceToken[{\n] CloseBraceToken[}] nodes{ MethodDeclaration[21..98) { code: public dynamic Bar()\n {\n return Math.Min(x + width, maxWidth);\n }\n tokens: PublicKeyword[ public ] IdentifierToken[Bar] nodes{ IdentifierName[30..38) { code: dynamic tokens: IdentifierToken[dynamic ] } ParameterList[41..45) { code: ()\n tokens: OpenParenToken[(] CloseParenToken[)\n] } Block[45..98) { code: {\n return Math.Min(x + width, maxWidth);\n }\n tokens: OpenBraceToken[ {\n] CloseBraceToken[ }\n] nodes{ ReturnStatement[50..93) { code: return Math.Min(x + width, maxWidth);\n tokens: ReturnKeyword[ return ] SemicolonToken[;\n] nodes{ InvocationExpression[61..90) { code: Math.Min(x + width, maxWidth) nodes{ SimpleMemberAccessExpression[61..69) { code: Math.Min tokens: DotToken[.] nodes{ IdentifierName[61..65) { code: Math tokens: IdentifierToken[Math] } IdentifierName[66..69) { code: Min tokens: IdentifierToken[Min] } } } ArgumentList[69..90) { code: (x + width, maxWidth) tokens: OpenParenToken[(] CommaToken[, ] CloseParenToken[)] nodes{ Argument[70..79) { code: x + width nodes{ AddExpression[70..79) { code: x + width tokens: PlusToken[+ ] nodes{ IdentifierName[70..72) { code: x tokens: IdentifierToken[x ] } IdentifierName[74..79) { code: width tokens: IdentifierToken[width] } } } } } Argument[81..89) { code: maxWidth nodes{ IdentifierName[81..89) { code: maxWidth tokens: IdentifierToken[maxWidth] } } } } } } } } } } } } } } } } }
Thomas Leves.. 7
我认为你需要使用语义模型.这是一个(非常基本的)示例,显示如何查找未解析的符号:
var tree = CSharpSyntaxTree.ParseFile(fileName); var root = tree.GetRoot(); var refs = new MetadataReference[] { new MetadataFileReference(@"C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll", new MetadataReferenceProperties(MetadataImageKind.Assembly)) }; var compilation = CSharpCompilation.Create("testRoslyn", new[] { tree }, refs); var model = compilation.GetSemanticModel(tree); var unknownSymbols = from node in root.DescendantNodes() where node.IsKind(SyntaxKind.IdentifierName) let symbolInfo = model.GetSymbolInfo(node) where symbolInfo.Symbol == null && !symbolInfo.CandidateSymbols.Any() select node;
从那里你可以用Resolve(name)
.替换节点.