Groovy: как получить статически выведенный тип возврата из AST
Я использую Groovy, чтобы позволить пользователям создавать сценарии и настраивать определенные части моего Java-приложения. Я использую статическую компиляцию всех пользовательских скриптов.
Мой вопрос: если мой код ожидает, например, получить значение типа boolean в результате пользовательского сценария, есть ли способ проверить, будет ли предоставленный пользовательский сценарий всегда возвращать булево значение без фактического выполнения сценария? Другими словами, как я могу получить доступ к результатам вывода типов, выполняемых статическим компилятором groovy? Я хотел бы иметь возможность сказать пользователю "эй, ваш сценарий не всегда возвращает логическое значение", пока он редактирует содержимое сценария.
2 ответа
Прямого пути нет, но это возможно. Boolean особенно сложен, так как компилятор с радостью применяет все виды приведений типов (например, преобразует int в boolean без жалоб). У меня была точно такая же проблема, и я сделал следующие шаги:
-
ASTTransformation для установки типа возвращаемого значения в логическое значение(не требуется, был артефактомполуработающейболее ранней итерации) - ASTTransformation, чтобы материализовать все возвратные заявления
- TypeCheckingExtension, чтобы посетить ReturnStatements и убедиться, что они имеют тип boolean
- 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
(тип по АСТ). Вызов addStaticTypeError
по не булеву типу.
Для 4:
простираться StaticTypesTransformation
Override newVisitor
и создать новый StaticTypeCheckingVisitor
и позвонить addTypeCheckingExtension
на него, чтобы добавить свой TypeCheckingExtension
GitHub Project
https://github.com/MeneDev/groovy-dsl-building-blocks-enforce-return-type
Это может даже быть многоразовым в качестве зависимости;)
Не с "Типичным" groovy- это разница между типизацией groovy во время исполнения и статической типизацией java во время компиляции.
Например, будет ли следующий метод возвращать логическое значение?
def value(v) {
return v;
}
В версии 2.0, однако, есть аннотация @CompileStatic, которая, я думаю, заставит знать все типы во время компиляции. Не уверен, как бы вы принудительно включили это "Вкл" для кода скрипта вашего клиента.