Archive for the ‘eclipse’ Category

Custom folding actions and configurable error levels with Xtext2

Friday, December 14th, 2012

Recently, I have been working on an eclipse editor prototype for the semantic web language turtle based on Xtext2. Two features not supported out of the box are custom folding actions and configurable error levels. You can find my solution attempt on github.

Additional preference pages

When adding your own preference pages, don’t forget to adapt the XtextEditor, so that these pages are not filtered away when opening the preferences from the editor’s context menu.

Folding

Adapting the creation of folding regions is quite well supported, already. The problem is, that they are not typed, i.e. the region has no information about the type of the foldable content. Worse still, it is everything but trivial to extract that information from the region finally created. This is because the region starts at the beginning of the first line and ends with the last character on the last line. So you cannot easily use the node model (at least I could not) to ask for the semantic element, as you don’t know the exact offset to use – the regions of foldable types may overlap after all.

What I did is using a custom region holding the type information. I added a custom folding action “Collapse strings” to the folding menu and a preference page for defining which type of region should be folded on editor startup. You find the main code in the folding package of the UI project, plugin.xml and the custom XtextEditor-implementation. I’d be interested in suggestions for a more elegant solution.

Custom error levels

Allowing configurable error levels for validation rules is a bit more straightforward. Have an interface for the providing the levels, feed it with default values in the language project and override it in the ui project there using values from the preference page. In the validator you simply invoke the error-, warning-, info-message generation based on the configured level.

Integrating your Xtext editor with eclipse help

Friday, April 27th, 2012

You have implemented a Xtext editor for a cool language and have even documented both via eclipse help, but unfortunately pressing F1 does not yield the desired effect? Here are some (hopefully) helpful code snippets.

First of all, it is important that you provided context ids for your help.

For a simple scenario, the necessary modifications in the UI project are quite small.
1) add org.eclipse.help to the plugin dependencies
2) bind your own implementation of XtextEditor (code snippets from below go there)

If you want a “static” help for your editor, i.e. the result of pressing F1 does not depend on the cursor position within the editor, overriding the createPartControl method is enough:

  @Override
  public void createPartControl(Composite parent) {
    //important to set context id before super call
    setHelpContextId(ITextEditorHelpContextIds.TEMPLATES_VIEW);
    super.createPartControl(parent);
  }

If you want more dynamic behaviour, e.g. the help should depend on the cursor position, explaining a language concept used there, one way to go is the IContextProvider… The following is a somewhat minimal example. Just as above, it uses existing help ids, so that you can play around without actually needing your own help. Normally, you would inspect the model element present at the given offset (available via text.getSelection().x):

  @Override
  public Object getAdapter(Class adapter) {
    if(adapter.equals(IContextProvider.class)){
      //this is just an example!
      //you should not instantiate a new provider every time
      return new IContextProvider() {
        @Override
        public String getSearchExpression(Object target) {
          //adapt the search expression according to the current position
          return "grammar mixin";
        }
        @Override
        public int getContextChangeMask() {
          //provide a new context whenever the selection changes
          return IContextProvider.SELECTION;
        }
        @Override
        public IContext getContext(Object target) {
          //retrieve one (or more for combining them) context
          //from the help system and return the result
          StyledText text = (StyledText)target;
          if(text.getSelection().x>20){
            return HelpSystem.getContext(
              ITextEditorHelpContextIds.TEXT_EDITOR_PREFERENCE_PAGE);
          }else{
            return HelpSystem.getContext(
              ITextEditorHelpContextIds.TEMPLATES_VIEW);
          }
        }
      };
    }
    return super.getAdapter(adapter);
  }

Some additional remarks:

PlatformUI.getWorkbench().getHelpSystem().setHelp(control, contextId) is nice for setting the help for a particular control. We used it for redirecting to our help in the DSL’s preference pages (bind extension of e.g. SyntaxColoringPreferencePage, there override setControl with super call + setHelp for the given control).

Assume that for a certain position in the editor several of your help contexts are relevant. In that case you could create a new “artificial” IContext with the accumulated related topics.

There are extensions of IContext that allow changing the title, categories etc.

Getting Xtext model todo comments into the task list

Friday, March 30th, 2012

Wouldn’t it be nice, if the todo comments from your DSL would make it to the task list, as you know it from the java editor?

The sample project is based on Xtext 1. All relevant code is in the UI project. The plugin.xml (very end) contains the definition of a marker with taskmarker supertype. XtextTaskCalculator contains the code for creating the markers on saving a file. Basically it iterates over all elements of the node model and asks an injected ITaskElementChecker if that element contains a task, if so the marker is created. The MydslTaskElementChecker triggers for single line comments starting with //TODO.

For some reason the marker ID defined in the plugin.xml (Xtask) has to be prefixed when creating the marker (org.xtext.example.mydsl.ui.Xtask)…
(When experiencing problems here, you might want to add an annotationTypes extension and browse the markerTypes available. There you will get the fully qualified name of the marker)

Download: sample project

How to highlight matching tags in Xtext

Tuesday, March 27th, 2012

Folding regions, bracket matching, outline etc. are ways to provide structural information about a model. Sometimes you might want to highlight matching tags that are longer than one character. In this case Xtext’s built in bracket matching may not be enough for the user.
This post provides a simple sample project indicating a solution. It is based on Xtext 1 (Greeting example). Adapting it to Xtext 2 should be straight forward (different node model and NodeModelUtil instead of NodeUtil). I shamelessly adapted code from Xtext2′s mark occurrences code.

The idea is to define an annotation type and re-calculate annotations when the selection changes. All the interesting code is in the UI project. The plugin.xml defines the annotation type (whose properties may then be changed in the preference page). The MyDslUIModule configures a binding to an IXtextEditorCallback, so that the selection change listener can be registered when the editor is opened an unregistered when it is disposed. And all the work is done in the GreetingsMatchingTagMarker. Its code should by quite generic. If you want to adapt it to your purposes, you’ll need a different Grammar access in TaskMarkJob and your own logic in its fillAnnotationMap method. There the annotations for a particular model element are calculated.

Download sample project.