Implement our own RhinoDebugger subclass to display scripts in a nice table.
The current implementation is merged from helma_1_4 branch and a bit quirky in regard to repository script source names
This commit is contained in:
parent
fb04c05289
commit
f7e929441c
3 changed files with 276 additions and 11 deletions
|
@ -17,6 +17,8 @@
|
|||
package helma.scripting.rhino;
|
||||
|
||||
import helma.scripting.rhino.extensions.*;
|
||||
import helma.scripting.rhino.debug.HelmaDebugger;
|
||||
import helma.scripting.rhino.debug.ScopeProvider;
|
||||
import helma.framework.core.*;
|
||||
import helma.framework.repository.Resource;
|
||||
import helma.objectmodel.*;
|
||||
|
@ -27,8 +29,6 @@ import helma.util.CacheMap;
|
|||
import helma.util.SystemMap;
|
||||
import helma.util.WrappedMap;
|
||||
import org.mozilla.javascript.*;
|
||||
import org.mozilla.javascript.tools.debugger.Main;
|
||||
import org.mozilla.javascript.tools.debugger.ScopeProvider;
|
||||
|
||||
import java.io.*;
|
||||
import java.text.*;
|
||||
|
@ -65,7 +65,7 @@ public final class RhinoCore implements ScopeProvider {
|
|||
// Any error that may have been found in global code
|
||||
String globalError;
|
||||
|
||||
Main debugger = null;
|
||||
HelmaDebugger debugger = null;
|
||||
|
||||
/**
|
||||
* Create a Rhino evaluator for the given application and request evaluator.
|
||||
|
@ -86,12 +86,7 @@ public final class RhinoCore implements ScopeProvider {
|
|||
|
||||
// Set up visual debugger if rhino.debug = true
|
||||
if ("true".equals(app.getProperty("rhino.debug"))) {
|
||||
debugger = new Main(app.getName() + " Debugger");
|
||||
debugger.setScopeProvider(this);
|
||||
debugger.pack();
|
||||
debugger.setVisible(true);
|
||||
debugger.contextCreated(context);
|
||||
debugger.contextEntered(context);
|
||||
initDebugger(context);
|
||||
}
|
||||
|
||||
// Set default optimization level according to whether debugger is on
|
||||
|
@ -153,6 +148,19 @@ public final class RhinoCore implements ScopeProvider {
|
|||
}
|
||||
}
|
||||
|
||||
void initDebugger(Context context) {
|
||||
if (debugger == null) {
|
||||
debugger = new HelmaDebugger(app.getName());
|
||||
debugger.setScopeProvider(this);
|
||||
debugger.pack();
|
||||
debugger.setLocation(60, 60);
|
||||
}
|
||||
if (!debugger.isVisible())
|
||||
debugger.setVisible(true);
|
||||
debugger.contextCreated(context);
|
||||
debugger.contextEntered(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the evaluator, making sure the minimum type information
|
||||
* necessary to bootstrap the rest is parsed.
|
||||
|
|
|
@ -156,8 +156,7 @@ public class RhinoEngine implements ScriptingEngine {
|
|||
|
||||
// if visual debugger is on let it know we're entering a context
|
||||
if (core.debugger != null) {
|
||||
core.debugger.contextCreated(context);
|
||||
core.debugger.contextEntered(context);
|
||||
core.initDebugger(context);
|
||||
}
|
||||
|
||||
if ("true".equals(app.getProperty("rhino.trace"))) {
|
||||
|
|
258
src/helma/scripting/rhino/debug/HelmaDebugger.java
Normal file
258
src/helma/scripting/rhino/debug/HelmaDebugger.java
Normal file
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 1998-2003 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile$
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
package helma.scripting.rhino.debug;
|
||||
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.debug.DebuggableScript;
|
||||
import org.mozilla.javascript.debug.DebugFrame;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.tree.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.*;
|
||||
|
||||
import helma.util.StringUtils;
|
||||
|
||||
public class HelmaDebugger extends Main implements TreeSelectionListener {
|
||||
|
||||
JTree tree;
|
||||
JList list;
|
||||
DebuggerTreeNode treeRoot;
|
||||
DefaultTreeModel treeModel;
|
||||
HashMap treeNodes = new HashMap();
|
||||
HashMap scripts = new HashMap();
|
||||
|
||||
public HelmaDebugger(String name) {
|
||||
super(name);
|
||||
Container contentPane = getContentPane();
|
||||
Component main = contentPane.getComponent(1);
|
||||
contentPane.remove(main);
|
||||
|
||||
treeRoot = new DebuggerTreeNode(name);
|
||||
tree = new JTree(treeRoot);
|
||||
treeModel = new DefaultTreeModel(treeRoot);
|
||||
tree.setModel(treeModel);
|
||||
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
|
||||
tree.addTreeSelectionListener(this);
|
||||
// tree.setRootVisible(false);
|
||||
// track double clicks
|
||||
tree.addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(MouseEvent evt) {
|
||||
openScript(tree.getSelectionPath());
|
||||
}
|
||||
});
|
||||
// track enter key
|
||||
tree.addKeyListener(new KeyAdapter() {
|
||||
public void keyPressed(KeyEvent evt) {
|
||||
if (evt.getKeyCode() == KeyEvent.VK_ENTER)
|
||||
openScript(tree.getSelectionPath());
|
||||
}
|
||||
});
|
||||
JScrollPane treeScroller = new JScrollPane(tree);
|
||||
treeScroller.setPreferredSize(new Dimension(180, 300));
|
||||
|
||||
list = new JList();
|
||||
// no bold font lists for me, thanks
|
||||
list.setFont(list.getFont().deriveFont(Font.PLAIN));
|
||||
list.addMouseListener(new MouseAdapter() {
|
||||
public void mouseClicked(MouseEvent evt) {
|
||||
openFunction((String) list.getSelectedValue());
|
||||
}
|
||||
});
|
||||
list.addKeyListener(new KeyAdapter() {
|
||||
public void keyPressed(KeyEvent evt) {
|
||||
if (evt.getKeyCode() == KeyEvent.VK_ENTER)
|
||||
openFunction((String) list.getSelectedValue());
|
||||
}
|
||||
});
|
||||
JScrollPane listScroller = new JScrollPane(list);
|
||||
listScroller.setPreferredSize(new Dimension(180, 200));
|
||||
|
||||
JSplitPane split1 = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
|
||||
split1.setTopComponent(treeScroller);
|
||||
split1.setBottomComponent(listScroller);
|
||||
split1.setOneTouchExpandable(true);
|
||||
Main.setResizeWeight(split1, 0.66);
|
||||
|
||||
JSplitPane split2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
||||
split2.setLeftComponent(split1);
|
||||
split2.setRightComponent(main);
|
||||
split2.setOneTouchExpandable(true);
|
||||
contentPane.add(split2, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
public void setVisible(boolean b) {
|
||||
super.setVisible(b);
|
||||
// hide console window
|
||||
console.hide();
|
||||
}
|
||||
|
||||
public void handleCompilationDone(Context cx, DebuggableScript fnOrScript,
|
||||
String source) {
|
||||
String sourceName = fnOrScript.getSourceName();
|
||||
if (!treeNodes.containsKey(sourceName)) {
|
||||
createTreeNode(sourceName);
|
||||
}
|
||||
super.handleCompilationDone(cx, fnOrScript, source);
|
||||
}
|
||||
|
||||
void createTreeNode(String sourceName) {
|
||||
String[] path = StringUtils.split(sourceName, ":/\\");
|
||||
DebuggerTreeNode node = treeRoot;
|
||||
DebuggerTreeNode newNode = null;
|
||||
for (int i = 1; i < path.length; i++) {
|
||||
DebuggerTreeNode n = node.get(path[i]);
|
||||
if (n == null) {
|
||||
n = new DebuggerTreeNode(path[i]);
|
||||
node.add(n);
|
||||
if (newNode == null) newNode = n;
|
||||
}
|
||||
node = n;
|
||||
}
|
||||
treeNodes.put(sourceName, node);
|
||||
scripts.put(node, sourceName);
|
||||
if (newNode != null) {
|
||||
SwingUtilities.invokeLater(new NodeInserter(newNode));
|
||||
}
|
||||
}
|
||||
|
||||
void openScript(TreePath path) {
|
||||
if (path == null)
|
||||
return;
|
||||
Object node = path.getLastPathComponent();
|
||||
if (node == null)
|
||||
return;
|
||||
String script = (String) scripts.get(node);
|
||||
if (script == null)
|
||||
return;
|
||||
JInternalFrame w = (JInternalFrame) fileWindows.get(script);
|
||||
if (w != null) {
|
||||
try {
|
||||
if (w.isIcon())
|
||||
w.setMaximum(true);
|
||||
w.show();
|
||||
w.setSelected(true);
|
||||
} catch (Exception exc) {
|
||||
}
|
||||
} else {
|
||||
SourceInfo si = (SourceInfo) sourceNames.get(script);
|
||||
if (si == null) {
|
||||
System.out.println("debugger error: Couldn't find source: " + script);
|
||||
}
|
||||
swingInvoke(CreateFileWindow.action(this, si, -1));
|
||||
}
|
||||
// display functions for opened script file
|
||||
Vector functions = new Vector();
|
||||
Iterator it = functionNames.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
ScriptItem si = (ScriptItem) entry.getValue();
|
||||
if (script.equals(si.getSourceInfo().getUrl())) {
|
||||
functions.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
Collections.sort(functions);
|
||||
list.setListData(functions);
|
||||
}
|
||||
|
||||
void openFunction(String function) {
|
||||
if (function == null)
|
||||
return;
|
||||
ScriptItem item = (ScriptItem) functionNames.get(function);
|
||||
if (item != null) {
|
||||
SourceInfo si = item.getSourceInfo();
|
||||
String url = si.getUrl();
|
||||
int lineNumber = item.getFirstLine();
|
||||
FileWindow w = getFileWindow(url);
|
||||
if (w == null) {
|
||||
CreateFileWindow.action(this, si, lineNumber).run();
|
||||
w = getFileWindow(url);
|
||||
w.setPosition(-1);
|
||||
}
|
||||
int start = w.getPosition(lineNumber - 1);
|
||||
int end = w.getPosition(lineNumber) - 1;
|
||||
w.textArea.select(start);
|
||||
w.textArea.setCaretPosition(start);
|
||||
w.textArea.moveCaretPosition(end);
|
||||
try {
|
||||
if (w.isIcon())
|
||||
w.setMaximum(true);
|
||||
w.show();
|
||||
requestFocus();
|
||||
w.requestFocus();
|
||||
w.textArea.requestFocus();
|
||||
} catch (Exception exc) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode)
|
||||
tree.getLastSelectedPathComponent();
|
||||
|
||||
if (node == null) return;
|
||||
|
||||
Object script = scripts.get(node);
|
||||
if (script != null) {
|
||||
// openScript(script);
|
||||
}
|
||||
}
|
||||
|
||||
class DebuggerTreeNode extends DefaultMutableTreeNode {
|
||||
|
||||
public DebuggerTreeNode(Object obj) {
|
||||
super(obj);
|
||||
}
|
||||
|
||||
public DebuggerTreeNode get(String name) {
|
||||
Enumeration children = this.children();
|
||||
while (children.hasMoreElements()) {
|
||||
DebuggerTreeNode node = (DebuggerTreeNode) children.nextElement();
|
||||
if (node != null && name.equals(node.getUserObject()))
|
||||
return node;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class NodeInserter implements Runnable {
|
||||
MutableTreeNode node;
|
||||
|
||||
NodeInserter(MutableTreeNode node) {
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
MutableTreeNode parent = (MutableTreeNode) node.getParent();
|
||||
if (parent == treeRoot && treeRoot.getChildCount() == 1) {
|
||||
tree.makeVisible(new TreePath(new Object[]{parent, node}));
|
||||
}
|
||||
treeModel.insertNodeInto(node, parent, parent.getIndex(node));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue