C# CodeAnalysis - 表达式的结构
C# CodeAnalysis - Structure of expressions
我想在 VS2013 的 C# (.NET 4.5) 脚本中做一个简单的代码替换。应重写每个 @GetIt
调用,以便将其封装在 lambda 函数中:
new MyClass(@GetInt("a") * @GetInt("b"));
变成
new MyClass( x => (x.GetInt("a") * x.GetInt("b")) )
我安装了 Roslyn 的 CodeAnalysis 来解析脚本。我使用以下调用获取所有带有 @GetInt
标识符的令牌:
var getters = CSharpSyntaxTree.ParseText("new MyClass(@GetInt("a") * @GetInt("b"));")
.GetRoot().DescendantTokens().OfType<SyntaxToken>()
.Where(x => x.Text.Equals("@GetInt"));
对于 @GetInt
作为 MyClass
构造函数的一个简单参数,它工作正常并且使用 getters[i].Parent.Parent.Parent.Parent
我正确地到达了构造函数的 MethodDeclarationSyntax
节点。
但是,如顶部的示例中那样添加乘法,第二个 @GetInt
的标记将 * GetInt("b")
声明为它的父项(但是它已经是 MethodDeclarationSyntax
,而不是参数节点)并遍历回其父节点导致 CompilationUnitSyntax
这是根!
这样,我就无法获得有关语法树中第二个 @GetInt
位置的信息。因此,如果没有丢失的信息,则无法进行替换。
不使用前缀@
的情况下我已经检查过了,但是结果是一样的。有人可以告诉我我做错了什么吗?
SOLUTION 正如 JoshVarty 在他的评论之一中所建议的那样:在 NuGet 包中禁用脚本的代码分析之前,我必须使用一种解决方法。首先,我把 string script = "..."
装饰成
var decoratedScript = "class MYCLASS { void METHOD() {\n" + script + "\n} }";
@GetInt
重写完成后,我把添加的装饰去掉
默认情况下 ParseText()
希望您传递典型的 C# 文档。 (由 using 语句、命名空间、类型等组成的东西)
如果您想解析单个表达式,可以使用 CSharpParseOptions
来实现:
var parseOptions = CSharpParseOptions.Default;
parseOptions = parseOptions.WithKind(SourceCodeKind.Script); //We're going to be passing individual expressions in.
var getters = CSharpSyntaxTree.ParseText(@"new MyClass(@GetInt(""a"") * @GetInt(""b""));", parseOptions)
.GetRoot().DescendantTokens().OfType<SyntaxToken>()
.Where(x => x.Text.Equals("@GetInt"));
当我使用它时,我得到了 @GetInt
作为 BinaryExpressionSyntax
(乘法)的子项的两次调用。
您可以通过以下方式看到树最初为您自己解析错误:
var tree = CSharpSyntaxTree.ParseText(@"new MyClass(@GetInt(""a"") * @GetInt(""b""));");
var errs = tree.GetDiagnostics().Where(n => n.Severity == DiagnosticSeverity.Error);
编辑 真的很抱歉,RTM 的脚本 API 似乎已被删除。我能想到的唯一解决方法是将每个语句包装在 class 和一个方法中,直到它再次开始工作。
它出现在 http://sourceroslyn.io 上的原因是它基于当前的母版,他们正在重新添加它。
我想在 VS2013 的 C# (.NET 4.5) 脚本中做一个简单的代码替换。应重写每个 @GetIt
调用,以便将其封装在 lambda 函数中:
new MyClass(@GetInt("a") * @GetInt("b"));
变成
new MyClass( x => (x.GetInt("a") * x.GetInt("b")) )
我安装了 Roslyn 的 CodeAnalysis 来解析脚本。我使用以下调用获取所有带有 @GetInt
标识符的令牌:
var getters = CSharpSyntaxTree.ParseText("new MyClass(@GetInt("a") * @GetInt("b"));")
.GetRoot().DescendantTokens().OfType<SyntaxToken>()
.Where(x => x.Text.Equals("@GetInt"));
对于 @GetInt
作为 MyClass
构造函数的一个简单参数,它工作正常并且使用 getters[i].Parent.Parent.Parent.Parent
我正确地到达了构造函数的 MethodDeclarationSyntax
节点。
但是,如顶部的示例中那样添加乘法,第二个 @GetInt
的标记将 * GetInt("b")
声明为它的父项(但是它已经是 MethodDeclarationSyntax
,而不是参数节点)并遍历回其父节点导致 CompilationUnitSyntax
这是根!
这样,我就无法获得有关语法树中第二个 @GetInt
位置的信息。因此,如果没有丢失的信息,则无法进行替换。
不使用前缀@
的情况下我已经检查过了,但是结果是一样的。有人可以告诉我我做错了什么吗?
SOLUTION 正如 JoshVarty 在他的评论之一中所建议的那样:在 NuGet 包中禁用脚本的代码分析之前,我必须使用一种解决方法。首先,我把 string script = "..."
装饰成
var decoratedScript = "class MYCLASS { void METHOD() {\n" + script + "\n} }";
@GetInt
重写完成后,我把添加的装饰去掉
默认情况下 ParseText()
希望您传递典型的 C# 文档。 (由 using 语句、命名空间、类型等组成的东西)
如果您想解析单个表达式,可以使用 CSharpParseOptions
来实现:
var parseOptions = CSharpParseOptions.Default;
parseOptions = parseOptions.WithKind(SourceCodeKind.Script); //We're going to be passing individual expressions in.
var getters = CSharpSyntaxTree.ParseText(@"new MyClass(@GetInt(""a"") * @GetInt(""b""));", parseOptions)
.GetRoot().DescendantTokens().OfType<SyntaxToken>()
.Where(x => x.Text.Equals("@GetInt"));
当我使用它时,我得到了 @GetInt
作为 BinaryExpressionSyntax
(乘法)的子项的两次调用。
您可以通过以下方式看到树最初为您自己解析错误:
var tree = CSharpSyntaxTree.ParseText(@"new MyClass(@GetInt(""a"") * @GetInt(""b""));");
var errs = tree.GetDiagnostics().Where(n => n.Severity == DiagnosticSeverity.Error);
编辑 真的很抱歉,RTM 的脚本 API 似乎已被删除。我能想到的唯一解决方法是将每个语句包装在 class 和一个方法中,直到它再次开始工作。
它出现在 http://sourceroslyn.io 上的原因是它基于当前的母版,他们正在重新添加它。