Groovy: как получить статически выведенный тип возврата из AST

Я использую Groovy, чтобы позволить пользователям создавать сценарии и настраивать определенные части моего Java-приложения. Я использую статическую компиляцию всех пользовательских скриптов.

Мой вопрос: если мой код ожидает, например, получить значение типа boolean в результате пользовательского сценария, есть ли способ проверить, будет ли предоставленный пользовательский сценарий всегда возвращать булево значение без фактического выполнения сценария? Другими словами, как я могу получить доступ к результатам вывода типов, выполняемых статическим компилятором groovy? Я хотел бы иметь возможность сказать пользователю "эй, ваш сценарий не всегда возвращает логическое значение", пока он редактирует содержимое сценария.

2 ответа

Решение

Прямого пути нет, но это возможно. Boolean особенно сложен, так как компилятор с радостью применяет все виды приведений типов (например, преобразует int в boolean без жалоб). У меня была точно такая же проблема, и я сделал следующие шаги:

  1. ASTTransformation для установки типа возвращаемого значения в логическое значение (не требуется, был артефактом полуработающей более ранней итерации)
  2. ASTTransformation, чтобы материализовать все возвратные заявления
  3. TypeCheckingExtension, чтобы посетить ReturnStatements и убедиться, что они имеют тип boolean
  4. 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, которая, я думаю, заставит знать все типы во время компиляции. Не уверен, как бы вы принудительно включили это "Вкл" для кода скрипта вашего клиента.

Другие вопросы по тегам