首页 > 解决方案 > Groovy:如何从 AST 获取静态推断的返回类型

问题描述

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

我的问题是:如果我的代码期望收到例如 boolean 类型的值作为用户脚本的结果,有没有办法让我检查提供的用户脚本是否总是返回布尔值而不实际执行脚本?换句话说,我如何访问静态 groovy 编译器执行的类型推断的结果?我希望能够在用户编辑脚本内容时告诉用户“嘿,您的脚本并不总是返回布尔值”。

标签: javagroovytype-systemsstatic-compilation

解决方案


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

  1. ASTTransformation 将返回类型设置为布尔值(不是必需的,是早期迭代的一半工作的产物)
  2. ASTTransformation 用于计量所有返回语句
  3. TypeCheckingExtension 访问 ReturnStatements 并验证它们是布尔类型
  4. ASTTransformation 使用 TypeCheckingExtension 执行静态类型转换

对于 1:

扩展ClassCodeVisitorSupport,在visitMethod识别你想要返回布尔值的所有方法(例如检查匹配的命名约定)

设置returnTypeMethodNode_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

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


推荐阅读