On 2020-01-02 17:50, Marcin Zajączkowski wrote: > Hi, > > TL;TR. I would like to have a way to inform IDE that a passed in an > annotation Closure's execution is in fact delegated to a specific object > (type). E.g. "@Requires({ jvm.java11 })" should allow to write "jv" and > see jvm in IDE (once a delegate has that field/getter).
Having no reply within a few days I assume it is problematic to do that right now. Therefore, I will narrow down my question. Do you think it is worth to extend @DelegatesTo to be able use it for Closures returned from a method: > public @interface MyRequires { > @DelegatesTo(PreconditionContext.class) Class<? extends Closure> value(); > } to instruct IDE what is a delegate for a Closure placed in an annotation (and have code completion)? > @Requires({ jvm.java11 && os.linux }) Marcin > More detailed version. > > One of the nice features of Spock is an ability to define conditions in > Closure when test(s) should (not) be executes with @Required/@IgnoreIf. > > @Requires({ isSpecialConditionFulfilled() }) > def "some test"() {} > > The annotation itself is defined as: > > @Retention(RetentionPolicy.RUNTIME) > @Target({ElementType.TYPE, ElementType.METHOD}) > @ExtensionAnnotation(RequiresExtension.class) > public @interface Requires { > Class<? extends Closure> value(); > } > > Down the line the execution is delegated to PreconditionContext which > provides convenient methods/objects such as os.linux, jvm.java11, env, etc. > > @Requires({ jvm.java11 && os.linux }) > > Unfortunately, there is no code completion as IDE doesn't know about > that delegation (and jvm, os fields/methods). Groovy 2 introduced > @DelegatesTo, however it cannot be used with other annotations or methods. > > It can be tricked by creating a static final instance of > PreconditionContext (it's stateless) somewhere (e.g. in the > Specification super class), but people has to know to refer it, e.g: > > @Requires({ CTX.jvm.java11 }) > > Alternatively, I was thinking about a method in the base Spock class: > > protected static def ctx(@DelegatesTo(PreconditionContext) Closure > closure) { > closure() > } > > which could be referenced as: > > @Requires({ ctx { jvm.java10Compatible } }) > > It works, but again "ctx" has to be referenced on demand. > > The best long-term solution would be to allow to use @DelegatesTo at the > method level: > > public @interface MyRequires { > @DelegatesTo(PreconditionContext.class) Class<? extends Closure> value(); > } > > It would provide code completion out of the box (once IDEs have support > for that :) ). The second main drawback I see is being not very > intuitive declaration and limited usage. > > > Having Groovy 3.0 on the horizon (with breaking changes postponed to > Groovy 4) I wonder do you see any elegant solution to deal with the > aforementioned case in Spock itself (Spock 2 could potentially break > compatibility if needed) or in Groovy (that potentially could be > implemented before 3.0-final)? > > Marcin >