我正在使用Groovy允许用户编写脚本和自定义Java应用程序的某些部分。我正在使用所有用户提供的脚本的静态编译。
我的问题是:如果我的代码期望收到例如布尔类型的值作为用户脚本的结果,我有什么办法可以检查提供的用户脚本是否总是返回布尔值而不实际执行脚本?换句话说,如何访问静态 groovy 编译器执行的类型推断的结果?我希望能够在用户编辑脚本内容时告诉用户"嘿,您的脚本并不总是返回布尔值"。
没有直截了当的方法,但这是可能的。布尔值尤其困难,因为编译器会很乐意应用各种类型强制(例如,将 int 转换为布尔值而不抱怨(。我遇到了完全相同的问题,并执行了以下步骤:
-
ASTTransformation 将返回类型设置为布尔值(不是必需的,是半工作早期迭代的工件( - ASTTransform将所有返回报表计量化
- 类型检查扩展,以访问返回语句并验证它们是否为布尔类型
- ASTTransformation 使用 TypeCheckingExtension 执行静态类型转换
对于 1:
扩展ClassCodeVisitorSupport
,visitMethod
标识要返回布尔值的所有方法(例如,检查匹配的命名约定(
将MethodNode
的returnType
设置为ClassHelper.boolean_TYPE
对于 2:
对于与上述相同的方法,调用org.codehaus.groovy.classgen.ReturnAdder.visitMethod
对于 3:
扩展AbstractTypeCheckingExtension
,覆盖afterVisitMethod
。此时,AbstractTypeCheckingExtension
将推断出方法内所有表达式的下限。使用ClassCodeVisitorSupport
子类并覆盖visitReturnStatement
。使用getType(statement.expression)
获取推断的类型。请注意,这可能与statement.expression.type
(根据 AST 的类型(不同。在非布尔类型上调用addStaticTypeError
。
对于 4:
扩展StaticTypesTransformation
覆盖newVisitor
并创建一个新StaticTypeCheckingVisitor
,并对其调用addTypeCheckingExtension
以添加TypeCheckingExtension
GitHub 项目
https://github.com/MeneDev/groovy-dsl-building-blocks-enforce-return-type
它甚至可以作为依赖项重用;)
不是"Typical"groovy——这是groovy的运行时类型和Java的编译时静态类型之间的区别。
例如,以下方法是否将返回布尔值?
def value(v) {
return v;
}
但是,在 2.0 版中,有一个@CompileStatic注释,我认为它会强制在编译时知道所有类型的注释。 不确定如何为客户端的脚本代码强制使用"开"。