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