FishEye Gutter Renderer Plugin Tutorial

This tutorial teaches you how to add extra information to annotated views of files, and to diffs

Plugin Source

We encourage you to work through this tutorial. If you want to skip ahead or check your work when you are done, you can find the plugin source code on Atlassian Bitbucket. Bitbucket serves a public Git repository containing the tutorial's code. To clone the repository, issue the following command:

$ git clone https://atlassian_tutorial@bitbucket.org/atlassian_tutorial/fecru-gutter-tutorial.git

Alternatively, you can download the source using the Downloads page here: https://bitbucket.org/atlassian_tutorial/fecru-gutter-tutorial

Introduction To Gutter Renderers

A gutter renderer should not be performing time-consuming analysis of code at render time – if (for instance) you wished to perform style checking of code and report issues with a gutter renderer, the analysis would be best done either in an external system (e.g. your continuous integration server) or with an Event Listener. The stored results from the analysis would be used by the gutter renderer.

A gutter renderer plugin adds an extra column in the form of a <td> tag at the left hand side of the text of annotated file views and diff views.

The plugin controls the HTML class of the td, can give it a style (to avoid the need to provide a custom CSS file) and of course provides the HTML contained by the td.

Structure of a Gutter Renderer

Writing a gutter renderer requires that you create implementations of three interfaces:

  • GutterRenderer– This interface is called once per file to be decorated.
    • It has two methods, both named getAnnotationDecorators.
    • One is called for annotated files, and returns a List of LineDecorators.
    • The other is called when a diff is being displayed, and returns a List of DiffLineDecorators.
    • If your implementation is called for a file/diff it doesn't wish to decorate then it must return an empty list.
    • Of course you can return different concrete implementations of the decorator classes for different files/diffs.
  • LineDecorator – The implementation returned by getAnnotationDecorators has its decorateLine method called once for each line in the file. It must return a GutterRenderResult instance.
  • DiffLineDecorator – The implementation returned by getAnnotationDecorators has one of its decorateLine/Added/Changed/Common/Removed methods called for each line of the diff. The method called depends on the type of changes which occurred in that line. These methods all return a GutterRenderResult instance.

A Sample Gutter Renderer

The gutter renderer we develop in this tutorial will simply display some text on the nth line of each file whose name contains the letter 'a', where n is the number of characters in the name. It will not provide any decoration for diffs.

The GutterRenderer implementation looks like this:

public class TutorialGutterRenderer implements GutterRenderer {

    public List<LineDecorator> getAnnotationDecorators(String repository, String path, String rev) {
        String fileName = path.substring(path.lastIndexOf('/')+1);
        if (fileName.matches(".*[aA].*")) {
            return Collections.<LineDecorator>singletonList(new TutorialLineDecorator(fileName.length()));
        } else {
            return Collections.emptyList();
        }
    }

    public List<DiffLineDecorator> getAnnotationDecorators(DiffType diffType, String repository, String fromPath, String fromRev, String toPath, String toRev) {
        return Collections.emptyList();
    }
}

and the LineDecorator implementation looks like this:

public class TutorialLineDecorator implements LineDecorator {
    private final int lineToDecorate;

    public TutorialLineDecorator(int lineToDecorate) {
        this.lineToDecorate = lineToDecorate;
    }

    public int getWidth() {
        return 10; // the width required for this gutter column, in ems
    }

    public GutterRenderResult decorateLine(int i) {
        GutterRenderResult r = new GutterRenderResult();
        if (i == lineToDecorate) {
            r.setInnerHtml("Decoration!");
        }
        return r;
    }
}
Was this page helpful?

Have a question about this article?

See questions about this article

Powered by Confluence and Scroll Viewport