Note
This guide is a work in progress. If in the process of writing a new plugin you find anything here that is unclear or missing, please don’t hesitate to post to the eclim-dev mailing list with questions, suggestions, etc.
To allow eclim to support different languages, eclim is broken up into eclipse plugins, each of which depend on a corresponding eclipse feature which provides support for that language. When you install or build eclim, it will examine your eclipse install to determine which features are available and will add the corresponding eclim plugins to expose those features. This page documents the core aspects of what goes into the creation of a new eclim plugin.
Eclim includes a set of templates to help you bootstrap a new plugin. To utilize them you can run the following ant target:
$ ant plugin.create
You will be prompted to enter a name for this plugin along with some guidelines on choosing an appropriate name.
Once you’ve chosen a name, the plugin’s directory structure will be created and
populated with bare bones version of the required artifacts. Eclim’s
build.xml
file will also be updated to include a target to the new plugin’s
unit test target.
After you’ve bootstrapped your plugin, you can now start updating the generated artifacts:
The first file you’ll need to modify is a gant file for your plugin. The main
eclim build.gant script will load this file during the build process to
determine what the plugin’s eclipse dependency is, so it knows whether it can be
built against the target eclipse install. So the first thing we need to do is to
fill in that information by updating the feature_<plugin_name>
variable with
the name of the eclipse feature that this plugin depends on. For example, the
eclim jdt plugin has this set to 'org.eclipse.jdt'
. The build script will
look in the features
directory of your eclipse install (including the
dropins
and your user local eclipse dir if set), to find this feature, so
the value you set, must be found in one of those locations (the version suffixes
will be removed from the features in order to match it against the value you’ve
set).
You’ll also notice that there is a unit test target in the gant file. You can ignore that for now.
The next file to note is the plugin’s META-INF/MANIFEST.MF
. This is the file
that eclipse will use to determine how to load the bundle and what to include in
its classpath. The only part of this file that you should edit is the
Require-Bundle:
section. This is a comma separated list of bundles (or
plugins) which this bundle depends on. When this bundle is loaded only those
bundles listed here will be available in the classpath. So when you start
running commands you’ve written later, if you receive a
ClassNotFoundException
, that is likely due to the bundle containing that
class not being listed in your plugin’s Require-Bundle:
list. At this point
you probably don’t know yet what bundles you need to add to this list. When you
start writing commands for your plugin, you’ll have to find out which bundles
contain the classes imported from the eclipse plugin you are integrating with,
and you’ll need to add those bundles accordingly.
It’s also worth noting that eclim provides a custom classpath container which
scans the manifest of each eclim plugin and loads the required bundles of each
into the classpath. So when adding new bundles, if you want validation, search,
code completion, etc to work with classes from those new bundles, you’ll have to
restart the eclim daemon. While restarting can be annoying, this is generally
better than having to add/remove entries from the .classpath
file or
worrying about one user having different bundle version numbers from another.
At this point you’ll typically need to start customizing your plugin’s
org.eclim.<name>/java/org/eclim/plugin/<name>/PluginResources.java
file.
Here is where you will map a short alias to the project nature, or natures, of
the plugin you are integrating with, register a project manager for initializing
project’s for this plugin, register any plugin settings that users can
configure, etc. You’ll be doing all this inside of the initialize
method
which has been generated for you.
You’ll first need to find out where the plugin’s nature id is defined. Here are some examples that should give you an idea of where to look:
One way to find it is to open up the .project
file in a project containing
the nature, locate the fully qualified name in the <natures>
section, then
grep the plugin’s code for that name.
Once you have the reference to the nature id, you can then create a public
static variable called NATURE
:
public static final String NATURE = SomeClass.NATURE_ID;
You’ll be using this constant as the key to register features for project containing this nature, but first we’ll register a short alias for this nature since the actual nature id tends to be long and unstandardized, and we don’t want users to have to type it out when creating projects from eclim:
ProjectNatureFactory.addNature("shortname", NATURE);
The next thing you’ll probably need to do is to create a project manager for
your project
(org.eclim.<name>/java/org/eclim/plugin/<name>/project/SomeProjectManager.java
).
The project manager is responsible for performing any post create, update,
delete, or refresh logic required for projects of this nature. This logic can
include things such as creating an initial classpath/buildpath, validate the
classpath/buildpath on update, forcing a full update of the search index on
refresh, or any number of other things.
Overriding the create
method will almost certainly be necessary, but the
logic you’ll need here varies widely. Finding what you’ll need is a matter of
digging through the parent plugin’s source code, typically looking for the
project creation wizard class, to see what it does to create a project of this
nature and later comparing the created artifacts from your code against those of
a project created from the eclipse gui. This can be a difficult hurdle to get
past for someone doing this the first time, so please don’t be shy about asking
for help on the eclim-dev mailing list.
Eclim does provide a couple ant tasks to at least help you to quickly extract any docs and source code found in your eclipse install:
eclipse.doc: This target will extract any doc jars from your eclipse install to a ‘doc’ directory in your eclipse home (or user local eclipse home).
eclipse.src: This target will extract any src jars from your eclipse install to a ‘src’ directory in your eclipse home (or user local eclipse home). If you download the sdk version of eclipse then the jdt and all the core eclipse source will be available. Some other plugins provide sdk versions which include the source code and this target can extract those as well, but some plugins don’t seem to have this option when installing via eclipse’s update manager (and may not include the source when installed from a system package manager). For those you can often download a zip version of their update site which should include source bundles. Once you’ve extracted that file, you can tell this target to extract source bundles from a specified directory. Here is an example of extracting the source from an unpacked dltk update site:
$ ant -Dsrc.dir=/home/ervandew/downloads/dltk-core-5.0.0/plugins eclipse.src
Once you’ve created your project manager, you then map it to your plugin’s
nature inside of your PluginResources.initialize
method like so:
ProjectManagement.addProjectManager(NATURE, new SomeProjectManager());
At this point you should have the minimum of what is needed for a new plugin. Hopefully you can now create new projects with your plugin’s defined nature. The next step would be to start adding commands to provide validation, code completion, etc. The remaining items in this list are not required to continue. They provide you with the ability to setup your own preferences or to expose the parent plugin’s defined preferences inside of vim. When you’ve come to the point that you need to work with preferences, then feel free to come back here and continue reading.
To Be Continued…