Skip to content

Commit c52c492

Browse files
committed
add suggested chaanges
1 parent cab59cd commit c52c492

File tree

4 files changed

+150
-3
lines changed

4 files changed

+150
-3
lines changed

app/src/processing/app/ui/Editor.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2945,4 +2945,13 @@ public void show(Component component, int x, int y) {
29452945
super.show(component, x, y);
29462946
}
29472947
}
2948+
2949+
/**
2950+
* Called when clicking on the version number in the footer.
2951+
* Return a string with diagnostic info from the sketch,
2952+
* or empty string (or null) if not implemented/available.
2953+
*/
2954+
public String getSketchDiagnostics() {
2955+
return "";
2956+
}
29482957
}

app/src/processing/app/ui/EditorFooter.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public void mousePressed(MouseEvent e) {
109109
Base.DEBUG = !Base.DEBUG;
110110
editor.updateDevelopMenu();
111111
}
112-
copyDebugInformationToClipboard();
112+
copyFullDiagnosticsToClipboard();
113113
}
114114
});
115115

@@ -120,13 +120,23 @@ public void mousePressed(MouseEvent e) {
120120
updateTheme();
121121
}
122122

123-
public static void copyDebugInformationToClipboard() {
124-
var debugInformation = String.join("\n",
123+
public static String getSystemDebugInformation() {
124+
return String.join("\n",
125125
"Version: " + Base.getVersionName(),
126126
"Revision: " + Base.getRevision(),
127127
"OS: " + System.getProperty("os.name") + " " + System.getProperty("os.version") + " " + System.getProperty("os.arch"),
128128
"Java: " + System.getProperty("java.version") + " " + System.getProperty("java.vendor")
129129
);
130+
}
131+
132+
public static void copyDebugInformationToClipboard() {
133+
var stringSelection = new StringSelection(getSystemDebugInformation());
134+
var clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard();
135+
clipboard.setContents(stringSelection, null);
136+
}
137+
138+
public void copyFullDiagnosticsToClipboard() {
139+
var debugInformation = getSystemDebugInformation() + "\n\n" + editor.getSketchDiagnostics();
130140
var stringSelection = new StringSelection(debugInformation);
131141
var clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard();
132142
clipboard.setContents(stringSelection, null);

java/src/processing/mode/java/JavaEditor.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2234,4 +2234,14 @@ static private int howManyFloats(List<List<Handle>> handles) {
22342234
}
22352235
return count;
22362236
}
2237+
2238+
@Override
2239+
public String getSketchDiagnostics() {
2240+
if (debugger.isStarted()) {
2241+
return debugger.getDiagnostics();
2242+
} else if (runtime != null) {
2243+
return Debugger.getDiagnostics(runtime);
2244+
}
2245+
return super.getSketchDiagnostics();
2246+
}
22372247
}

java/src/processing/mode/java/debug/Debugger.java

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import java.awt.event.KeyEvent;
3232
import java.io.*;
3333
import java.util.ArrayList;
34+
import java.util.Collections;
3435
import java.util.HashMap;
3536
import java.util.HashSet;
3637
import java.util.Iterator;
@@ -468,6 +469,123 @@ public synchronized void stepOut() {
468469
}
469470

470471

472+
473+
/**
474+
* Get diagnostics from the sketch, whether paused or running.
475+
* If running, it will temporarily suspend the VM.
476+
*/
477+
public String getDiagnostics() {
478+
return getDiagnostics(runtime);
479+
}
480+
481+
482+
/**
483+
* Static helper to fetch diagnostics from a Runner, even if not debugging.
484+
* Uses field reads instead of method invocations to avoid thread state issues.
485+
*/
486+
public static String getDiagnostics(Runner targetRuntime) {
487+
if (targetRuntime == null) return "";
488+
VirtualMachine targetVM = targetRuntime.vm();
489+
if (targetVM == null) return "";
490+
491+
targetVM.suspend();
492+
try {
493+
// Find the PApplet subclass
494+
List<ReferenceType> pAppletClasses = targetVM.classesByName("processing.core.PApplet");
495+
if (pAppletClasses.isEmpty()) {
496+
return "processing.core.PApplet not found in VM";
497+
}
498+
ClassType pAppletBase = (ClassType) pAppletClasses.get(0);
499+
500+
ClassType sketchClass = null;
501+
for (ReferenceType type : targetVM.allClasses()) {
502+
if (type instanceof ClassType) {
503+
ClassType ct = (ClassType) type;
504+
ClassType superclass = ct.superclass();
505+
while (superclass != null) {
506+
if (superclass.equals(pAppletBase)) {
507+
sketchClass = ct;
508+
break;
509+
}
510+
superclass = superclass.superclass();
511+
}
512+
if (sketchClass != null) break;
513+
}
514+
}
515+
516+
if (sketchClass == null) {
517+
return "Could not find sketch class extending PApplet";
518+
}
519+
520+
// Find instance
521+
List<ObjectReference> instances = sketchClass.instances(1);
522+
if (instances.isEmpty()) {
523+
return "No instance of " + sketchClass.name() + " found";
524+
}
525+
ObjectReference appletInstance = instances.get(0);
526+
527+
// Build diagnostics by reading fields directly (no thread required)
528+
StringBuilder diag = new StringBuilder();
529+
diag.append("Sketch Diagnostics:\n");
530+
diag.append(" Class: ").append(sketchClass.name()).append("\n");
531+
532+
// Read PApplet fields
533+
appendField(diag, appletInstance, pAppletBase, "width");
534+
appendField(diag, appletInstance, pAppletBase, "height");
535+
appendField(diag, appletInstance, pAppletBase, "pixelDensity");
536+
appendField(diag, appletInstance, pAppletBase, "frameCount");
537+
appendField(diag, appletInstance, pAppletBase, "frameRate");
538+
appendField(diag, appletInstance, pAppletBase, "focused");
539+
540+
// Try to get renderer class name from 'g' field (PGraphics)
541+
try {
542+
Field gField = pAppletBase.fieldByName("g");
543+
if (gField != null) {
544+
Value gValue = appletInstance.getValue(gField);
545+
if (gValue instanceof ObjectReference) {
546+
ObjectReference graphics = (ObjectReference) gValue;
547+
diag.append(" renderer: ").append(graphics.referenceType().name()).append("\n");
548+
}
549+
}
550+
} catch (Exception e) {
551+
diag.append(" renderer: (unavailable)\n");
552+
}
553+
554+
return diag.toString();
555+
556+
} catch (Exception e) {
557+
return "Error gathering diagnostics: " + e.toString();
558+
} finally {
559+
targetVM.resume();
560+
}
561+
}
562+
563+
/**
564+
* Helper to append a field value to the diagnostics string.
565+
*/
566+
private static void appendField(StringBuilder sb, ObjectReference obj, ClassType type, String fieldName) {
567+
try {
568+
Field field = type.fieldByName(fieldName);
569+
if (field != null) {
570+
Value value = obj.getValue(field);
571+
sb.append(" ").append(fieldName).append(": ");
572+
if (value == null) {
573+
sb.append("null");
574+
} else if (value instanceof com.sun.jdi.PrimitiveValue) {
575+
sb.append(value.toString());
576+
} else if (value instanceof StringReference) {
577+
sb.append(((StringReference) value).value());
578+
} else {
579+
sb.append(value.toString());
580+
}
581+
sb.append("\n");
582+
}
583+
} catch (Exception e) {
584+
sb.append(" ").append(fieldName).append(": (error: ").append(e.getMessage()).append(")\n");
585+
}
586+
}
587+
588+
471589
/**
472590
* Gather system diagnostics from the running sketch.
473591
* <p>

0 commit comments

Comments
 (0)