Wednesday, November 20, 2013

Debugger 8: Adding "Run to line" support

Dedicated Run to line support is quite easy to implement. Most parts are already provided by the debug framework, we only need to consume it in the right way.
  1. A fictional interpreter
  2. The launch framework
  3. A tale of debuggers, processes and threads
  4. Stepping, suspending and other actions
  5. UI breakpoint integration
  6. Debugger breakpoint integration
  7. Display current source code - source lookup
  8. Run to line support
  9. Displaying variables
  10. Displaying memory areas

Source code for this tutorial is available on googlecode as a single zip archive, as a Team Project Set or you can checkout the SVN projects directly.


Step 1: Implement editor support

To use the run to line functionality from the debug framework the source code editor needs to implement IRunToLineTarget.
package com.codeandme.textinterpreter.debugger;

public class RunToLineTarget implements IRunToLineTarget {

 @Override
 public void runToLine(IWorkbenchPart part, ISelection selection, ISuspendResume target) throws CoreException {
  if (target instanceof TextStackFrame) {
   IDebugTarget debugTarget = (IDebugTarget) ((IAdaptable) target).getAdapter(IDebugTarget.class);
   if (debugTarget instanceof TextDebugTarget) {
    IBreakpoint breakpoint = new TextRunToLineBreakpoint(((TextDebugTarget) debugTarget).getFile(), getLineNumber(selection));
    RunToLineHandler handler = new RunToLineHandler(debugTarget, target, breakpoint);
    handler.run(new NullProgressMonitor());
   }
  }
 }

 @Override
 public boolean canRunToLine(IWorkbenchPart part, ISelection selection, ISuspendResume target) {
  return (target instanceof TextStackFrame);
 }

 private static int getLineNumber(ISelection selection) {
  if (selection instanceof ITextSelection)
   // text selections are 0 based
   return ((ITextSelection) selection).getStartLine() + 1;

  return 0;
 }
}
On a runToLine() call we create a new TextRunToLineBreakpoint which the handler automatically activates. The only difference to a TextLineBreakpoint is that we set its PERSISTED flag to false.
That is everything we need to code for the Run to line functionality. Easy, isn't it?

The debug framework implementation also honors the preferences setting Run/Debug / Skip breakpoints during a 'Run to Line' operation. To me it seems as the implementation might be slightly buggy though. As the demo interpreter is lightning fast, conventional breakpoints will not be disabled fast enough sometimes and might still trigger.

Step 2: Register UI integration

To add the action into the editor context menu we need to add a new org.eclipse.ui.popupMenus extension point. Add a viewerContribution to it with id set to "textEditor.editorActions" and targetID set to "#TextEditorContext". Now add the Run to line action as provided in the screenshot.
For the text editor we furthermore need to register an adapter as it does not implement IRunToLineTarget natively. The RunToLineAdapter simply converts editors to IRunToLineTargets.

No comments:

Post a Comment