使使用过的类别为@TypeChecked 所知

Make used categories known to @TypeChecked

是否可以让编译器知道在 groovy 中执行闭包时使用的类别?

一个小例子:

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 注解让编译器知道闭包是用不同的委托执行的,但我找不到相应的使用类别的注解。

之后我实现了一个小的POC扩展模块。

首先我查看了涉及的类型

于是我想出了这个扩展

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
            }
        }
    }
}

它只查看未解析的属性。

请注意,这只是一个 POC。没有逻辑验证缺少的属性是否在使用 TimeCategory.

调用的闭包中

要让编译器使用扩展名,请将限定名称添加到 TypeChecked 注释中(下例中的 type.PrecompiledExtension)。请注意,用 TypeChecked 注释的 class 无法调用 GroovyUtil.use,因此我将调用移到了基础 class.

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 class 必须在 Example class 之前编译。对于 POC,我在第一次编译过程中禁用了 TypeChecked,然后在第二次编译过程中再次启用它。

这适用于编译器,但 IntelliJ 不会选择它。

不,@TypeChecked 不支持类别。您可以使用 extension module or write your own type checked extensions