From 00c57607d1f5750361bc9dd0af3b95145b13f883 Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Thu, 6 Feb 2025 22:47:58 +0100 Subject: [PATCH 1/2] Logging cleanup --- app/{src => ant}/processing/app/Messages.java | 0 app/src/processing/app/Base.java | 10 +- app/src/processing/app/Library.java | 23 +- app/src/processing/app/Messages.kt | 282 ++++++++++++++++++ app/src/processing/app/exec/StreamPump.java | 4 +- .../app/syntax/im/InputMethodSupport.java | 8 +- app/src/processing/app/ui/EditorConsole.java | 4 +- .../processing/mode/java/CompletionPanel.java | 2 +- .../processing/mode/java/PreprocService.java | 14 +- .../processing/mode/java/runner/Runner.java | 12 +- 10 files changed, 320 insertions(+), 39 deletions(-) rename app/{src => ant}/processing/app/Messages.java (100%) create mode 100644 app/src/processing/app/Messages.kt diff --git a/app/src/processing/app/Messages.java b/app/ant/processing/app/Messages.java similarity index 100% rename from app/src/processing/app/Messages.java rename to app/ant/processing/app/Messages.java diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index a5b3ac7c0c..4690c6946c 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -563,14 +563,12 @@ public Base(String[] args) throws Exception { cl.downloadAvailableList(this, new ContribProgress(null)); long t9 = System.currentTimeMillis(); - if (DEBUG) { - System.out.println("core modes: " + (t2b-t2) + - ", contrib modes: " + (t2c-t2b) + - ", contrib ex: " + (t2c-t2b)); - System.out.println("base took " + (t2-t1) + " " + (t3-t2) + " " + (t4-t3) + + Messages.log("core modes: " + (t2b-t2) + + ", contrib modes: " + (t2c-t2b) + + ", contrib ex: " + (t2c-t2b)); + Messages.log("base took " + (t2-t1) + " " + (t3-t2) + " " + (t4-t3) + " " + (t5-t4) + " t6-t5=" + (t6-t5) + " " + (t7-t6) + " handleNew=" + (t8-t7) + " " + (t9-t8) + " ms"); - } } diff --git a/app/src/processing/app/Library.java b/app/src/processing/app/Library.java index dc8269eeb9..e92ee8496d 100644 --- a/app/src/processing/app/Library.java +++ b/app/src/processing/app/Library.java @@ -330,6 +330,7 @@ static String[] listPlatformEntries(File libraryFolder, String folderName, Strin * imports to specific libraries. * @param importToLibraryTable mapping from package names to Library objects */ + static boolean instruced = false; // public void addPackageList(HashMap importToLibraryTable) { public void addPackageList(Map> importToLibraryTable) { // PApplet.println(packages); @@ -342,18 +343,20 @@ public void addPackageList(Map> importToLibraryTable) { libraries = new ArrayList<>(); importToLibraryTable.put(pkg, libraries); } else { - if (Base.DEBUG) { - System.err.println("The library found in"); - System.err.println(getPath()); - System.err.println("conflicts with"); + if(!instruced) { + instruced = true; + Messages.err("The library found in"); + Messages.err(getPath()); + Messages.err("conflicts with"); for (Library library : libraries) { - System.err.println(library.getPath()); + Messages.err(library.getPath()); } - System.err.println("which already define(s) the package " + pkg); - System.err.println("If you have a line in your sketch that reads"); - System.err.println("import " + pkg + ".*;"); - System.err.println("Then you'll need to first remove one of those libraries."); - System.err.println(); + Messages.err("which already define(s) the package " + pkg); + Messages.err("If you have a line in your sketch that reads"); + Messages.err("import " + pkg + ".*;"); + Messages.err("Then you'll need to first remove one of those libraries."); + }else{ + Messages.err("\tPackage ("+pkg+")\t conflict found in [" + name + "] with libraries: " + libraries.stream().map(Library::getName).reduce((a, b) -> a + ", " + b).orElse("")); } } libraries.add(this); diff --git a/app/src/processing/app/Messages.kt b/app/src/processing/app/Messages.kt new file mode 100644 index 0000000000..cae54e6e97 --- /dev/null +++ b/app/src/processing/app/Messages.kt @@ -0,0 +1,282 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* + Part of the Processing project - http://processing.org + + Copyright (c) 2015 The Processing Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +package processing.app + +import processing.app.ui.Toolkit +import java.awt.EventQueue +import java.awt.Frame +import java.io.PrintWriter +import java.io.StringWriter +import javax.swing.JFrame +import javax.swing.JOptionPane + +class Messages { + companion object { + /** + * "No cookie for you" type messages. Nothing fatal or all that + * much of a bummer, but something to notify the user about. + */ + @JvmStatic + fun showMessage(title: String = "Message", message: String) { + if (Base.isCommandLine()) { + println("$title: $message") + } else { + JOptionPane.showMessageDialog( + Frame(), message, title, + JOptionPane.INFORMATION_MESSAGE + ) + } + } + + + /** + * Non-fatal error message with optional stack trace side dish. + */ + /** + * Non-fatal error message. + */ + @JvmStatic + @JvmOverloads + fun showWarning(title: String = "Warning", message: String, e: Throwable? = null) { + if (Base.isCommandLine()) { + println("$title: $message") + } else { + JOptionPane.showMessageDialog( + Frame(), message, title, + JOptionPane.WARNING_MESSAGE + ) + } + e?.printStackTrace() + } + + /** + * Non-fatal error message with two levels of formatting. + * Unlike the others, this is non-blocking and will run later on the EDT. + */ + @JvmStatic + fun showWarningTiered( + title: String, + primary: String, secondary: String, + e: Throwable? + ) { + if (Base.isCommandLine()) { + // TODO All these messages need to be handled differently for + // proper parsing on the command line. Many have \n in them. + println("$title: $primary\n$secondary") + } else { + EventQueue.invokeLater { + JOptionPane.showMessageDialog( + JFrame(), + Toolkit.formatMessage(primary, secondary), + title, JOptionPane.WARNING_MESSAGE + ) + } + } + e?.printStackTrace() + } + + + /** + * Show an error message that's actually fatal to the program. + * This is an error that can't be recovered. Use showWarning() + * for errors that allow P5 to continue running. + */ + @JvmStatic + fun showError(title: String = "Error", message: String, e: Throwable?) { + if (Base.isCommandLine()) { + System.err.println("$title: $message") + } else { + JOptionPane.showMessageDialog( + Frame(), message, title, + JOptionPane.ERROR_MESSAGE + ) + } + e?.printStackTrace() + System.exit(1) + } + + + /** + * Warning window that includes the stack trace. + */ + @JvmStatic + fun showTrace( + title: String?, + message: String, + t: Throwable?, + fatal: Boolean + ) { + val title = title ?: if (fatal) "Error" else "Warning" + + if (Base.isCommandLine()) { + System.err.println("$title: $message") + t?.printStackTrace() + } else { + val sw = StringWriter() + t!!.printStackTrace(PrintWriter(sw)) + + JOptionPane.showMessageDialog( + Frame(), // first
clears to the next line + // second
is a shorter height blank space before the trace + Toolkit.formatMessage("$message

$sw
"), + title, + if (fatal) JOptionPane.ERROR_MESSAGE else JOptionPane.WARNING_MESSAGE + ) + + if (fatal) { + System.exit(1) + } + } + } + + @JvmStatic + fun showYesNoQuestion( + editor: Frame?, title: String?, + primary: String?, secondary: String? + ): Int { + if (!Platform.isMacOS()) { + return JOptionPane.showConfirmDialog( + editor, + Toolkit.formatMessage(primary, secondary), //"" + + //"" + primary + "" + + //"
" + secondary, + title, + JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE + ) + } else { + val result = showCustomQuestion( + editor, title, primary, secondary, + 0, "Yes", "No" + ) + return if (result == 0) { + JOptionPane.YES_OPTION + } else if (result == 1) { + JOptionPane.NO_OPTION + } else { + JOptionPane.CLOSED_OPTION + } + } + } + + + /** + * @param highlight A valid array index for options[] that specifies the + * default (i.e. safe) choice. + * @return The (zero-based) index of the selected value, -1 otherwise. + */ + @JvmStatic + fun showCustomQuestion( + editor: Frame?, title: String?, + primary: String?, secondary: String?, + highlight: Int, vararg options: String + ): Int { + val result: Any + if (!Platform.isMacOS()) { + return JOptionPane.showOptionDialog( + editor, + Toolkit.formatMessage(primary, secondary), title, + JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, + options, options[highlight] + ) + } else { + val pane = + JOptionPane( + Toolkit.formatMessage(primary, secondary), + JOptionPane.QUESTION_MESSAGE + ) + + pane.options = options + + // highlight the safest option ala apple hig + pane.initialValue = options[highlight] + + val dialog = pane.createDialog(editor, null) + dialog.isVisible = true + + result = pane.value + } + for (i in options.indices) { + if (result != null && result == options[i]) return i + } + return -1 + } + + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + @JvmStatic + @Deprecated("Use log() instead") + fun log(from: Any, message: String) { + if (Base.DEBUG) { + val callingClass = Throwable() + .stackTrace[2] + .className + .formatClassName() + println("$callingClass: $message") + } + } + + @JvmStatic + fun log(message: String?) { + if (Base.DEBUG) { + val callingClass = Throwable() + .stackTrace[2] + .className + .formatClassName() + println("$callingClass$message") + } + } + + @JvmStatic + fun logf(message: String?, vararg args: Any?) { + if (Base.DEBUG) { + val callingClass = Throwable() + .stackTrace[2] + .className + .formatClassName() + System.out.printf("$callingClass$message", *args) + } + } + + @JvmStatic + @JvmOverloads + fun err(message: String?, e: Throwable? = null) { + if (Base.DEBUG) { + if (message != null) { + val callingClass = Throwable() + .stackTrace[4] + .className + .formatClassName() + System.err.println("$callingClass$message") + } + e?.printStackTrace() + } + } + } +} + +// Helper functions to give the base classes a color +fun String.formatClassName() = this + .replace("processing.", "") + .replace(".", "/") + .padEnd(40) + .colorizePathParts() +fun String.colorizePathParts() = split("/").joinToString("/") { part -> + "\u001B[${31 + (part.hashCode() and 0x7).rem(6)}m$part\u001B[0m" +} \ No newline at end of file diff --git a/app/src/processing/app/exec/StreamPump.java b/app/src/processing/app/exec/StreamPump.java index 130a74afd3..29786102cc 100644 --- a/app/src/processing/app/exec/StreamPump.java +++ b/app/src/processing/app/exec/StreamPump.java @@ -13,6 +13,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import processing.app.Base; +import processing.app.Messages; /** @@ -79,8 +80,7 @@ public void run() { } } catch (final IOException e) { if (Base.DEBUG) { - System.err.println("StreamPump: " + name); - e.printStackTrace(System.err); + Messages.err("StreamPump: " + name, e); // removing for 0190, but need a better way to handle these throw new RuntimeException("Inside " + this + " for " + name, e); } diff --git a/app/src/processing/app/syntax/im/InputMethodSupport.java b/app/src/processing/app/syntax/im/InputMethodSupport.java index 391b96b97b..e3323fa110 100644 --- a/app/src/processing/app/syntax/im/InputMethodSupport.java +++ b/app/src/processing/app/syntax/im/InputMethodSupport.java @@ -79,9 +79,7 @@ public void setCallback(Callback callback) { @Override public Rectangle getTextLocation(TextHitInfo offset) { - if (Base.DEBUG) { - Messages.log("#Called getTextLocation:" + offset); - } + Messages.log("#Called getTextLocation:" + offset); int line = textArea.getCaretLine(); int offsetX = textArea.getCaretPosition() - textArea.getLineStartOffset(line); // '+1' mean textArea.lineToY(line) + textArea.getPainter().getFontMetrics().getHeight(). @@ -238,9 +236,7 @@ private TextLayout getTextLayout(AttributedCharacterIterator text, int committed RenderingHints.VALUE_TEXT_ANTIALIAS_ON : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); FontRenderContext frc = g2d.getFontRenderContext(); - if (Base.DEBUG) { - Messages.log("debug: FontRenderContext is Antialiased = " + frc.getAntiAliasingHint()); - } + Messages.log("debug: FontRenderContext is Antialiased = " + frc.getAntiAliasingHint()); return new TextLayout(composedTextString.getIterator(), frc); } diff --git a/app/src/processing/app/ui/EditorConsole.java b/app/src/processing/app/ui/EditorConsole.java index 14be32d680..c8c40ee487 100644 --- a/app/src/processing/app/ui/EditorConsole.java +++ b/app/src/processing/app/ui/EditorConsole.java @@ -276,7 +276,9 @@ public void message(String what, boolean err) { // components, causing deadlock. Updates are buffered to the console and // displayed at regular intervals on Swing's event-dispatching thread. // (patch by David Mellis) - consoleDoc.appendString(what, err ? errStyle : stdStyle); + // Remove ANSI escape codes from the text before adding it to the console + String clean = what.replaceAll("\u001B\\[[0-9;]*m", ""); + consoleDoc.appendString(clean, err ? errStyle : stdStyle); } } diff --git a/java/src/processing/mode/java/CompletionPanel.java b/java/src/processing/mode/java/CompletionPanel.java index bda85d75ec..2ba1eb29ef 100644 --- a/java/src/processing/mode/java/CompletionPanel.java +++ b/java/src/processing/mode/java/CompletionPanel.java @@ -287,7 +287,7 @@ private String fetchCurrentSubWord() { int x = ta.getCaretPosition() - ta.getLineStartOffset(line) - 1, x1 = x - 1; if (x >= s.length() || x < 0) return null; //TODO: Does this check cause problems? Verify. - if (Base.DEBUG) System.out.print(" x char: " + s.charAt(x)); + Messages.log(" x char: " + s.charAt(x)); String word = String.valueOf(s.charAt(x)); if (s.trim().length() == 1) { diff --git a/java/src/processing/mode/java/PreprocService.java b/java/src/processing/mode/java/PreprocService.java index f705362944..4f91505613 100644 --- a/java/src/processing/mode/java/PreprocService.java +++ b/java/src/processing/mode/java/PreprocService.java @@ -117,7 +117,7 @@ private void mainLoop() { running = true; PreprocSketch prevResult = null; CompletableFuture runningCallbacks = null; - Messages.log("PPS: Hi!"); + Messages.log("Hi!"); while (running) { try { try { @@ -127,7 +127,7 @@ private void mainLoop() { break; } - Messages.log("PPS: Starting"); + Messages.log("Starting"); prevResult = preprocessSketch(prevResult); @@ -143,7 +143,7 @@ private void mainLoop() { synchronized (requestLock) { if (requestQueue.isEmpty()) { runningCallbacks = lastCallback; - Messages.log("PPS: Done"); + Messages.log("Done"); preprocessingTask.complete(prevResult); } } @@ -151,7 +151,7 @@ private void mainLoop() { Messages.err("problem in preprocessor service loop", e); } } - Messages.log("PPS: Bye!"); + Messages.log("Bye!"); } /** @@ -188,7 +188,7 @@ public void notifySketchChanged() { * Indicate to this service that the sketch libraries have changed. */ public void notifyLibrariesChanged() { - Messages.log("PPS: notified libraries changed"); + Messages.log("notified libraries changed"); librariesChanged.set(true); notifySketchChanged(); } @@ -197,7 +197,7 @@ public void notifyLibrariesChanged() { * Indicate to this service that the folder housing sketch code has changed. */ public void notifyCodeFolderChanged() { - Messages.log("PPS: notified code folder changed"); + Messages.log("notified code folder changed"); codeFolderChanged.set(true); notifySketchChanged(); } @@ -216,7 +216,7 @@ private CompletableFuture registerCallback(Consumer callback) .thenAcceptBothAsync(lastCallback, (ps, a) -> callback.accept(ps)) // Make sure exception in callback won't cancel whole callback chain .handleAsync((res, e) -> { - if (e != null) Messages.err("PPS: exception in callback", e); + if (e != null) Messages.err("exception in callback", e); return res; }); return lastCallback; diff --git a/java/src/processing/mode/java/runner/Runner.java b/java/src/processing/mode/java/runner/Runner.java index 0e29e18a12..b4dc517707 100644 --- a/java/src/processing/mode/java/runner/Runner.java +++ b/java/src/processing/mode/java/runner/Runner.java @@ -253,19 +253,19 @@ public boolean launchVirtualMachine(boolean present, String[] args) { // while (!available) { while (true) { try { - Messages.log(getClass().getName() + " attempting to attach to VM"); + Messages.log("attempting to attach to VM"); synchronized (cancelLock) { vm = connector.attach(arguments); if (cancelled && vm != null) { // cancelled and connected to the VM, handle closing now - Messages.log(getClass().getName() + " aborting, launch cancelled"); + Messages.log("aborting, launch cancelled"); close(); return false; } } // vm = connector.attach(arguments); if (vm != null) { - Messages.log(getClass().getName() + " attached to the VM"); + Messages.log("attached to the VM"); // generateTrace(); // available = true; return true; @@ -273,17 +273,17 @@ public boolean launchVirtualMachine(boolean present, String[] args) { } catch (ConnectException ce) { // This will fire ConnectException (socket not available) until // the VM finishes starting up and opens its socket for us. - Messages.log(getClass().getName() + " socket for VM not ready"); + Messages.log("socket for VM not ready"); // System.out.println("waiting"); // e.printStackTrace(); try { Thread.sleep(100); } catch (InterruptedException ie) { - Messages.err(getClass().getName() + " interrupted", ie); + Messages.err("interrupted", ie); // ie.printStackTrace(sketchErr); } } catch (IOException e) { - Messages.err(getClass().getName() + " while attaching to VM", e); + Messages.err("while attaching to VM", e); } } // } catch (IOException exc) { From 115274358832f444e6cf3f794f187ec2535abe39 Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Tue, 11 Mar 2025 09:26:29 +0100 Subject: [PATCH 2/2] Fixed typo --- app/src/processing/app/Library.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/processing/app/Library.java b/app/src/processing/app/Library.java index e92ee8496d..f23354284b 100644 --- a/app/src/processing/app/Library.java +++ b/app/src/processing/app/Library.java @@ -1,6 +1,5 @@ package processing.app; -import java.awt.EventQueue; import java.io.*; import java.util.*; import java.util.zip.ZipFile; @@ -330,7 +329,7 @@ static String[] listPlatformEntries(File libraryFolder, String folderName, Strin * imports to specific libraries. * @param importToLibraryTable mapping from package names to Library objects */ - static boolean instruced = false; + static boolean instructed = false; // public void addPackageList(HashMap importToLibraryTable) { public void addPackageList(Map> importToLibraryTable) { // PApplet.println(packages); @@ -343,8 +342,8 @@ public void addPackageList(Map> importToLibraryTable) { libraries = new ArrayList<>(); importToLibraryTable.put(pkg, libraries); } else { - if(!instruced) { - instruced = true; + if(!instructed) { + instructed = true; Messages.err("The library found in"); Messages.err(getPath()); Messages.err("conflicts with");