This is an automated email from the ASF dual-hosted git repository.

entl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 1668b3a  Proper handling of LSP logging breakpoints.
1668b3a is described below

commit 1668b3a2c0bbf61fc3b1a48fd9e9a8954a7a7e31
Author: Martin Entlicher <martin.entlic...@oracle.com>
AuthorDate: Thu Sep 2 09:28:47 2021 +0200

    Proper handling of LSP logging breakpoints.
---
 .../jpda/truffle/access/TruffleAccess.java         |  50 +++++++--
 .../debugger/jpda/truffle/access/TruffleEval.java  |   4 +
 .../truffle/breakpoints/TruffleLineBreakpoint.java |  34 +++++-
 .../breakpoints/impl/HitBreakpointInfo.java        |  65 ++++++++++++
 .../breakpoints/impl/TruffleBreakpointOutput.java  | 118 +++++++++++++++++++++
 .../impl/TruffleBreakpointsHandler.java            |   4 +
 .../impl/TruffleBreakpointsRegistry.java           |  75 +++++++++++++
 .../debugger/jpda/console/DebuggerOutput.java      |   9 +-
 .../jpda/expr/InvocationExceptionTranslated.java   |   7 +-
 .../server/debugging/breakpoints/NbBreakpoint.java |  18 +++-
 10 files changed, 373 insertions(+), 11 deletions(-)

diff --git 
a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleAccess.java
 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleAccess.java
index eaf94da..7730a71 100644
--- 
a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleAccess.java
+++ 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleAccess.java
@@ -38,6 +38,7 @@ import java.beans.PropertyVetoException;
 import java.io.InvalidObjectException;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
@@ -89,6 +90,8 @@ import 
org.netbeans.modules.debugger.jpda.truffle.TruffleDebugManager;
 import org.netbeans.modules.debugger.jpda.truffle.Utils;
 import org.netbeans.modules.debugger.jpda.truffle.actions.StepActionProvider;
 import org.netbeans.modules.debugger.jpda.truffle.ast.TruffleNode;
+import 
org.netbeans.modules.debugger.jpda.truffle.breakpoints.impl.HitBreakpointInfo;
+import 
org.netbeans.modules.debugger.jpda.truffle.breakpoints.impl.TruffleBreakpointOutput;
 import org.netbeans.modules.debugger.jpda.truffle.frames.TruffleStackFrame;
 import org.netbeans.modules.debugger.jpda.truffle.frames.TruffleStackInfo;
 import org.netbeans.modules.debugger.jpda.truffle.source.Source;
@@ -366,12 +369,18 @@ public class TruffleAccess implements 
JPDABreakpointListener {
         JPDADebugger debugger = event.getDebugger();
         if (execHaltedBP.get(debugger) == bp) {
             LOG.log(Level.FINE, 
"TruffleAccessBreakpoints.breakpointReached({0}), exec halted.", event);
-            StepActionProvider.killJavaStep(debugger);
-            setCurrentPosition(debugger, event.getThread());
+            if (!setCurrentPosition(debugger, event.getThread())) {
+                event.resume();
+            } else {
+                StepActionProvider.killJavaStep(debugger);
+            }
         } else if (execStepIntoBP.get(debugger) == bp) {
             LOG.log(Level.FINE, 
"TruffleAccessBreakpoints.breakpointReached({0}), exec step into.", event);
-            StepActionProvider.killJavaStep(debugger);
-            setCurrentPosition(debugger, event.getThread());
+            if (!setCurrentPosition(debugger, event.getThread())) {
+                event.resume();
+            } else {
+                StepActionProvider.killJavaStep(debugger);
+            }
         } else if (dbgAccessBP.get(debugger) == bp) {
             LOG.log(Level.FINE, 
"TruffleAccessBreakpoints.breakpointReached({0}), debugger access.", event);
             try {
@@ -388,8 +397,11 @@ public class TruffleAccess implements 
JPDABreakpointListener {
         }
     }
     
-    private void setCurrentPosition(JPDADebugger debugger, JPDAThread thread) {
+    private boolean setCurrentPosition(JPDADebugger debugger, JPDAThread 
thread) {
         CurrentPCInfo cpci = getCurrentPosition(debugger, thread);
+        if (cpci == null) {
+            return false;
+        }
         synchronized (currentPCInfos) {
             ThreadInfo info = currentPCInfos.get(thread);
             if (info == null) {
@@ -399,6 +411,7 @@ public class TruffleAccess implements 
JPDABreakpointListener {
             }
             info.cpi = cpci;
         }
+        return true;
     }
 
     private static CurrentPCInfo getCurrentPosition(JPDADebugger debugger, 
JPDAThread thread) {
@@ -427,15 +440,40 @@ public class TruffleAccess implements 
JPDABreakpointListener {
             ObjectVariable thisObject = null;// TODO: (ObjectVariable) 
frameInfoVar.getField("thisObject");
             TruffleStackFrame topFrame = new TruffleStackFrame(debugger, 
thread, 0, frame, topFrameDescription, null/*code*/, scopes, thisObject, true);
             TruffleStackInfo stack = new TruffleStackInfo(debugger, thread, 
stackTrace, haltedInfo.supportsJavaFrames);
-            return new CurrentPCInfo(haltedInfo.stepCmd, thread, sp, scopes, 
topFrame, stack, depth -> {
+            HitBreakpointInfo[] breakpointInfos = 
getBreakpointInfos(haltedInfo, thread);
+            CurrentPCInfo cpi = new CurrentPCInfo(haltedInfo.stepCmd, thread, 
sp, scopes, topFrame,stack, depth -> {
                 return getTruffleAST(debugger, (JPDAThreadImpl) thread, depth, 
sp, stack);
             });
+            if (breakpointInfos != null) {
+                TruffleBreakpointOutput.breakpointsHit(breakpointInfos, cpi);
+            }
+            return cpi;
         } catch (IllegalStateException ex) {
             Exceptions.printStackTrace(ex);
             return null;
         }
     }
 
+    private static HitBreakpointInfo[] getBreakpointInfos(ExecutionHaltedInfo 
haltedInfo, JPDAThread thread) {
+        ObjectVariable[] breakpointsHit = haltedInfo.breakpointsHit;
+        ObjectVariable[] breakpointConditionExceptions = 
haltedInfo.breakpointConditionExceptions;
+        int n = breakpointsHit.length;
+        HitBreakpointInfo[] breakpointInfos = null;
+        for (int i = 0; i < n; i++) {
+            HitBreakpointInfo breakpointInfo = 
HitBreakpointInfo.create(breakpointsHit[i], breakpointConditionExceptions[i]);
+            if (breakpointInfo != null) {
+                if (breakpointInfos == null) {
+                    breakpointInfos = new HitBreakpointInfo[] { breakpointInfo 
};
+                } else {
+                    // There will rarely be more than one breakpoint hit
+                    breakpointInfos = Arrays.copyOf(breakpointInfos, 
breakpointInfos.length + 1);
+                    breakpointInfos[breakpointInfos.length - 1] = 
breakpointInfo;
+                }
+            }
+        }
+        return breakpointInfos;
+    }
+
     private static TruffleNode getTruffleAST(JPDADebugger debugger, 
JPDAThreadImpl thread, int depth, SourcePosition topPosition, TruffleStackInfo 
stack) {
         JPDAClassType debugAccessor = 
TruffleDebugManager.getDebugAccessorJPDAClass(debugger);
         Lock lock = thread.accessLock.writeLock();
diff --git 
a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleEval.java
 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleEval.java
index d51e4f1..330752c 100644
--- 
a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleEval.java
+++ 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleEval.java
@@ -56,6 +56,10 @@ public class TruffleEval {
         if (currentPCInfo == null) {
             throw new InvalidExpressionException(Bundle.MSG_NoSuspend());
         }
+        return evaluate(debugger, currentPCInfo, expression);
+    }
+
+    public static Variable evaluate(JPDADebugger debugger, CurrentPCInfo 
currentPCInfo, String expression) throws InvalidExpressionException {
         TruffleStackFrame selectedStackFrame = 
currentPCInfo.getSelectedStackFrame();
         if (selectedStackFrame == null) {
             throw new InvalidExpressionException(Bundle.MSG_NoSuspend());
diff --git 
a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/TruffleLineBreakpoint.java
 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/TruffleLineBreakpoint.java
index b74c53c..e2a9f68 100644
--- 
a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/TruffleLineBreakpoint.java
+++ 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/TruffleLineBreakpoint.java
@@ -25,12 +25,16 @@ import java.net.URL;
 import org.netbeans.modules.javascript2.debug.EditorLineHandler;
 import org.netbeans.modules.javascript2.debug.EditorLineHandlerFactory;
 import org.netbeans.modules.javascript2.debug.breakpoints.JSLineBreakpoint;
+
 import org.openide.filesystems.FileObject;
 import org.openide.filesystems.URLMapper;
 import org.openide.util.Lookup;
 
 public class TruffleLineBreakpoint extends JSLineBreakpoint {
-    
+
+    private volatile boolean suspend = true;
+    private volatile String printText;
+
     public TruffleLineBreakpoint(EditorLineHandler lineHandler) {
         super(lineHandler);
     }
@@ -39,6 +43,34 @@ public class TruffleLineBreakpoint extends JSLineBreakpoint {
         this(getEditorLineHandler(url, lineNumber));
     }
 
+    /**
+     * Test whether the breakpoint suspends execution when hit.
+     */
+    public final boolean isSuspend() {
+        return suspend;
+    }
+
+    /**
+     * Set whether the breakpoint should suspend execution when hit.
+     */
+    public final void setSuspend(boolean suspend) {
+        this.suspend = suspend;
+    }
+
+    /**
+     * Get a logging text that is printed to an output console when the 
breakpoint is hit.
+     */
+    public final String getPrintText() {
+        return printText;
+    }
+
+    /**
+     * Set a logging text that is printed to an output console when the 
breakpoint is hit.
+     */
+    public final void setPrintText(String printText) {
+        this.printText = printText;
+    }
+
     private static EditorLineHandler getEditorLineHandler(URL url, int 
lineNumber) {
         EditorLineHandler handler;
         if (Lookup.getDefault().lookup(EditorLineHandlerFactory.class) != 
null) {
diff --git 
a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/HitBreakpointInfo.java
 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/HitBreakpointInfo.java
new file mode 100644
index 0000000..e1068f4
--- /dev/null
+++ 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/HitBreakpointInfo.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.debugger.jpda.truffle.breakpoints.impl;
+
+import com.sun.jdi.ObjectReference;
+
+import org.netbeans.api.debugger.jpda.JPDADebugger;
+import org.netbeans.api.debugger.jpda.ObjectVariable;
+import org.netbeans.modules.debugger.jpda.expr.JDIVariable;
+import org.netbeans.modules.javascript2.debug.breakpoints.JSLineBreakpoint;
+
+import org.openide.util.Pair;
+
+/**
+ * Info about a hit breakpoint.
+ */
+public final class HitBreakpointInfo {
+
+    private final JPDADebugger debugger;
+    private final JSLineBreakpoint breakpoint;
+    private final ObjectVariable conditionException;
+
+    private HitBreakpointInfo(JPDADebugger debugger, JSLineBreakpoint 
breakpoint, ObjectVariable conditionException) {
+        this.debugger = debugger;
+        this.breakpoint = breakpoint;
+        this.conditionException = conditionException;
+    }
+
+    public static HitBreakpointInfo create(ObjectVariable breakpointHit, 
ObjectVariable breakpointConditionException) {
+        Pair<JPDADebugger, JSLineBreakpoint> breakpoint = 
TruffleBreakpointsRegistry.getDefault().get((ObjectReference) ((JDIVariable) 
breakpointHit).getJDIValue());
+        if (breakpoint == null) {
+            return null;
+        }
+        return new HitBreakpointInfo(breakpoint.first(), breakpoint.second(), 
breakpointConditionException);
+    }
+
+    public JPDADebugger getDebugger() {
+        return debugger;
+    }
+
+    public JSLineBreakpoint getBreakpoint() {
+        return breakpoint;
+    }
+
+    public ObjectVariable getConditionException() {
+        return conditionException;
+    }
+
+}
diff --git 
a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointOutput.java
 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointOutput.java
new file mode 100644
index 0000000..db31c50
--- /dev/null
+++ 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointOutput.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.debugger.jpda.truffle.breakpoints.impl;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.netbeans.api.debugger.jpda.InvalidExpressionException;
+import org.netbeans.api.debugger.jpda.JPDADebugger;
+import org.netbeans.api.debugger.jpda.ObjectVariable;
+import org.netbeans.api.debugger.jpda.Variable;
+import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
+import org.netbeans.modules.debugger.jpda.expr.InvocationExceptionTranslated;
+import org.netbeans.modules.debugger.jpda.truffle.access.CurrentPCInfo;
+import org.netbeans.modules.debugger.jpda.truffle.access.TruffleEval;
+import 
org.netbeans.modules.debugger.jpda.truffle.breakpoints.TruffleLineBreakpoint;
+import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleVariable;
+import org.netbeans.modules.javascript2.debug.breakpoints.JSLineBreakpoint;
+import org.openide.util.NbBundle;
+
+/**
+ * Prints text specified in the Truffle breakpoint when it is hits.
+ *
+ * @see TruffleLineBreakpoint#setPrintText(java.lang.String)
+ */
+public class TruffleBreakpointOutput {
+
+    private static final Pattern EXPRESSION_PATTERN = 
Pattern.compile("\\{=(.*?)\\}");  // NOI18N
+
+    private TruffleBreakpointOutput() {
+    }
+
+    public static void breakpointsHit(HitBreakpointInfo[] breakpointInfos, 
CurrentPCInfo cpi) {
+        for (HitBreakpointInfo breakpointInfo : breakpointInfos) {
+            breakpointHit(breakpointInfo, cpi);
+        }
+    }
+
+    private static void breakpointHit(HitBreakpointInfo breakpointInfo, 
CurrentPCInfo cpi) {
+        JSLineBreakpoint breakpoint = breakpointInfo.getBreakpoint();
+        if (!(breakpoint instanceof TruffleLineBreakpoint)) {
+            return;
+        }
+        String printText = ((TruffleLineBreakpoint)  
breakpoint).getPrintText();
+        if (printText == null || printText.isEmpty()) {
+            return;
+        }
+        ObjectVariable conditionException = 
breakpointInfo.getConditionException();
+        String exceptionMessage = null;
+        if (conditionException != null && conditionException.getUniqueID() != 
0) {
+            exceptionMessage = new 
InvocationExceptionTranslated(conditionException, (JPDADebuggerImpl) 
breakpointInfo.getDebugger()).getLocalizedMessage();
+        }
+        substituteAndPrintText(printText, exceptionMessage, cpi, 
breakpointInfo.getDebugger());
+    }
+
+    private static void substituteAndPrintText(String printText, String 
exceptionMessage, CurrentPCInfo cpi, JPDADebugger debugger) {
+        printText = substitute(printText, exceptionMessage, cpi, debugger);
+        ((JPDADebuggerImpl) debugger).getConsoleIO().println(printText, null);
+    }
+
+    @NbBundle.Messages({"# {0} - Expression",
+                        "# {1} - Error message",
+                        "MSG_EvaluateError=Cannot evaluate expression ''{0}'' 
: {1}"})
+    private static String substitute(String printText, String 
exceptionMessage, CurrentPCInfo cpi, JPDADebugger debugger) {
+        // 5) resolve all expressions {=expression}
+        for (;;) {
+            Matcher m = EXPRESSION_PATTERN.matcher (printText);
+            if (!m.find ()) {
+                break;
+            }
+            String expression = m.group (1);
+            String value = "";
+            try {
+                Variable varValue = TruffleEval.evaluate(debugger, cpi, 
expression);
+                if (varValue != null) {
+                    TruffleVariable tv = TruffleVariable.get(varValue);
+                    if (tv != null) {
+                        value = tv.getDisplayValue();
+                    } else {
+                        if (varValue instanceof ObjectVariable) {
+                            value = ((ObjectVariable) 
varValue).getToStringValue();
+                        } else {
+                            value = varValue.getValue();
+                        }
+                    }
+                }
+            } catch (InvalidExpressionException e) {
+                // expression is invalid or cannot be evaluated
+                String msg = e.getCause() != null ? e.getCause().getMessage() 
: e.getMessage();
+                ((JPDADebuggerImpl) debugger).getConsoleIO().println(
+                        Bundle.MSG_EvaluateError(expression, msg),
+                        null
+                );
+            }
+            printText = m.replaceFirst(value);
+        }
+        if (exceptionMessage != null) {
+            printText = printText + "\n***\n"+ exceptionMessage + "\n***\n";   
 // NOI18N
+        }
+        return printText;
+    }
+}
diff --git 
a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointsHandler.java
 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointsHandler.java
index 0c244e2..ce0c05a 100644
--- 
a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointsHandler.java
+++ 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointsHandler.java
@@ -116,6 +116,7 @@ public class TruffleBreakpointsHandler {
         if (breakpointResolvedHandler != null) {
             
DebuggerManager.getDebuggerManager().removeBreakpoint(breakpointResolvedHandler);
         }
+        TruffleBreakpointsRegistry.getDefault().dispose(debugger);
     }
     
     private void setBreakpointResolvedHandler(ClassType accessorClass) {
@@ -193,6 +194,7 @@ public class TruffleBreakpointsHandler {
             if (bp.isEnabled()) {
                 bpImpl = setLineBreakpoint(debugManager, t, uri, 
bp.getLineNumber(),
                                            getIgnoreCount(bp), 
bp.getCondition());
+                TruffleBreakpointsRegistry.getDefault().add(debugger, bp, 
bpImpl);
                 // Find out whether the breakpoint was resolved already during 
the submission:
                 try {
                     updateResolved(bp, bpImpl, t.getThreadReference());
@@ -320,6 +322,7 @@ public class TruffleBreakpointsHandler {
                             // Find out whether the breakpoint was resolved 
already during the submission:
                             for (Value v : ret.getValues()) {
                                 if (v instanceof ObjectReference) {
+                                    
TruffleBreakpointsRegistry.getDefault().add(debugger, bp, (ObjectReference) v);
                                     updateResolved(bp, (ObjectReference) v, 
tr);
                                 }
                             }
@@ -392,6 +395,7 @@ public class TruffleBreakpointsHandler {
                                      ObjectCollectedExceptionWrapper ex) {
                                 Exceptions.printStackTrace(ex);
                             }
+                            
TruffleBreakpointsRegistry.getDefault().remove(debugger, bpImpl);
                         }
                     } catch (VMDisconnectedExceptionWrapper ex) {}
                 }
diff --git 
a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointsRegistry.java
 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointsRegistry.java
new file mode 100644
index 0000000..438e264
--- /dev/null
+++ 
b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/impl/TruffleBreakpointsRegistry.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.debugger.jpda.truffle.breakpoints.impl;
+
+import com.sun.jdi.ObjectReference;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.netbeans.api.debugger.jpda.JPDADebugger;
+import org.netbeans.modules.javascript2.debug.breakpoints.JSLineBreakpoint;
+
+import org.openide.util.Pair;
+
+/**
+ * Registry of Truffle breakpoints. It helps to identify hit breakpoints via 
{@link TruffleBreakpointsRegistry#get(ObjectReference)}
+ */
+final class TruffleBreakpointsRegistry {
+
+    private static final TruffleBreakpointsRegistry DEFAULT = new 
TruffleBreakpointsRegistry();
+
+    private final Map<JPDADebugger, Map<ObjectReference, JSLineBreakpoint>> 
breakpoints = new ConcurrentHashMap<>();
+
+    private TruffleBreakpointsRegistry() {
+    }
+
+    static TruffleBreakpointsRegistry getDefault() {
+        return DEFAULT;
+    }
+
+    void add(JPDADebugger debugger, JSLineBreakpoint breakpoint, 
ObjectReference truffleBreakpoint) {
+        Map<ObjectReference, JSLineBreakpoint> bps = breakpoints.get(debugger);
+        if (bps == null) {
+            bps = breakpoints.computeIfAbsent(debugger, (key) -> new 
ConcurrentHashMap<>());
+        }
+        bps.put(truffleBreakpoint, breakpoint);
+    }
+
+    void remove(JPDADebugger debugger, ObjectReference truffleBreakpoint) {
+        Map<ObjectReference, JSLineBreakpoint> bps = breakpoints.get(debugger);
+        if (bps != null) {
+            bps.remove(truffleBreakpoint);
+        }
+    }
+
+    void dispose(JPDADebugger debugger) {
+        breakpoints.remove(debugger);
+    }
+
+    Pair<JPDADebugger, JSLineBreakpoint> get(ObjectReference 
truffleBreakpoint) {
+        for (Map.Entry<JPDADebugger, Map<ObjectReference, JSLineBreakpoint>> 
bpsEntry : breakpoints.entrySet()) {
+            JSLineBreakpoint bp = bpsEntry.getValue().get(truffleBreakpoint);
+            if (bp != null) {
+                return Pair.of(bpsEntry.getKey(), bp);
+            }
+        }
+        return null;
+    }
+}
diff --git 
a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/console/DebuggerOutput.java
 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/console/DebuggerOutput.java
index 36bc7cf..4e19502 100644
--- 
a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/console/DebuggerOutput.java
+++ 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/console/DebuggerOutput.java
@@ -295,7 +295,6 @@ public class DebuggerOutput implements 
PropertyChangeListener {
             final int lineNumber = t.getLineNumber (language);
             Operation op = t.getCurrentOperation();
             try {
-                final String sourceName = t.getSourceName (language);
                 String url = null;
                 SourcePath sourcePath = contextProvider.lookupFirst(null, 
SourcePath.class);
                 if (sourcePath != null) {
@@ -304,6 +303,14 @@ public class DebuggerOutput implements 
PropertyChangeListener {
                     } catch (InternalExceptionWrapper | 
InvalidStackFrameExceptionWrapper |
                              ObjectCollectedExceptionWrapper | 
VMDisconnectedExceptionWrapper ex) {}
                 }
+                String urlName = null;
+                if (url != null) {
+                    int index = url.lastIndexOf('/');
+                    if (index > 0) {
+                        urlName = url.substring(index + 1);
+                    }
+                }
+                final String sourceName = (urlName != null) ? urlName : 
t.getSourceName(language);
 //                String relativePath = EditorContextBridge.getRelativePath 
 //                    (t, language);
 //                synchronized (this) {
diff --git 
a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/expr/InvocationExceptionTranslated.java
 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/expr/InvocationExceptionTranslated.java
index 5e474cb..f212904 100644
--- 
a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/expr/InvocationExceptionTranslated.java
+++ 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/expr/InvocationExceptionTranslated.java
@@ -40,6 +40,7 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import org.netbeans.api.debugger.jpda.InvalidExpressionException;
 import org.netbeans.api.debugger.jpda.JPDAThread;
+import org.netbeans.api.debugger.jpda.ObjectVariable;
 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
 import org.netbeans.modules.debugger.jpda.jdi.ArrayReferenceWrapper;
 import org.netbeans.modules.debugger.jpda.jdi.ClassNotPreparedExceptionWrapper;
@@ -79,7 +80,11 @@ public class InvocationExceptionTranslated extends Exception 
{
     public InvocationExceptionTranslated(InvocationException iex, 
JPDADebuggerImpl debugger) {
         this(iex.getMessage(), iex.exception(), debugger);
     }
-    
+
+    public InvocationExceptionTranslated(ObjectVariable exception, 
JPDADebuggerImpl debugger) {
+        this(null, (ObjectReference) ((JDIVariable) exception).getJDIValue(), 
debugger);
+    }
+
     private InvocationExceptionTranslated(String invocationMessage, 
ObjectReference exeption, JPDADebuggerImpl debugger) {
         super(InvocationException.class.getName(), null);
         this.invocationMessage = invocationMessage;
diff --git 
a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/breakpoints/NbBreakpoint.java
 
b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/breakpoints/NbBreakpoint.java
index 2318924..ca39974 100644
--- 
a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/breakpoints/NbBreakpoint.java
+++ 
b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/breakpoints/NbBreakpoint.java
@@ -33,6 +33,7 @@ import org.eclipse.lsp4j.debug.Source;
 
 import org.netbeans.api.debugger.Breakpoint;
 import org.netbeans.api.debugger.DebuggerManager;
+import org.netbeans.api.debugger.jpda.JPDABreakpoint;
 import org.netbeans.api.debugger.jpda.LineBreakpoint;
 import 
org.netbeans.modules.debugger.jpda.truffle.breakpoints.TruffleLineBreakpoint;
 import org.netbeans.modules.java.lsp.server.debugging.DebugAdapterContext;
@@ -92,6 +93,8 @@ public final class NbBreakpoint {
             this.hitCount = hitCount;
             if (hitCount > 0) {
                 breakpoint.setHitCountFilter(hitCount, 
Breakpoint.HIT_COUNT_FILTERING_STYLE.GREATER);
+            } else {
+                breakpoint.setHitCountFilter(0, null);
             }
         }
     }
@@ -112,7 +115,9 @@ public final class NbBreakpoint {
                 b.setCondition(condition);
             }
             if (logMessage != null && !logMessage.isEmpty()) {
-                b.setPrintText(logMessage);
+                String message = lsp2NBLogMessage(logMessage);
+                b.setPrintText(message);
+                b.setSuspend(JPDABreakpoint.SUSPEND_NONE);
             }
             breakpoint = b;
         } else {
@@ -127,6 +132,11 @@ public final class NbBreakpoint {
             if (condition != null && !condition.isEmpty()) {
                 b.setCondition(condition);
             }
+            if (logMessage != null && !logMessage.isEmpty()) {
+                String message = lsp2NBLogMessage(logMessage);
+                b.setPrintText(message);
+                b.setSuspend(false);
+            }
             breakpoint = b;
         }
         if (hitCount > 0) {
@@ -142,6 +152,10 @@ public final class NbBreakpoint {
         return CompletableFuture.completedFuture(this);
     }
 
+    private static final String lsp2NBLogMessage(String message) {
+        return message.replaceAll("\\{([^\\}]+)\\}", "{=$1}");      // NOI18N
+    }
+
     private void updateValid(Breakpoint breakpoint, boolean sendNotify) {
         String message = breakpoint.getValidityMessage();
         boolean verified = breakpoint.getValidity() == 
Breakpoint.VALIDITY.VALID;
@@ -196,7 +210,7 @@ public final class NbBreakpoint {
             if (breakpoint instanceof LineBreakpoint) {
                 ((LineBreakpoint) breakpoint).setPrintText(logMessage);
             } else {
-                // no print text
+                ((TruffleLineBreakpoint) breakpoint).setPrintText(logMessage);
             }
         }
     }

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org
For additional commands, e-mail: commits-h...@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to