This Eclipse integration problem has been causing us issues for years now but we were able to somehow live with the itch. With some changes to the projects this is now becoming significantly harder. While Gradle does differentiate between “main compile”, “main runtime”, “test compile” and “test runtime” classpaths, as noted in numerous places and forums, Eclipse does not, at least not to the same extent. Eclipse projects only have one classpath and all of it is used for compilation. It does not differentiate between main and test code either - it is all just code to it. Runtime classpaths are supposed to be defined by run/launch configurations and tests are supposed to be in separate projects.
As far as I know and have experienced, Gradle’s Eclipse plugin behaves like most tools out there - it kinds of gives up on Eclipse and rolls all relevant Gradle classpaths (via runtime and testRuntime that extend compile and testCompile) into a single Eclipse project classpath for ‘that’ project. Tests are declared as an extra source tree for the same project. Normally this is of little issue, as naughty main code referencing test code would fail in a gradle build even though it would pass in the Eclipse build and projects may not be large/complex/managed enough to warrant preventing access to some code that is supposed to be a runtime-only dependency.
Both of these problems become nasty in certain situations. We have in-Eclipse code generation tools (Gradle equivalents we use are neither the problem nor the solution) that get messed up by visibility of test code as if it were project code in Eclipse - they fail. As for compile vs. runtime dependencies we have strict rules as to which libraries our own code can use directly (compile classpath) and which it should not because we want to minimize the number of dependencies and preserve the ability to move to a different library (mainly transient, runtime-only dependencies).
To this extent I attempted to create a gradle plugin that will create separate Eclipse test projects ‘out of thin air’ based on the main projects configuration (these would not be in source control, as they only exist to help with Eclipse model differences). This I more-or-less succeeded. In creating the runtime classpaths, so far, I failed miserably.
Again, for Eclipse, runtime classpaths should be defined in launch configurations. However, to do this I would have to generate those just like the eclipse plugin generates the .classpath files. Since developers often copy the launch configs to make local tweaks, their copies would end up being disconnected from this generation and would not receive any classpath updates. So I abandoned that idea.
I tried using the same trick I did for the test projects - creating helper ‘runtime classpath’ projects out of thin air, with no code, only dependencies (referenced libraries). Not only I hit some weird issues with this (due to either my own lack of understanding of how Gradle works or Gradle bugs, I may write about these separately), I re-discovered that this very quickly leads to multiple occurrences of the same library in the runtime classpath - one per referenced project that brings it. Eclipse does not eliminate duplicates, it is happy to have them. With startup classpath scanning code (say searching for beans, annotations, etc) this becomes a serious issue - that of performance and can fail when the same class is apparently found multiple times.
The ongoing plan is now to abandon the “runtime classpath only projects” and instead replace them with dynamically (gradle) generated “Eclipse Libraries”. It is then the library (or libraries) that would be included in the launch configuration classpath instead of ANY non-project dependencies (projects would either not export their dependencies or these would have to be ignored).
Before I start doing this, is there any existing work done on this and/or any recommendations?