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 而不会抱怨)。我遇到了完全相同的问题并执行了以下步骤:
ASTTransformation 以将 return 类型设置为布尔值(不需要,是早期迭代的半成品)
- 对所有 return 语句进行实体化的 ASTTransformation
- TypeCheckingExtension 访问 ReturnStatements 并验证它们是布尔类型
- ASTTransformation 以使用 TypeCheckingExtension 执行静态类型转换
对于 1:
扩展 ClassCodeVisitorSupport
,在 visitMethod
中确定您想要 return 布尔值的所有方法(例如检查匹配的命名约定)
将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
它甚至可以作为依赖项重复使用 ;)
我正在使用 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 而不会抱怨)。我遇到了完全相同的问题并执行了以下步骤:
ASTTransformation 以将 return 类型设置为布尔值(不需要,是早期迭代的半成品)- 对所有 return 语句进行实体化的 ASTTransformation
- TypeCheckingExtension 访问 ReturnStatements 并验证它们是布尔类型
- ASTTransformation 以使用 TypeCheckingExtension 执行静态类型转换
对于 1:
扩展 ClassCodeVisitorSupport
,在 visitMethod
中确定您想要 return 布尔值的所有方法(例如检查匹配的命名约定)
将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
它甚至可以作为依赖项重复使用 ;)