Можно ли сообщить компилятору о категориях, используемых при выполнении закрытия в groovy?Использовать категории, известные @TypeChecked
Небольшой пример:
class Example {
static time = evaluateTime {
println 1.minute.from.now
}
static def evaluateTime(Closure<Void> cl) {
GroovyUtil.use(TimeCategory, cl)
}
}
это работает отлично при выполнении, но IntelliJ будет серо-вне minute
и если я добавляю TypeChecked
аннотацию, я получаю ошибки компилятора.
@TypeChecked()
class Example {
static time = evaluateTime {
println 1.minute.from.now
}
static def evaluateTime(Closure<Void> cl) {
GroovyUtil.use(TimeCategory, cl)
}
}
В подобном случае я нашел DelegatesTo
аннотацию, чтобы компилятор знал, что замыкание выполняется с другим делегатом, но я не могу найти соответствующую аннотацию для использования категории.
Will P's advice Я реализовал небольшой модуль расширения POC.
Сначала я смотрел на типы участвует
1
имеет типint
1.minute
имеет типgroovy.time.TimeDuration
1.minute.from
является анонимным классом типаgroovy.time.BaseDuration.From
groovy.time.BaseDuration.From
имеетnow
свойство (getNow
способ)
Таким образом, я пришел с этим расширением
class PrecompiledExtension extends GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
@Override
Object run() {
unresolvedProperty { pexp ->
if ('minute' == pexp.propertyAsString &&
getType(pexp.objectExpression) == classNodeFor(int)) {
storeType(pexp, classNodeFor(TimeDuration))
handled = true
}
if ('from' == pexp.propertyAsString &&
getType(pexp.objectExpression) == classNodeFor(TimeDuration)) {
storeType(pexp, classNodeFor(BaseDuration.From))
handled = true
}
}
}
}
Он смотрит на только неразрешенных Properties.
- Если имя свойства
minute
и тип выражения свойство считывается из являетсяint
, то результат будет иметь типTimeDuration
. - Если имя свойства равно
from
, а тип выражения, из которого считывается свойство, равенTimeDuration
, результат будет иметь типBaseDuration.From
.
Обратите внимание, что это только ПОС. Не существует логической проверки того, что недостающие свойства находятся в замыкании, которое вызывается с использованием TimeCategory
.
Чтобы компилятор использовал расширение, добавьте квалифицированное имя в TypeChecked
Аннотация (type.PrecompiledExtension
в примере ниже). Обратите внимание, что класс, аннотированный с помощью TypeChecked
, не может вызвать GroovyUtil.use
, поэтому я перевел вызов базовому классу.
class ExampleBase {
static def evaluateTime(@DelegatesTo(TimeCategory) Closure<Void> cl) {
GroovyUtil.use(TimeCategory, cl)
}
}
@TypeChecked(extensions = "type.PrecompiledExtension")
class Example extends ExampleBase {
static time = evaluateTime {
TimeDuration minute = 1.minute
BaseDuration.From from = minute.from
println 1.minute.from.now
}
}
Обратите внимание, что type.PrecompiledExtension
класс должен быть составлен до Example
класса. Для POC я отключил TypeChecked
для первого прохода компиляции, а затем снова включил его для второго прохода.
Это работает для компилятора, но IntelliJ не заберет это.