21 Aug 2009 waffel   » (Journeyer)

use your own variable in eclipse code templates


On my work we develop eclipse plugins and want to add the current bundle id and bundle version to the since field for class comments. There are not much examples around this problem (we have searched google and eclipse help) so let me explain how you can achive this.

For example we want to define follow code template:


/**
 * @author ${user}
 *
 * ${tags}
 * @since ${bundleId} ${bundleVersion}
 */

The bundleId and bundleVersion variable are not provided by the standard code template variables. Now we have to find out how we can achive this problem.

First of all you need to develop your own eclipse plugin which should provide such feature. The new plugin requires follow dependencies:

  • org.eclipse.core.resources;bundle-version=”3.5.0″,
  • org.eclipse.ui;bundle-version=”3.5.0″,
  • org.eclipse.jface.text;bundle-version=”3.5.0″,
  • org.eclipse.jdt.core;bundle-version=”3.5.0″,
  • org.eclipse.jdt.ui;bundle-version=”3.5.0″,
  • org.eclipse.core.runtime;bundle-version=”3.5.0″,
  • org.eclipse.pde.core;bundle-version=”3.5.0″

The PDE dependency is needed to get the current bundle id and the bundle version. If you need other features (for example a maven project version) you have depend on other plugins. But in this example I’ll show you how to add bundle id and bundle version as extra variable for the eclipse code templates.

Next you have to create a extention to register your own variable resolver at startup. The variable resolvers are the heart of the plugin because they providing new variables for the code templates to be used and resolving the content if you use the code template.

plugin.xml:


< ?xml version="1.0" encoding="UTF-8"?>
< ?eclipse version="3.4"?>
<plugin>
   <extension point="org.eclipse.ui.startup">
      <startup class="yourplugin.eclipse.javadoc.internal.RegisterResolvers">
      </startup>
   </extension>
</plugin>

The RegisterResolvers class implements the IStartup interface from eclipse. This class registers the variable resolvers to the code template context. This is required to have the variables available in the code templates from eclipse.

RegisterResolver:


/**
   *
   * {@inheritDoc}
   *
   * @see IStartup#earlyStartup()
   *
   */
  public void earlyStartup() {
    // check if plug-in org.eclipse.jdt.ui is already active
    final Bundle bundle = Platform.getBundle(PLUGIN_ID);
    if (bundle != null && bundle.getState() == Bundle.ACTIVE) {
      // register resolvers
      registerResolvers();
    } else {
      // register listener to get informed, when plug-in becomes active
      final BundleContext bundleContext = Activator.getDefault().getBundle().getBundleContext();
      bundleContext.addBundleListener(new BundleListener() {
        public void bundleChanged(final BundleEvent pEvent) {
          final Bundle bundle2 = pEvent.getBundle();
          if (!bundle2.getSymbolicName().equals(PLUGIN_ID)) {
            return;
          }
          if (bundle2.getState() == Bundle.ACTIVE) {
            registerResolvers();
            bundleContext.removeBundleListener(this);
          }
        }
      });
    }
  }

/**
   *
   * Internal method to register resolvers with all context types.
   *
   */
  private void registerResolvers() {
    final ContextTypeRegistry codeTemplateContextRegistry = JavaPlugin.getDefault().getCodeTemplateContextRegistry();
    final Iterator ctIter = codeTemplateContextRegistry.contextTypes();
    while (ctIter.hasNext()) {
      final TemplateContextType contextType = (TemplateContextType) ctIter.next();
      contextType.addResolver(new BundleIdResolver());
      contextType.addResolver(new BundleVersionResolver());

    }
  }

The bundleIdResolver extends the TemplateVariableResolver and defines (in the default constructor) the variable name which can be used later in the code template, a description and overrides the resolve method.

The resolve method checks if the current project is a plugin project and if so returns the bundle id from the project.


public class BundleIdResolver extends TemplateVariableResolver {
  /**
   *
   * Constructs a new <code>BundleIdResolver</code>.
   *
   */
  public BundleIdResolver() {
    super("bundleId", "id of the bundle containing the current compilation unit");
  }

  /**
   *
   * {@inheritDoc}
   *
   * @see TemplateVariableResolver#resolve(org.eclipse.jface.text.templates.TemplateContext)
   *
   */
  @Override
  protected String resolve(final TemplateContext pContext) {
    final CodeTemplateContext context = (CodeTemplateContext) pContext;
    final IPluginModelBase pluginModelBase = PluginRegistry.findModel(context.getJavaProject().getProject());
    if (pluginModelBase == null) {
      return null;
    }
    return pluginModelBase.getBundleDescription().getSymbolicName();
  }
}

Now you can come up with the question why not you can use the standard eclipse extention point mechanism and create your own context.

Well, we want to extend the java context but the current eclipse implementation doe’s not provide such functionality. For sure if you want to have your own context you can do this with the standard extention point mechanism (as the Ant example). There is a small example about the eclipse editor templates.

Thanks to my colleague Marco Lehmann for the complete solution.

Posted in java Tagged: code template, eclipse, java, plugin

Syndicated 2009-08-21 12:08:44 from waffel's Weblog

Latest blog entries     Older blog entries

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!