Background
I m a developer of the Vrapper project.
Vrapper contains of 2 major parts
- Vim-emulation library (vrapper.core)
- Eclipse part that makes a good use of it
We want vrapper.core to be Eclipse-unaware, so it s reusable outside of the Eclipse. Currently, we can "vrap" all sorts of Eclipse text editors and our little mock text editor that we use for unit testing.
vrapper.core implements all sorts of Vim commands, modes, etc. Those all communicate with Platform - an interface that abstracts out underlying stuff (text editor, clipboards, settings system, etc.).
When mode is created for an editor it asks platform if there are extra commands that are approperiate for underlying editor, currently edited file type, etc.
EclipsePlatform provides those commands using Eclipse extension points mechanism.
So, let s consider the following projects (there are more):
- vrapper.core - Eclipse-independent code for Vrapper
- vrapper.eclipse - Eclipse plug-in that depends on vrapper.core
- surround.core - Eclipse-independent code that emulates surround.vim (Vim plug-in)
- surround.eclipse - Eclipse fragment for vrapper.eclipse that makes it provide commands form surround.core.
There are two ways we can deal with those:
One plug-in to rule them all
This is how it should look like from Eclipse s perspective. There is one plug-in that contains code from vrapper.eclipse and vrapper.core, and one fragment that contains code from surround.core and surround.eclipse.
Many plug-ins
- There are 3 plug-ins
- two OSGified libraries vrapper.core, surround.core
- vrapper.eclipse
- surround.eclipse fragment depends on vrapper.core in this case
Problems
Many plug-ins solution have some issues with lazy class loading that I don t understand. It s beacause when instances of modes from vrapper.core are created they need classes from surround.core to be created (via vrapper.eclipse -> surround.eclipse).
This works if you run stuff from Eclipse and select all plug-ins from run configuration, but if one deploys features & plugins and run eclipse normally an exception is thrown because classes from surround.core cannot be found. It s something in the spirit of surround.core asking for extra commands from dependent plug-ins creates implicit circular dependencies.
What I mean by implicit dependencies is that no core class depends on eclipse-specific classes in compile time.
Modes (like vim normal mode) are core classes. They contain commands. There are some commands specific for particular Eclipse editors (like run this JDT-specific refactoring). Those commands implement core interfaces, but their code (obviously) lives in eclipse-specific projects. When mode is created it asks underlying platform for some extra commands - those extra commands are implemented in eclipse plug-ins. This is when lazy class loading in eclipse make everything blow up in runtime - classes for extra commands are referenced by extension points, but they are not yet loaded. Boom, exception.
I tried to work this around by using "one plug-in to rule them all" approach. Having just one plug-in seems to be much better solution to me, but I couldn t make it work cleanly.
Only thing that succeeded for me was quite an ugly hack.
- All .core projects had an Ant task that created .jar file with their classes and dropped it into corresponding *.eclipse project
- *.eclipse projects included that jars and had them enlisted in MANIFEST files.
The problem with this ugly hack approach (besides of it being ugly hack) is that development becomes quite painful. Eclipse code navigation, code coverage and few other things in Eclipse stops working.
Summary
We have eclipse independent library + eclipse specific stuff architecture, but we really need all of this to live in one plug-in (because there are some dependencies in both directions).
How do I make code from few projects live into one plug-in/fragment?