You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by en...@apache.org on 2021/09/10 13:44:15 UTC
[netbeans] branch master updated: Proper handling of LSP logging
breakpoints.
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 <ma...@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-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists