Writing your own plugins for the Flex Builder debugger, part 2: a fully functional sample

Let’s write a plugin for the Flex Builder debugger. This will be a simple panel called Expression Tracker, which is like the Expressions view except that it does not refresh its displayed values each time you step. Don’t expect anything useful or beautiful here; this is just a barely-functional sample with a pretty rotten UI. But it’s a start.

I should warn you that creating Eclipse plugins takes a large investment of effort to understand how they fit together.

Eclipse cruft

You’ll need to be using the plugin-based version of Flex Builder rather than the standalone version. This means that first, you have to install Eclipse version 3.1.2 from http://www.eclipse.org. Then, you have to install the plugin version of Flex Builder:

installer.png

The standalone version of Flex Builder is only for writing and debugging Flex applications. But the plugin version is a set of plugins that you install on top of Eclipse, to enable the creation of Flex projects in addition to other types of projects. Flex Builder plugins are written in Java.

File > New > Project; Plug-in Development > Plug-in Project. Project name: “ExpressionTracker”. Click Next, then Next. Use the “Plug-in with a view” template, so Eclipse will fill in some boilerplate code for us:

plugin-template.png

Click Next, and change the classname and a few other settings as follows. The “View Class Name” is the name of the Java class; the “View Name” is the name displayed to the user in the tab for that view; and the “View Category ID” and “View Category Name” control where it shows up under “Window > Show View > Other”:

plugin-settings.png
The above settings will cause your view to show up in the “Flex” category of views. If you would rather have your plugin show up in the “Debug” category, then use a View Category ID of org.eclipse.debug.ui, and a view category name of “Debug”. Or, make your own new category if you want, such as “Acme Awesome Flex Extensions.”

Click Finish.

Let’s see what we have so far. Select the ExpressionConsole project in the Package Explorer view, then do Run > Run As > Eclipse Application. Then, in the newly launched Eclipse, Window > Show View > Other; Debug > Expression Tracker.

view1.png

Hey, it worked! Okay, now we get to the interesting part.

The interesting part

Start by opening ExpressionTrackerView.java and exploring for a bit. The various Eclipse templates are very useful for showing you how to hook everything together. In here, you will see some simple examples of context-menu commands, double-click handlers, and so on. Insert these two functions into ExpressionTrackerPlugin.java. You should put these in every Eclipse plugin you make, and whenever you have caught an exception that indicate an error condition, you should call <YourPluginClass>.log(), to send it to the “Error Log” view:
/**
 * Logs the given status to this plug-in's error log.
 *
 * @param message
 *            general message, e.g. "Error during initialization"
 * @param t
 *            exception associated with this error, or <code>null</code>
 */
public static void log(String message, Throwable t) {
  getDefault().getLog().log(createStatusError(message, t));
}

/**
 * Create and return an IStatus object with ERROR severity and the given
 * message and exception.
 */
public static IStatus createStatusError(String message, Throwable t) {
  if (message == null) {
    message = t.getLocalizedMessage();
    if (message == null)
      message = "";
  }
  return new Status(IStatus.ERROR, getDefault().getBundle()
    .getSymbolicName(), IStatus.ERROR, message, t);
}

Replace your ExpressionTrackerView.java with this completed version.

Let’s go through that new version and look at the interesting debugger-related parts. Given an expression, how do you get its value? Answer: You get a reference to Eclipse’s global “expression manager;” tell it to create an expression; tell that expression to evaluate itself in a specified context (stack frame); and then wait until Eclipse sends you an event telling you the evaluation has completed. The relevant source:

ExpressionTrackerView constructor: Start listening for all debug events.

public ExpressionTrackerView() {
  // We register to be notified of all debug-related events, so that
  // we will be notified whenever an expression has been evaluated.
  DebugPlugin.getDefault().addDebugEventListener(this);
}

ExpressionAndValue constructor: the user has said to add a new expression to the view. Create it, and tell it to evaluate itself.

// Get the expression manager, and create a new watch expression
IExpressionManager expressionManager = DebugPlugin.getDefault().getExpressionManager();
watchExpr = expressionManager.newWatchExpression(expr);

// Figure out the "context" of this watch expression -- that is, which
// stack frame is currently selected in Eclipse's "Debug" view?
IDebugElement debugElement = null;
IAdaptable debugContext = DebugUITools.getDebugContext();
if (debugContext != null)
  debugElement = (IDebugElement) debugContext.getAdapter(IDebugElement.class);

if (debugElement == null) {
  value = "<no debug context>";
} else {
  // Have the watch expression begin evaluating itself.  When it is
  // done, it will dispatch a DebugEvent, which we will see in our
  // handleDebugEvents() function.
  value = "...";
  watchExpr.setExpressionContext(debugElement);
  watchExpr.evaluate();
}

ExpressionTrackerView.handleDebugEvents(): Called by Eclipse whenever any debugger-related event takes place — a process starts or terminates, a breakpoint is hit, etc. Our code will look for debug events that indicate that one of our expressions has been evaluated, and when it has, call ExpressionAndValue.doneEvaluating():

public void handleDebugEvents(DebugEvent[] events) {
  for (int i=0; i<events.length; ++i) {
    DebugEvent event = events[i];
    if (event.getKind() == DebugEvent.CHANGE) {
      Object source = event.getSource();
      if (source instanceof IWatchExpression) {
        for (int j=0; j<items.size(); ++j) {
          ExpressionAndValue item = (ExpressionAndValue) items.get(j);
          if (item.watchExpr == source) {
            item.doneEvaluating();
            break;
          }
        }
      }
    }
  }
}

ExpressionAndValue.doneEvaluating(): Check if the expression evaluation encountered errors, such as syntax errors. If so, display the error; otherwise, display the vlaue.

if (watchExpr.hasErrors()) {
  String[] errorMessages = watchExpr.getErrorMessages();
  if (errorMessages.length > 0) {
    // We should really display all the error messages,
    // not just the first...
    this.value = errorMessages[0];
  } else {
    this.value = "Error";
  }
} else {
  IValue exprValue = watchExpr.getValue();
  if (exprValue != null)
    this.value = exprValue.getValueString();
  else
    this.value = "";
}

That is pretty much all the debugger-related functionality in the code. Give it a try now. Run a child instance of Eclipse again. Create a Flex Builder project. Open the Expression Tracker view. Right-click, and add an expression or two.

working.png

A masterpiece.

Publishing your masterpiece

The main thing you need to know is: File > Export > Deployable plug-ins and fragments. This command will package up your plugin in a form that is easy to publish.

11 Comments so far

Sam Robbins on June 8th, 2006

This is great! Thanks a ton for posting.

Sebastian on September 26th, 2006

Hi Mike,
I tryed to configure your sample for eclipse 3.2, but the plugin stopped running when ExpressionTrackerView.java should implement the ‘IDebugEventSetListener’ interface. Is there a larger change for Plugin-Development between Eclipse 3.1.2 and 3.2 ?

Regards

Ido on October 18th, 2006

Hi Mike,
Thanks for the post. It’s great.
I need to make something similar to what you need only I need the variable to referesh themself on every break point. I tried to add an event on the DebugHandler but it just doesn’t seems to work. any idea?

Thanks again,
Ido

mike on October 18th, 2006

Ido,

What you’re describing is the right way to do it — adding logic to the debug handler in handleDebugEvents(). You would then need to tell every expression to re-evaluate and display the new value.

Ido on October 18th, 2006

Hi Mike,
I tried that, But when I am debuggin a c++ program it only works for step over events. When I do resume (till the next breakpoint) I Can’t evaluate the watch expression value anymore. It doesn’t happen when I debug a regular java program only a c++ program but I thought it shouldn’t matter. Do you have any idea why?

mike on October 18th, 2006

Ido, you’re right it shouldn’t matter if it’s Java or C++. But I’ve never tried the CDT, so I’m not sure why it’s failing.

judah on September 15th, 2008

Hi Mike,

I’m trying to get this to work but the screens have changed so much I have no idea how to start. I downloaded eclipse yesterday as you advised to get the plug in development environment. Could you create a super simple no frills basic example? I personally don’t need screen shots but just the steps I need to get to a point where I can copy and paste your code and not get 100 errors.

[...] Builder Plug in and I’ve had no luck. The closest thing to any working tutorial I found is here. I have some great ideas I’d like to create. And although Eclipse has some great features it [...]

mike on September 19th, 2008

Judah, I just re-read this old blog post, and the only things that have changed are:

- The main class name of the plugin has changed from ExpressionTrackerPlugin.java to Activator.java

- The package name for ExpressionTrackerView.java now needs to be expressiontracker.views, with a lower case "t", instead of the old expressionTracker.views.

In addition, it looks like I forgot to mention that you need to make your plugin depend on Eclipse’s org.eclipse.debug.core and org.eclipse.debug.ui plugins. You do this by double-clicking META-INF/MANIFEST.MF, going to the Dependencies tab, and clicking Add.

With these changes, the original sample works for me.

judah on September 22nd, 2008

Hi Mike,
Thanks so much. But I didn’t even get that far. What I need help is in getting the project setup to begin with. I’m having trouble knowing where to map all these values in your example here to where they should go here, http://judahfrangipane.com/temp/plugin.png.

mike on September 22nd, 2008

You don’t need to modify any of the settings on that page. I don’t know, perhaps you clicked Finish instead of Next when going through the wizard, and are assuming that the "Main View Settings" dialog shown above no longer exists, and has been replaced by the one you linked to.

Posting your comment.

Leave a reply

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word


You are viewing a mobilized version of this site...
View original page here

How do you rate mobile version of this page?

Mobilized by Mowser Mowser