Groovy:如何从 AST 静态推断 return 类型

Groovy: How to get statically inferred return type from AST

我正在使用 Groovy 来允许用户编写脚本和自定义我的 Java 应用程序的某些部分。我正在使用所有用户提供的脚本的静态编译。

我的问题是:如果我的代码期望收到例如作为用户脚本结果的 boolean 类型的值,我有什么方法可以检查提供的用户脚本是否总是 return 布尔值而不实际执行脚本?换句话说,我如何访问静态 groovy 编译器执行的类型推断的结果?我希望能够在用户编辑脚本内容时告诉他们 "hey, your script does not always return a boolean"。

不适用于 "Typical" groovy--这是 groovy 的运行时类型和 java 的编译时静态类型之间的区别。

例如,下面的方法是return布尔值吗?

def value(v) {
    return v;
}

然而,在 2.0 版中,有一个 @CompileStatic 注释,我认为它会强制在编译时知道所有类型。不确定如何为您的客户的脚本代码强制执行此 "On"。

没有直截了当的方法,但有可能。布尔值特别难,因为编译器会很乐意应用各种类型强制转换(例如,将 int 转换为 boolean 而不会抱怨)。我遇到了完全相同的问题并执行了以下步骤:

  1. ASTTransformation 以将 return 类型设置为布尔值(不需要,是早期迭代的半成品)
  2. 对所有 return 语句进行实体化的 ASTTransformation
  3. TypeCheckingExtension 访问 ReturnStatements 并验证它们是布尔类型
  4. ASTTransformation 以使用 TypeCheckingExtension 执行静态类型转换

对于 1:

扩展 ClassCodeVisitorSupport,在 visitMethod 中确定您想要 return 布尔值的所有方法(例如检查匹配的命名约定)

MethodNodereturnType设为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

它甚至可以作为依赖项重复使用 ;)