Mike Morearty
07 Jun 2006

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

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

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.

comments powered by Disqus