Editor

FeatureExtension PointsClasses
ABSEditor and Content Type
Markers and Annotationsorg.eclipse.core.resources.markers org.eclipse.ui.editors.annotationTypes org.eclipse.ui.editors.markerAnnotationSpecificationeu.hatsproject.absplugin.editor.ABSMarkerAnnotationModel eu.hatsproject.absplugin.editor.ABSSourceViewerConfiguration
Decoration for Location Typesorg.eclipse.core.resources.markers org.eclipse.ui.editors.annotationTypes org.eclipse.ui.editors.markerAnnotationSpecificationeu.hatsproject.absplugin.editor.decoration.ABSDecorationSupport eu.hatsproject.absplugin.editor.ABSEditor org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy eu.hatsproject.absplugin.editor.ABSSourceViewerConfiguration
Semantic highlightingeu.hatsproject.absplugin.editor.ABSCodeScanner eu.hatsproject.absplugin.editor.ABSSourceViewerConfiguration abs.frontend.parser.Keywords eu.hatsproject.absplugin.preferences.ABSSyntaxColoring
Content Assistanteu.hatsproject.absplugin.contentassist.ABSCompletionProcessor eu.hatsproject.absplugin.contentassist.ProposalFactory
Jump to declarationorg.eclipse.ui.commands org.eclipse.ui.bindings org.eclipse.ui.popupMenus org.eclipse.ui.editorActions org.eclipse.ui.contextseu.hatsproject.absplugin.editor.JumpToDeclarationDelegate
Outlineorg.eclipse.ui.menus org.eclipse.ui.commandseu.hatsproject.absplugin.editor.outline.ABSContentOutlineFilters eu.hatsproject.absplugin.editor.outline.ABSContentOutlinePage eu.hatsproject.absplugin.editor.outline.ABSContentOutlineProvider eu.hatsproject.absplugin.editor.outline.ABSContentOutlineStyledLabelProvider eu.hatsproject.absplugin.editor.outline.ABSContentOutlineUtils eu.hatsproject.absplugin.editor.outline.handlers.ABSContentOutlineFilterHandler eu.hatsproject.absplugin.editor.outline.handlers.ABSContentOutlineSortHandler

ABSEditor and Content Type

Markers and Annotations

  • defined with extension point org.eclipse.core.resources.markers
  • two kinds of markers: absproblem and locationtypeinferenceinfo
    • additional attributes (startline, endline, startcol, endcol)
  • subtypes of absproblem: absparseproblem and abstypecheckproblem
  • annotationTypes
    • defined with extension point org.eclipse.ui.editors.annotationTypes
    • connection with markers over property markerType
  • markerAnnotationSpecification
    • specification of the style of highlighting with extension point org.eclipse.ui.editors.markerAnnotationSpecification
    • the keys used (like colorPreferenceKey) are keys in the preference store and and can be chosen freely but need to be unique
    • connection to annotations with property annotationType
  • eu.hatsproject.absplugin.editor.ABSMarkerAnnotationModel
    • method createPositionFromMarker(..) reads the additional attributes (see above) and returns the respective positions (relative to the document of the editor)
  • eu.hatsproject.absplugin.editor.ABSSourceViewerConfiguration
    • add cases for the new markers to the methods getAnnotationHover(..) and getTextHover(..) so you get pop-ups for the new annotations when hovering the mouse over it.

Decoration for Location Types

  • create annotation and marker types like in "Markers and Annotations"
  • add special DrawingStrategy in ABSDecorationSupport (eu.hatsproject.absplugin.editor.decoration.ABSDecorationSupport)
  • change text style values in ABSEditor (eu.hatsproject.absplugin.editor.ABSEditor) in method configureSourceViewerDecorationSupport(..)

Semantic highlighting

In eclipse, a text editor partitions the text into different partition types. One of the types is the source code, in this case of the ABS program. The partitioner doing the job is the ABSCodeScanner (eu.hatsproject.absplugin.editor.ABSCodeScanner). It is initialized in the ABSSourceViewerConfiguration (eu.hatsproject.absplugin.editor.ABSSourceViewerConfiguration).

The ABSCodeScanner initializes the list of keywords (given by the abs Frontend in class abs.frontend.parser.Keywords). The color and style of the tokens are taken from the preference store of the plug-in. For highlighting elements of the abs language like functions, data types and so on, there are two possibilities: Regular expressions or semantic rules.

When the document of an editor changes, it determines the damage and tries to repair it. For this, the changed part of the document has to be rescanned. The method setRange(..) gets called. In this method one can do initialization stuff like re-parsing the document (because there could be changes in the editor that are not yet saved). Next the method nextToken() gets called as long as there are parts of the document left that needs to be repaired/rescanned. There the interesting stuff happens. The next token is searched for using a word detector (here for finding identifiers) and the token for this identifier is determined. Keywords have highest priority, if semantic highlighting fails (for example if the file is not part of an abs project) regexp matching is used.

The style of highlighting can be changed in the preference page (under ABS -> ABS Syntax Coloring). This page can be changed in the class ABSSyntaxColoring (eu.hatsproject.absplugin.preferences.ABSSyntaxColoring). New elements have to be added to the list in method createContents(..) and added to the case in the selection listener some line underneath. The graphical elements are all FieldEditors which means you only have to supply the preference store and the key of the property. The rest is realized inside the field editor like loading and saving the values from and to the store.

Content Assistant

The content assistant should provide users with a list of completion proposals to the current input. In Eclipse, these proposals are provided by an org.eclipse.jface.text.contentassist.IContentAssistProcessor which has to be added to the sourceViewerConfiguration (override the method getContentAssistant to return an ICompletionProcessor).

This interface is implemented by the eu.hatsproject.absplugin.editor.contentassist.ABSCompletionProcessor. Notable int this class are the following methods

  • ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset)

    This method should return a list of proposals depending on the current input. It is already apparent in the interface and is called whenever the content assist is invoked on a file. The actual computation of the proposals is done by our ProposalFactory (eu.hatsproject.absplugin.editor.contentassist.ProposalFactory).

  • Qualifier getQualifier(IDocument doc, int documentOffset)

    This returns the String which is already typed in by the user.

  • char[] getCompletionProposalAutoActivationCharacters()

    As the name suggests, if one of the chars returned by this method is typed by the user, auto completion is invoked automatically.

As mentioned above, the computation of proposals is done by a ProposalFactory. Such a factory is created, whenever the content assist is invoked.

The constructor of this factory requests the qualifier already typed in, the position in the document, the document, the editor and an empty proposal list which should be populated.

Most important is the method computeStructureProposals, which populates the list with keywords, main blocks, classes, different incomplete access proposals, top level and class field proposals.

Jump To Declaration Feature

  • command added to org.eclipse.ui.commands extension point for key binding
  • key binding in org.eclipse.ui.bindings extension point
    • abs editor scope to activate binding only when an abs file is opened in editor
  • command included in editor pop-up menu with org.eclipse.ui.popupMenus extension point
  • real action added with org.eclipse.ui.editorActions extension point
    • definitionId to define which command should be handled (for previous bindings)
  • abs editor scope added with org.eclipse.ui.contexts extension point

Outline

General

The ABS outline dissects a ABS compilation unit with the help of its AST to create a tree view of the elements in an ABS compilation unit.

The ABS content outline is realized by implementing a content outline page (ABSContentOutlinePage). These outline pages are queried by the built-in Eclipse Content Outline View using the getAdapter(Class) method of the currently active Editor page to an IContentOutlinePage. Hence, to provide an outline, it is the editor's responsibility to override the getAdapter(Class) method to deliver an instance of an IContentOutlinePage.

Code to hook the content outline page into the ABSEditor:

public Object getAdapter(Class key){
        if (IContentOutlinePage.class.equals(key)){
                if(this.outlinePage == null){
                        outlinePage = new ABSContentOutlinePage(this.getDocumentProvider(),this);
                }
                return outlinePage;
        }
        return super.getAdapter(key);
}

If the outline should be extended with new elements or elements should be altered, the classes ABSContentOutlineProvider and ABSContentOutlineStyledLabelProvider have to be altered (see below).

ABS Content outline page (ABSContentOutlinePage)

Basically, the ABS content outline page is the container of a SWT TreeViewer component displaying the content outline tree. It is responsible for setting up the tree viewer component - including setting a label provider, a content provider as well as an input the tree viewer should display and it registers listeners for example to track down resource changes or listen to selection events in the underlying tree viewer. Lastly, the ABS content outline page is responsible for restoring the state of tree filters and tree sorters.

Example how to provide the TreeViewer with a content provider and a label provider :

        public void createControl(Composite parent) {
                ...
                getTreeViewer().setContentProvider(coProv);
                // The label provider is responsible for converting ASTNodes into their String representations
                getTreeViewer().setLabelProvider(new ABSContentOutlineStyledLabelProvider());
                ...
        }

ABS outline content provider (ABSContentOutlineProvider)

Any SWT TreeViewer needs a content provider that bridges the gap between the TreeViewer input model (setInput(Object)) and the viewer itself. Therefore, the ABS content outline provider is responsible for dissecting the AST of an ABS file (or more specifically a compilation unit) into a tree structure. The ABS content provider is set using the TreeViewer's method setContentProvider(ITreeContentProvider) during the setup of the TreeViewer.

If a TreeViewer has got a content provider, it uses the content provider's methods

  • Object[] getChildren(Object)
  • boolean hasChildren(Object)
  • Object[] getParent(Object)

in order to build up its content tree.

Example of getChildren(Object):

public Object[] getChildren(Object parentElement) {
        ...
        if (parentElement instanceof ModuleDecl) {
                return ABSContentOutlineUtils.getChildrenOf((ModuleDecl) parentElement).toArray();
        } else if (parentElement instanceof CompilationUnit) {
                return getChildrenOf((CompilationUnit) parentElement);
        } ...

        return new Object[0];
}

Example of hasChildren(Object):

public boolean hasChildren(java.lang.Object element) {
        ...
        if (element instanceof ClassDecl) {
                return (((ClassDecl) element).getNumField() > 0) || (((ClassDecl) element).getNumMethod() > 0);
        } else if (...) {
                ...
        }
        ...
}

ABS outline label provider (ABSContentOutlineStyledLabelProvider)

The ABS outline label provider (implements ILabelProvider interface) is used to map objects from the TreeViewer's model to a String representation as well as an optional image or icon. A TreeViewer uses an ILabelProvider to get a String representation of its internal model.

Relevant methods for the basic ILabelProvider:

  • Image getImage(Object element)
  • String getText(Object element).

The getImage method is provided with an Object that is a member of the TreeViewer and should return an image that is used to identify the object. If the Icon is included in the plug-in's jar file, an Image can be loaded with the following method:

/**
 * Retrieves an image specified by a path <b>LOCAL</b> to the plug-in  
 * @param path The Path of the image local to the plug-in bundle (jar file)
 * @return The desired Image or a default image, if the desired image was not found;
 */
public static Image createImage(String path){
        Bundle bundle = Platform.getBundle(Constants.PLUGIN_ID);
        IPath imagepath = new Path(path);
        URL imageUrl = FileLocator.find(bundle, imagepath,null);
        ImageDescriptor id = ImageDescriptor.createFromURL(imageUrl);
        Image im = id.createImage();
        return im;
}

If the Strings should be colored, a "normal" ILabelProvider is not enough. To provide coloured outputs, following steps have to be taken:

  1. Create Stylers.
    • StyledStrings need Stylers to obtain their text style and color information. They can be created using StyledString.createColorRegistryStyler(String fgColor, String bgColor) where fgColor and bgColors are color definitions stored in the ColorRegistry (see Activator.initializeColors() method)
  2. Provide a method that gives a StyledString for an Object
    • For simple Strings with only one color you can use:
      StyledString st = new StyledString("uncoloredString",Styler)
    • For more complex Strings that contain more than one color use:
      StyledString st = new StyledString();
      st.append("uncoloredString", Styler)
  3. The extended Label provider must extend the org.eclipse.jface.viewers.StyledLabelCellProvider class and has to override the update(ViewerCell cell) method with the following code:
    @Override
    public void update(ViewerCell cell) {
            Object obj = cell.getElement();
    
            //Get the StyledString of the object here...
            StyledString styledString = ...;
    
            cell.setText(styledString.toString());
            cell.setStyleRanges(styledString.getStyleRanges());
            cell.setImage(getImage(obj));
            super.update(cell);
    }

ABS outline filters

The buttons for enabling content outline filters and sorters are added using the menuContribution sub-element of the org.eclipse.ui.menus extension point. The right locationURI to add buttons to the outline view is

toolbar:org.eclipse.ui.views.ContentOutline?after=additions

and the button types are toggle buttons. Each of the buttons has a command attached defined by the org.eclipse.commands extension point.

Example: Definition of the sort outline command:

<command
         defaultHandler="eu.hatsproject.absplugin.editor.outline.handlers.ABSContentOutlineSortHandler"
         description="Sorts the content outline view alphabetically"
         id="eu.hatsproject.absplugin.sortCommand"
         name="Sort">
  <state
        class="org.eclipse.ui.handlers.RegistryToggleState:false"
        id="org.eclipse.ui.commands.toggleState">
  </state>
</command>

Note that the command has a pre-defined toggle state attached that is used to determine the current state of the toggle button. The state of a toggle button can be determined using the HandlerUtil.toggleCommandState(String commandId) Moreover, this pre-defined toggle state is persistable and is stored over different eclipse sessions.

In addition to the button and command definition in the plugin.xml, each command needs a Handler class (extends AbstractHandler implements IHandler) that are defined in eu.hatsproject.absplugin.editor.outline.handlers.*

Basically, these handlers are responsible for setting a org.eclipse.jface.viewers.ViewerFilter or org.eclipse.jface.viewers.ViewerComparator to the TreeViewer of the content outline page. ViewerFilters are set using the TreeViewer's setFilters(ViewerFilter[]) method and a ViewerSorter is set using the setComparator(ViewerComparator)

The ViewerFilters and ViewerComparators are stored in the ABSContentOutlineFiltersAndComparators class.