java - Groovy:如何从 AST 获取静态推断的返回类型
问题描述
我正在使用 Groovy 允许用户编写脚本并自定义我的 Java 应用程序的某些部分。我正在使用所有用户提供的脚本的静态编译。
我的问题是:如果我的代码期望收到例如 boolean 类型的值作为用户脚本的结果,有没有办法让我检查提供的用户脚本是否总是返回布尔值而不实际执行脚本?换句话说,我如何访问静态 groovy 编译器执行的类型推断的结果?我希望能够在用户编辑脚本内容时告诉用户“嘿,您的脚本并不总是返回布尔值”。
解决方案
没有直接的方法,但它是可能的。布尔值特别难,因为编译器会很高兴地应用各种类型强制(例如,将 int 转换为布尔值而不会抱怨)。我遇到了完全相同的问题并执行了以下步骤:
ASTTransformation 将返回类型设置为布尔值(不是必需的,是早期迭代的一半工作的产物)- ASTTransformation 用于计量所有返回语句
- TypeCheckingExtension 访问 ReturnStatements 并验证它们是布尔类型
- ASTTransformation 使用 TypeCheckingExtension 执行静态类型转换
对于 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
GitHub 项目
https://github.com/MeneDev/groovy-dsl-building-blocks-enforce-return-type
它甚至可以作为依赖项重用;)
推荐阅读
- javascript - Javascript Date() 返回错误的日期
- django - 如何像在 Django Admin 中一样在表单中创建外键链接字段?
- python - 我正在尝试使用函数修改列表中的值并失败
- php - 转换转义字符 PHP
- laravel - 从同一域/子域组合运行网站和 API 的正确方法是什么
- c++ - 类型检测器`hasNestedType`没有编译?
- python - SQLAlchemy order_by 日期编辑和日期创建列?
- performance - Godot 3中如何去掉图形
- tfrecord - TensorFlow 对象检测 API tfrecord
- python - 将对象传递到类实例内的选项卡中