Published using Google Docs
7 - Interactivity
Updated automatically every 5 minutes

DEPRECATED, REFER TO THIS DOCUMENT.

JEB2 Developer Tutorial

7- Interactivity (Part 1)

Links:

Syntax Highlighting

Let’s dive deeper and implement the first thing we want to get from an editor: syntax highlighting. This will allow us to uncover more corners of the JEB2 API.

We will need to add item highlights on some parts of the text. Remember our sample, we will use only a single part:

function a() {

  alert("a called");

}

A standard editor highlights keywords: they are specific words (reserved, most of the time) that are related to a language. In JavaScript, they are “function”, “var”, “if”, “else”... Other interesting artifacts that could be highlighted are strings. In this tutorial, we will highlight functions, variables and strings surrounded by double-quotes.

We want to modify only the display, not interact with the model (eg, renaming, formatting), so we will only look at the ITextDocument. It has two important features:

Let’s concentrate on the ITextDocumentPart. The interface defines two methods:

Remember that a part represents a part of the document (for buffered document) or can include the whole document. So the list of lines can be all the lines or just the lines of a part. We won’t treat buffered document in this tutorial to keep things simple.

Once again, let’s check only the most important object, ILine. It contains:

We will need to add ITextItem to our current model. The TextItem default implementation can be used. It takes as argument:

Exercice 1: Download the Sample Code. Il already displays function using a special ItemClassIdentifiers. Try to do the same for var keyword and strings.

Plugin7-01.png

Notifications

JEB2 is a security-oriented product: its aim is to help you analyze malicious code and point to potential areas of interest. Notifications can be used to pinpoint areas that are noteworthy; styles can be attached to notifications to highlight their corresponding elements upon rendering, if any. Notifications are global to a unit, which means that the search for notification should not be done on rendering (document build phasis).

For the sake of this tutorial, we want to highlight the usage of function “alert” because it can block the UI unreasonably.

The AbstractUnit exposes the following method:

public addtNotifications(IUnitNotification unit);

We will use the default implementation: UnitNotification.

In the process() method of your JavaScript Unit, add the following snippet:

root.visit(new NodeVisitor() {

        @Override

        public boolean visit(AstNode node) {

                switch(node.getType()) {

                case Token.EXPR_VOID:

                case Token.EXPR_RESULT:

                break;

                case Token.CALL:

                visitTarget(((FunctionCall)node).getTarget());

                break;

                default:

                break;

                }

                return true;

        }

        private void visitTarget(AstNode target) {

                if(target.getType() == Token.NAME) {

                if(((Name)target).getIdentifier().equals("alert")) {

                    // Add notification

                    addNotification(

new UnitNotification(NotificationType.POTENTIALLY_HARMFUL,

String.format(“alert is detected at position %d",

target.getAbsolutePosition())));

                }

                }

        }

});

The visit() recursively process all the elements. When we have a JavaScript function call, we check the name and add a notification if it is “alert”.

Now, you should see something new in the UI:

Plugin7-02.png

Note: If you want to see all notifications at file opening, you will have to slightly modify your code. Since the process() method is only called on opening an IUnit, the best is to call it directly after IUnit creation:

public IUnit prepare(String name, IInput input, IUnitProcessor unitProcessor, IUnitCreator parent) {

            IUnit sampleUnit = new SampleUnit(name, input, unitProcessor, parent, pdm);

            sampleUnit.process(); // forces children calculation

            return sampleUnit;

}

Be careful to add this line somewhere in the process() method to indicate that the processing should not be done once again:

setProcessed(true);

Now, we see something interesting on the screenshot: there is an address column that is blank. IUnitNotification defines an addressing binding which can be used to jump to the related section. Let’s see how to use it.

Addressing

To be able to jump to a correct Address, we need to define a bind from Unit addressing (address) to a position in Document (coordinates).

ITextDocument uses ICoordinates: apart from anchor, it only needs the line number and the position in the line.

Addresses, however, are user-(in this context, the plugin developer) defined: it is up to user to define them and their granularity. For instance, you can choose to support addresses:

The important aspect of addresses is that an address must not be directly tied to a Document (your implementation of Document can change: if you change beautifier, if you decide to format your document on a single line, if you use a tree/table for your representation, etc.). Of course, there should still be a way to make the link between the two addressing systems:

Refer to the technical note JEB2 Parsers / Position for more details.

At last, an address must identify an object /position in a unique way. Otherwise, you wouldn’t know where to jump.

For our sample JavaScript plugin, we will use the addressing using AstNode.getAbsolutePosition(). When jumping from Notification Panel, we have the current address (Absolute position), and we will jump to an ICoordinates in the ITextDocument. So the main method to implement is:

public ICoordinates addressToCoordinates(String address);

Assignment 2: Try to implement this method.

There is also another column in the Notification Panel called “Label”: it represents the label of the address. You can indicate here a human readable label: for example, the name of the function.

To display label, we need to inherit from IInteractiveUnit and implement String getAddressLabel(String address) to see changes in the Notification Panel.

Assignment 3: Try to implement the getAddressLabel method.

A solution to all assignments can be found here.

You may have noticed that IInteractiveUnit provides a lot of methods. In the next part, we will focus on these methods and available user actions.

Next up in Part 8: Interactivity, Part 2

JEB © PNF Software, Inc.