我正在使用 Groovy 允许用户编写脚本并自定义我的 Java 应用程序的某些部分。我正在使用所有用户提供的脚本的静态编译。
我的问题是:如果我的代码期望收到例如 boolean 类型的值作为用户脚本的结果,有没有办法让我检查提供的用户脚本是否总是返回布尔值而不实际执行脚本?换句话说,我如何访问静态 groovy 编译器执行的类型推断的结果?我希望能够在用户编辑脚本内容时告诉用户“嘿,您的脚本并不总是返回布尔值”。
我正在使用 Groovy 允许用户编写脚本并自定义我的 Java 应用程序的某些部分。我正在使用所有用户提供的脚本的静态编译。
我的问题是:如果我的代码期望收到例如 boolean 类型的值作为用户脚本的结果,有没有办法让我检查提供的用户脚本是否总是返回布尔值而不实际执行脚本?换句话说,我如何访问静态 groovy 编译器执行的类型推断的结果?我希望能够在用户编辑脚本内容时告诉用户“嘿,您的脚本并不总是返回布尔值”。
没有直接的方法,但它是可能的。布尔值特别难,因为编译器会很高兴地应用各种类型强制(例如,将 int 转换为布尔值而不会抱怨)。我遇到了完全相同的问题并执行了以下步骤:
对于 1:
扩展ClassCodeVisitorSupport
,在visitMethod
识别你想要返回布尔值的所有方法(例如检查匹配的命名约定)
设置returnType
为MethodNode
_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
https://github.com/MeneDev/groovy-dsl-building-blocks-enforce-return-type
它甚至可以作为依赖项重用;)
不是“典型的”groovy——它是 groovy 的运行时类型和 java 的编译时静态类型之间的区别。
例如,以下方法是否会返回布尔值?
def value(v) {
return v;
}
然而,在 2.0 版中,有一个 @CompileStatic 注释,我认为它会强制在编译时知道所有类型。不过,不确定如何为客户的脚本代码强制“开启”。