Hi everyone!
IDE support is on my wishlist for the Job DSL plugin since early on. Last week I found some time to work on the topic.
tl;drIDE support is coming and the parts of the DSL documented in the wiki are not going to change, but undocumented behavior is going to change.
The GoodThe following features are working in IDEA 13.1.5:
This works by adding the job-dsl-core library to the project containing the DSL scripts. The library contains a
GroovyDSL script that tells the IDE (IDEA only) which methods are available in scripts.
The BadCode completion does not work in IDEA 13.1.5. I tried the latest IDEA 14 EAP release, but also without luck.
There will be no IDE support for configure blocks. I have no idea how to get that done and I'm not sure if it's possible to implement.
The IDE can not guess the methods available in closures because the signature of methods taking a closure does not contain that information. The IDEA way to add IDE integration for closure parameters this is to extend the GroovyDSL script and the Groovy way is to use the
DelegatesTo annotation. I favor the Groovy way since it will enable support for those IDEs in the future. But the DelegatesTo annotation is only available in Groovy 2.1 or later and Jenkins uses Groovy 1.8. Updating the Groovy version in Jenkins will take some more time (
JENKINS-21249). So I had to
copy the annotation to the Job DSL plugin. I started to annotate some closure parameters with DelegatesTo, but there is still work left.
Only very few methods have useful Groovydoc. It will be a lot of work to add useful texts to all methods.
The UglyThe
Job class uses the
Delegate annotation to move functionality to other classes. The classes are called helpers in the Job DSL plugin, like
PublisherContextHelper. Unfortunately there is a bug in IDEA so that DelegateTo annotations in method signatures blended in via Delegate fields are not evaluated. I tried the latest IDEA 14 EAP release, but again without luck. For some reason the helper classes only exist on the first level below the job context (the exception to the rule is
StaticAnalysisPublisherContext) but deeper levels don't use that pattern. I always thought it was strange the have the helper classes on the first level, so I decided to remove them and move the functionality to the Job class. The benefit is that we don't have to wait for a fix in IDEA and that the DSL implementation is now cleaner, since the same pattern is used for contexts on all levels. On the downside the Job class will get bigger, but not as big as
PublisherContext for instance.
The Job class contains the methods for all job types. But views and config files are implemented in a different way. There are subclasses for each type. The good part is that those classes do not use the @Delegate annotation to keep the classes small since each class only contains the methods needed for the concrete type and it's not necessary to move the methods back as for the Job class. But the bad part is that there only one view and one configFiles method which select the view or config file type with a named parameter (e.g view(type: NestedView)). The DelegatesTo annotation on those methods can not dynamically point the class implementing the view or configFile type. So it has to point to the super type which contains only a few common methods. Meaning that there will be no IDE support for specific view or config file types without further changes. The named parameter pattern is only used for the top-level DSL methods (with a few exceptions like the
trigger method in extendedEmail) and the DSL design will get cleaner if the same rules are used on all levels. So I will deprecate the top-level methods and add new ones for each type of job, view or configFile (e.g. mavenJob or deliveryPipelineView) which will have the @DelegatesTo annotation pointing to the implementing class. I will also split-up the Job class into subclasses for each job type to cut down the size and to use the same pattern as for views and config files.
Allmost all DSL methods specify "
def" as return type, meaning that we don't care for the return type. The exception to the rule are the top-level methods which return Job, View or ConfigFile objects for further manipulation. In Groovydoc, def shows up as Object. The value actually returned by a DSL methods depends on the last statement in the implementing method block and since we do not care it can be anything. And when it shows up in the documentation, users may start to rely on the existing behavior. So we should start to care about the return value. To fix this I will change all return types to void, since there are no reasonable values to return.
Daniel