Java Groovy:如何从AST获取静态推断的返回类型
我使用Groovy允许用户编写和自定义Java应用程序的某些部分。我正在使用所有用户提供的脚本的静态编译 我的问题是:如果我的代码期望收到一个布尔类型的值作为用户脚本的结果,那么我是否可以检查提供的用户脚本是否总是返回布尔值而不实际执行脚本?换句话说,如何访问静态groovy编译器执行的类型推断的结果?我希望能够在用户编辑脚本内容时告诉用户“嘿,您的脚本并不总是返回布尔值”。与“典型”groovy不同——这是groovy的运行时类型和java的编译时静态类型之间的区别 例如,下面的方法是否将返回布尔值Java Groovy:如何从AST获取静态推断的返回类型,java,groovy,type-systems,static-compilation,Java,Groovy,Type Systems,Static Compilation,我使用Groovy允许用户编写和自定义Java应用程序的某些部分。我正在使用所有用户提供的脚本的静态编译 我的问题是:如果我的代码期望收到一个布尔类型的值作为用户脚本的结果,那么我是否可以检查提供的用户脚本是否总是返回布尔值而不实际执行脚本?换句话说,如何访问静态groovy编译器执行的类型推断的结果?我希望能够在用户编辑脚本内容时告诉用户“嘿,您的脚本并不总是返回布尔值”。与“典型”groovy不同——这是groovy的运行时类型和java的编译时静态类型之间的区别 例如,下面的方法是否将返回
def value(v) {
return v;
}
然而,在2.0版中,有一个@CompileStatic注释,我认为它将强制所有类型在编译时都知道。但是,不确定您将如何为客户端的脚本代码强制启用此选项。没有直接的方法,但这是可能的。布尔运算尤其困难,因为编译器会乐于应用各种类型的协同运算(例如,毫无怨言地将int转换为布尔运算)。我遇到了完全相同的问题,并执行了以下步骤:
ClassCodeVisitorSupport
,在visitMethod
中识别所有要返回布尔值的方法(例如检查匹配的命名约定)
将MethodNode
的returnType
设置为ClassHelper.boolean\u TYPE
对于2:
对于与上面相同的方法,请调用org.codehaus.groovy.classgen.ReturnAdder.visitMethod
对于3:
扩展AbstractTypeCheckingExtension
,覆盖afterVisitMethod
。此时,AbstractTypeCheckingExtension
将推断出方法中所有表达式的下限。使用ClassCodeVisitorSupport
子类并重写visitReturnStatement
。使用getType(statement.expression)
获取推断的类型。请注意,这可能不同于语句.expression.type
(类型根据AST)。对非布尔类型调用addStaticTypeError
对于4:
扩展静态类型转换格式
覆盖newVisitor
并创建一个新的StaticTypeCheckingVisitor
并在其上调用addTypeCheckingExtension
以添加您的TypeCheckingExtension
GitHub项目
它甚至可以作为依赖项重用;) 是的,这正是我们所做的。您可以将静态编译添加为AST定制器,这非常有效。我们面临的问题是如何访问分析结果,即带类型注释的AST。您是否可以要求用户使用其代码实现特定的接口?如果他没有返回一个布尔值,那么它应该无法编译。。。如果用户代码更像是一个“脚本”,那么在为他编译界面之前,您可以强制他的脚本实现一个界面。让用户自己实现一个界面(从语法上)显然是太难了。一种选择是在编译用户代码之前在其周围包装一个方法签名。但是,用户无法在脚本中定义帮助函数,因为方法不能嵌套在Groovy AFAIK中。AST转换比字符串串联更简单,但也可以完成这项工作。最干净的选择仍然是保持脚本不变并分析AST。问题是,我不知道如何在Groovy编译器API中做到这一点。感谢您的详细回复!我将尝试实施你的方法。在github上有这个例子肯定会有帮助。唉,关于Groovy的这些方面的信息在网上几乎找不到,包括一些尝试和错误。我会尽力的!好了: