mirror of
https://github.com/processing/processing4.git
synced 2026-02-04 06:09:17 +01:00
@@ -29,6 +29,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -68,7 +69,7 @@ public class Debugger {
|
||||
protected ReferenceType mainClass;
|
||||
|
||||
/// holds all loaded classes in the debuggee VM
|
||||
protected Set<ReferenceType> classes = new HashSet<>();
|
||||
protected Set<ReferenceType> classes = new LinkedHashSet<>();
|
||||
|
||||
/// listeners for class load events
|
||||
protected List<ClassLoadListener> classLoadListeners = new ArrayList<>();
|
||||
@@ -124,24 +125,12 @@ public class Debugger {
|
||||
|
||||
|
||||
/**
|
||||
* Get the {@link ReferenceType} for a class name.
|
||||
* @param name the class name
|
||||
* @return the {@link ReferenceType} or null if not found
|
||||
* (e.g. not yet loaded)
|
||||
* Get the main and nested {@link ReferenceType}s for the sketch.
|
||||
* @return a list of main and nested {@link ReferenceType}s,
|
||||
* empty list if nothing found (e.g. not yet loaded)
|
||||
*/
|
||||
public ReferenceType getClass(String name) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
if (name.equals(mainClassName)) {
|
||||
return mainClass;
|
||||
}
|
||||
for (ReferenceType rt : classes) {
|
||||
if (rt.name().equals(name)) {
|
||||
return rt;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
public Set<ReferenceType> getClasses() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
|
||||
@@ -239,6 +228,11 @@ public class Debugger {
|
||||
editor.variableInspector().lock();
|
||||
if (runtime != null) {
|
||||
Messages.log("closing runtime");
|
||||
|
||||
for (LineBreakpoint bp : breakpoints) {
|
||||
bp.detach();
|
||||
}
|
||||
|
||||
runtime.close();
|
||||
runtime = null;
|
||||
//build = null;
|
||||
@@ -563,21 +557,25 @@ public class Debugger {
|
||||
}
|
||||
}
|
||||
|
||||
private void createClassPrepareRequest(String name) {
|
||||
ClassPrepareRequest classPrepareRequest = runtime.vm().eventRequestManager().createClassPrepareRequest();
|
||||
classPrepareRequest.addClassFilter(name);
|
||||
classPrepareRequest.enable();
|
||||
}
|
||||
|
||||
|
||||
private void vmStartEvent() {
|
||||
// break on main class load
|
||||
log("requesting event on main class load: " + mainClassName);
|
||||
ClassPrepareRequest mainClassPrepare = runtime.vm().eventRequestManager().createClassPrepareRequest();
|
||||
mainClassPrepare.addClassFilter(mainClassName);
|
||||
mainClassPrepare.enable();
|
||||
|
||||
createClassPrepareRequest(mainClassName);
|
||||
createClassPrepareRequest(mainClassName + "$*");
|
||||
// break on loading custom classes
|
||||
for (SketchCode tab : editor.getSketch().getCode()) {
|
||||
if (tab.isExtension("java")) {
|
||||
log("requesting event on class load: " + tab.getPrettyName());
|
||||
ClassPrepareRequest customClassPrepare = runtime.vm().eventRequestManager().createClassPrepareRequest();
|
||||
customClassPrepare.addClassFilter(tab.getPrettyName());
|
||||
customClassPrepare.enable();
|
||||
String name = tab.getPrettyName();
|
||||
createClassPrepareRequest(name);
|
||||
createClassPrepareRequest(name + "$*");
|
||||
}
|
||||
}
|
||||
runtime.vm().resume();
|
||||
@@ -592,6 +590,7 @@ public class Debugger {
|
||||
if (rt.name().equals(mainClassName)) {
|
||||
//printType(rt);
|
||||
mainClass = rt;
|
||||
classes.add(rt);
|
||||
log("main class load: " + rt.name());
|
||||
started = true; // now that main class is loaded, we're started
|
||||
} else {
|
||||
|
||||
@@ -29,6 +29,7 @@ import processing.mode.java.Debugger;
|
||||
import com.sun.jdi.AbsentInformationException;
|
||||
import com.sun.jdi.Location;
|
||||
import com.sun.jdi.ReferenceType;
|
||||
import com.sun.jdi.VMDisconnectedException;
|
||||
import com.sun.jdi.request.BreakpointRequest;
|
||||
|
||||
|
||||
@@ -40,7 +41,7 @@ public class LineBreakpoint implements ClassLoadListener {
|
||||
protected Debugger dbg; // the debugger
|
||||
protected LineID line; // the line this breakpoint is set on
|
||||
protected BreakpointRequest bpr; // the request on the VM's event request manager
|
||||
protected ReferenceType theClass; // the class containing this breakpoint, null when not yet loaded
|
||||
protected String className;
|
||||
|
||||
|
||||
/**
|
||||
@@ -56,9 +57,9 @@ public class LineBreakpoint implements ClassLoadListener {
|
||||
this.line = line;
|
||||
line.startTracking(dbg.getEditor().getTab(line.fileName()).getDocument());
|
||||
this.dbg = dbg;
|
||||
theClass = dbg.getClass(className()); // try to get the class immediately, may return null if not yet loaded
|
||||
this.className = className();
|
||||
set(); // activate the breakpoint (show highlight, attach if debugger is running)
|
||||
Messages.log("LBP Created " + toString() + " class: " + className());
|
||||
Messages.log("LBP Created " + toString() + " class: " + this.className);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,48 +95,61 @@ public class LineBreakpoint implements ClassLoadListener {
|
||||
/**
|
||||
* Attach this breakpoint to the VM. Creates and enables a
|
||||
* {@link BreakpointRequest}. VM needs to be paused.
|
||||
*
|
||||
* @param theClass class to attach to
|
||||
* @return true on success
|
||||
*/
|
||||
protected void attach() {
|
||||
if (!dbg.isPaused()) {
|
||||
log("can't attach breakpoint, debugger not paused");
|
||||
return;
|
||||
protected boolean attach(ReferenceType theClass) {
|
||||
|
||||
if (theClass == null || className == null ||
|
||||
!className.equals(parseTopLevelClassName(theClass.name()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (theClass == null) {
|
||||
log("can't attach breakpoint, class not loaded: " + className());
|
||||
return;
|
||||
log("trying to attach: " + line.fileName + ":" + line.lineIdx + " to " + theClass.name());
|
||||
|
||||
if (!dbg.isPaused()) {
|
||||
log("can't attach breakpoint, debugger not paused");
|
||||
return false;
|
||||
}
|
||||
|
||||
// find line in java space
|
||||
LineID javaLine = dbg.sketchToJavaLine(line);
|
||||
if (javaLine == null) {
|
||||
log("couldn't find line " + line + " in the java code");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
log("BPs of class: " + theClass + ", line " + (javaLine.lineIdx() + 1));
|
||||
List<Location> locations = theClass.locationsOfLine(javaLine.lineIdx() + 1);
|
||||
if (locations.isEmpty()) {
|
||||
log("no location found for line " + line + " -> " + javaLine);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
// use first found location
|
||||
bpr = dbg.vm().eventRequestManager().createBreakpointRequest(locations.get(0));
|
||||
bpr.enable();
|
||||
log("attached breakpoint to " + line + " -> " + javaLine);
|
||||
return true;
|
||||
} catch (AbsentInformationException ex) {
|
||||
Messages.loge(null, ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isAttached() {
|
||||
return bpr != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach this breakpoint from the VM. Deletes the
|
||||
* {@link BreakpointRequest}.
|
||||
*/
|
||||
protected void detach() {
|
||||
public void detach() {
|
||||
if (bpr != null) {
|
||||
dbg.vm().eventRequestManager().deleteEventRequest(bpr);
|
||||
try {
|
||||
dbg.vm().eventRequestManager().deleteEventRequest(bpr);
|
||||
} catch (VMDisconnectedException ignore) { }
|
||||
bpr = null;
|
||||
}
|
||||
}
|
||||
@@ -148,9 +162,11 @@ public class LineBreakpoint implements ClassLoadListener {
|
||||
protected void set() {
|
||||
dbg.addClassLoadListener(this); // class may not yet be loaded
|
||||
dbg.getEditor().addBreakpointedLine(line);
|
||||
if (theClass != null && dbg.isPaused()) { // class is loaded
|
||||
// immediately activate the breakpoint
|
||||
attach();
|
||||
if (className != null && dbg.isPaused()) { // debugging right now, try to attach
|
||||
for (ReferenceType rt : dbg.getClasses()) {
|
||||
// try to attach to all top level or nested classes
|
||||
if (attach(rt)) break;
|
||||
}
|
||||
}
|
||||
if (dbg.getEditor().isInCurrentTab(line)) {
|
||||
dbg.getEditor().getSketch().setModified(true);
|
||||
@@ -191,12 +207,7 @@ public class LineBreakpoint implements ClassLoadListener {
|
||||
protected String className() {
|
||||
if (line.fileName().endsWith(".pde")) {
|
||||
// standard tab
|
||||
ReferenceType mainClass = dbg.getMainClass();
|
||||
//System.out.println(dbg.getMainClass().name());
|
||||
if (mainClass == null) {
|
||||
return null;
|
||||
}
|
||||
return dbg.getMainClass().name();
|
||||
return dbg.getEditor().getSketch().getName();
|
||||
}
|
||||
|
||||
if (line.fileName().endsWith(".java")) {
|
||||
@@ -215,17 +226,18 @@ public class LineBreakpoint implements ClassLoadListener {
|
||||
*/
|
||||
@Override
|
||||
public void classLoaded(ReferenceType theClass) {
|
||||
// check if our class is being loaded
|
||||
Messages.log("Class Loaded: " + theClass.name());
|
||||
if (theClass.name().equals(className())) {
|
||||
this.theClass = theClass;
|
||||
attach();
|
||||
}
|
||||
for (ReferenceType ct : theClass.nestedTypes()) {
|
||||
Messages.log("Nested " + ct.name());
|
||||
if (!isAttached()) {
|
||||
// try to attach
|
||||
attach(theClass);
|
||||
}
|
||||
}
|
||||
|
||||
public String parseTopLevelClassName(String name) {
|
||||
// Get rid of nested class name
|
||||
int dollar = name.indexOf('$');
|
||||
return (dollar == -1) ? name : name.substring(0, dollar);
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
Reference in New Issue
Block a user