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 1b12ab7  Step and Continue after breakpoint suspends at wrong place 
after eval. [NETBEANS-6123]
1b12ab7 is described below

commit 1b12ab7eebf06b7264161e8f19a90b5142103a03
Author: Martin Entlicher <martin.entlic...@oracle.com>
AuthorDate: Mon Oct 11 20:23:41 2021 +0200

    Step and Continue after breakpoint suspends at wrong place after eval. 
[NETBEANS-6123]
---
 .../modules/debugger/jpda/JPDAStepImpl.java        |  6 ++
 .../debugger/jpda/actions/StepActionProvider.java  |  3 +
 .../debugger/jpda/actions/StepIntoNextMethod.java  |  2 +
 .../modules/debugger/jpda/impl/StepUtils.java      | 67 ++++++++++++++++++++
 .../debugger/jpda/models/JPDAThreadImpl.java       | 42 ++++++++++++-
 .../org/netbeans/api/debugger/jpda/StepTest.java   | 71 ++++++++++++++++++++++
 .../debugger/jpda/testapps/StepAndContinueApp.java | 53 ++++++++++++++++
 7 files changed, 241 insertions(+), 3 deletions(-)

diff --git 
a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/JPDAStepImpl.java 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/JPDAStepImpl.java
index e762f6f..2a3706f 100644
--- 
a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/JPDAStepImpl.java
+++ 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/JPDAStepImpl.java
@@ -62,6 +62,7 @@ import 
org.netbeans.api.debugger.jpda.event.JPDABreakpointListener;
 import 
org.netbeans.modules.debugger.jpda.actions.CompoundSmartSteppingListener;
 import org.netbeans.modules.debugger.jpda.actions.SmartSteppingFilterImpl;
 import org.netbeans.modules.debugger.jpda.actions.StepIntoActionProvider;
+import org.netbeans.modules.debugger.jpda.impl.StepUtils;
 import org.netbeans.modules.debugger.jpda.jdi.ClassNotPreparedExceptionWrapper;
 import org.netbeans.modules.debugger.jpda.jdi.ClassTypeWrapper;
 import 
org.netbeans.modules.debugger.jpda.jdi.IllegalThreadStateExceptionWrapper;
@@ -225,6 +226,7 @@ public class JPDAStepImpl extends JPDAStep implements 
Executor {
                     size,
                     getDepth()
                 );
+                StepUtils.markOriginalStepDepth(stepRequest, 
trImpl.getThreadReference());
                 //stepRequest.addCountFilter(1); - works bad with exclusion 
filters!
                 String[] exclusionPatterns = 
applyExclusionPatterns(stepRequest);
                 debuggerImpl.getOperator().register(stepRequest, this);
@@ -468,6 +470,7 @@ public class JPDAStepImpl extends JPDAStep implements 
Executor {
             StepRequest.STEP_LINE,
             StepRequest.STEP_OVER
         );
+        StepUtils.markOriginalStepDepth(boundaryStepRequest, trRef);
         if (isNextOperationFromDifferentExpression) {
             EventRequestWrapper.addCountFilter(boundaryStepRequest, 2);
         } else {
@@ -632,6 +635,7 @@ public class JPDAStepImpl extends JPDAStep implements 
Executor {
                                 StepRequest.STEP_LINE,
                                 StepRequest.STEP_OUT
                             );
+                            StepUtils.markOriginalStepDepth(stepRequest, 
tr.getThreadReference());
                             EventRequestWrapper.addCountFilter(stepRequest, 1);
                             String[] exclusionPatterns = 
getCurrentExclusionPatterns();
                             // JDI is inconsistent!!! Step into steps 
*through* filters, but step out does *NOT*
@@ -946,6 +950,7 @@ public class JPDAStepImpl extends JPDAStep implements 
Executor {
                             doStepSize,
                             doStepDepth
                         );
+                        StepUtils.markOriginalStepDepth(stepRequest, tr);
                         //EventRequestWrapper.addCountFilter(stepRequest, 1);
                         String[] exclusionPatterns = 
applyExclusionPatterns(stepRequest);
                         debuggerImpl.getOperator ().register (stepRequest, 
this);
@@ -1002,6 +1007,7 @@ public class JPDAStepImpl extends JPDAStep implements 
Executor {
                     doStepSize,
                     depth
                 );
+                StepUtils.markOriginalStepDepth(stepRequest, tr);
                 if (logger.isLoggable(Level.FINE)) {
                     try {
                         logger.fine("Can not stop at " + 
ThreadReferenceWrapper.frame(tr, 0) + ", smart-stepping. Submitting step = " + 
stepRequest + "; depth = " + depth);
diff --git 
a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/actions/StepActionProvider.java
 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/actions/StepActionProvider.java
index a770ea5..6cff450 100644
--- 
a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/actions/StepActionProvider.java
+++ 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/actions/StepActionProvider.java
@@ -54,6 +54,7 @@ import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
 import org.netbeans.modules.debugger.jpda.JPDAStepImpl;
 import 
org.netbeans.modules.debugger.jpda.JPDAStepImpl.MethodExitBreakpointListener;
 import org.netbeans.modules.debugger.jpda.SourcePath;
+import org.netbeans.modules.debugger.jpda.impl.StepUtils;
 import 
org.netbeans.modules.debugger.jpda.jdi.IllegalThreadStateExceptionWrapper;
 import org.netbeans.modules.debugger.jpda.jdi.InternalExceptionWrapper;
 import 
org.netbeans.modules.debugger.jpda.jdi.InvalidRequestStateExceptionWrapper;
@@ -221,6 +222,7 @@ implements Executor {
                     stepSize,
                     stepDepth
                 );
+            StepUtils.markOriginalStepDepth(stepRequest, tr);
             EventRequestWrapper.addCountFilter (stepRequest, 1);
             getDebuggerImpl ().getOperator ().register (stepRequest, 
StepActionProvider.this);
             EventRequestWrapper.setSuspendPolicy (stepRequest, suspendPolicy);
@@ -416,6 +418,7 @@ implements Executor {
                     StepRequest.STEP_LINE,
                     step
                 );
+                StepUtils.markOriginalStepDepth(stepRequest, tr);
                 EventRequestWrapper.addCountFilter(stepRequest, 1);
                 getDebuggerImpl ().getOperator ().register (stepRequest, this);
                 EventRequestWrapper.setSuspendPolicy(stepRequest, 
suspendPolicy);
diff --git 
a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/actions/StepIntoNextMethod.java
 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/actions/StepIntoNextMethod.java
index 4499e7f..4f7ed77 100644
--- 
a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/actions/StepIntoNextMethod.java
+++ 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/actions/StepIntoNextMethod.java
@@ -46,6 +46,7 @@ import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
 import org.netbeans.modules.debugger.jpda.JPDAStepImpl;
 import org.netbeans.modules.debugger.jpda.SourcePath;
 import static 
org.netbeans.modules.debugger.jpda.actions.StepActionProvider.getTopFrame;
+import org.netbeans.modules.debugger.jpda.impl.StepUtils;
 import 
org.netbeans.modules.debugger.jpda.jdi.IllegalThreadStateExceptionWrapper;
 import org.netbeans.modules.debugger.jpda.jdi.InternalExceptionWrapper;
 import 
org.netbeans.modules.debugger.jpda.jdi.InvalidRequestStateExceptionWrapper;
@@ -509,6 +510,7 @@ public class StepIntoNextMethod implements Executor, 
PropertyChangeListener {
                     tr,
                     stepSize,
                     step);
+            StepUtils.markOriginalStepDepth(stepRequest, tr);
             getDebuggerImpl ().getOperator ().register (stepRequest, this);
             suspendPolicy = getDebuggerImpl().getSuspend();
             EventRequestWrapper.setSuspendPolicy (stepRequest, suspendPolicy);
diff --git 
a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/impl/StepUtils.java 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/impl/StepUtils.java
new file mode 100644
index 0000000..9fed504
--- /dev/null
+++ 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/impl/StepUtils.java
@@ -0,0 +1,67 @@
+/*
+ * 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.impl;
+
+import com.sun.jdi.IncompatibleThreadStateException;
+import com.sun.jdi.ThreadReference;
+import com.sun.jdi.request.StepRequest;
+import 
org.netbeans.modules.debugger.jpda.jdi.IllegalThreadStateExceptionWrapper;
+
+import org.netbeans.modules.debugger.jpda.jdi.InternalExceptionWrapper;
+import 
org.netbeans.modules.debugger.jpda.jdi.InvalidStackFrameExceptionWrapper;
+import org.netbeans.modules.debugger.jpda.jdi.ObjectCollectedExceptionWrapper;
+import org.netbeans.modules.debugger.jpda.jdi.ThreadReferenceWrapper;
+import org.netbeans.modules.debugger.jpda.jdi.VMDisconnectedExceptionWrapper;
+import org.netbeans.modules.debugger.jpda.jdi.request.EventRequestWrapper;
+
+public final class StepUtils {
+
+    private static final String STEP_PROP_DEPTH = "originalThreadDepth";     
// NOI18N
+
+    private StepUtils() {}
+
+    /**
+     * Mark the frame depth of the thread when the step is created. It's to be 
retrieved
+     * by {@link #getOriginalStepDepth(com.sun.jdi.request.StepRequest)}.
+     */
+    public static void markOriginalStepDepth(StepRequest stepRequest, 
ThreadReference threadReference) {
+        try {
+            EventRequestWrapper.putProperty(stepRequest, STEP_PROP_DEPTH, 
ThreadReferenceWrapper.frameCount(threadReference));
+        } catch (IllegalThreadStateExceptionWrapper | 
IncompatibleThreadStateException | InternalExceptionWrapper |
+                InvalidStackFrameExceptionWrapper | 
ObjectCollectedExceptionWrapper | VMDisconnectedExceptionWrapper ex) {
+            // Not successful, ignore.
+        }
+    }
+
+    /**
+     * Get the frame depth of the thread when the step was submitted, or 
<code>-1</code> when unknown.
+     */
+    public static int getOriginalStepDepth(StepRequest stepRequest) {
+        Object depth;
+        try {
+            depth = EventRequestWrapper.getProperty(stepRequest, 
STEP_PROP_DEPTH);
+        } catch (InternalExceptionWrapper | VMDisconnectedExceptionWrapper ex) 
{
+            return -1;
+        }
+        if (depth instanceof Integer) {
+            return (Integer) depth;
+        }
+        return -1;
+    }
+}
diff --git 
a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/models/JPDAThreadImpl.java
 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/models/JPDAThreadImpl.java
index c430d9b..757efd6 100644
--- 
a/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/models/JPDAThreadImpl.java
+++ 
b/java/debugger.jpda/src/org/netbeans/modules/debugger/jpda/models/JPDAThreadImpl.java
@@ -75,6 +75,7 @@ import org.netbeans.api.debugger.jpda.Variable;
 import org.netbeans.api.debugger.jpda.event.JPDABreakpointEvent;
 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
 import org.netbeans.modules.debugger.jpda.SingleThreadWatcher;
+import org.netbeans.modules.debugger.jpda.impl.StepUtils;
 import 
org.netbeans.modules.debugger.jpda.jdi.IllegalThreadStateExceptionWrapper;
 import org.netbeans.modules.debugger.jpda.jdi.InternalExceptionWrapper;
 import 
org.netbeans.modules.debugger.jpda.jdi.InvalidRequestStateExceptionWrapper;
@@ -128,8 +129,8 @@ public final class JPDAThreadImpl implements JPDAThread, 
Customizer, BeanContext
     private static final Logger logger = 
Logger.getLogger(JPDAThreadImpl.class.getName()); // NOI18N
     private static final Logger loggerS = 
Logger.getLogger(JPDAThreadImpl.class.getName()+".suspend"); // NOI18N
     
-    private ThreadReference     threadReference;
-    private JPDADebuggerImpl    debugger;
+    private final ThreadReference     threadReference;
+    private final JPDADebuggerImpl    debugger;
     /** Thread is suspended and everybody know about this. */
     private boolean             suspended;
     private boolean             suspendedOnAnEvent; // Suspended by an event 
that occured in this thread
@@ -1357,7 +1358,9 @@ public final class JPDAThreadImpl implements JPDAThread, 
Customizer, BeanContext
                             if (stepsToDelete == null) {
                                 stepsToDelete = new ArrayList<StepRequest>();
                             }
-                            stepsToDelete.add(sr);
+                            if (checkToDisableStep(sr, t)) {
+                                stepsToDelete.add(sr);
+                            }
                         }
                     }
                     if (stepsToDelete != null) {
@@ -1404,6 +1407,39 @@ public final class JPDAThreadImpl implements JPDAThread, 
Customizer, BeanContext
         }
     }
     
+    private static boolean checkToDisableStep(StepRequest sr, ThreadReference 
t) {
+        int stepKind;
+        try {
+            stepKind = StepRequestWrapper.depth(sr);
+        } catch (InternalExceptionWrapper | VMDisconnectedExceptionWrapper ex) 
{
+            // A wrong state, do nothing
+            return false;
+        }
+        if (stepKind == StepRequest.STEP_INTO) {
+            // Disable step into as method invocation will suspend on it
+            return true;
+        }
+        int threadDepth;
+        try {
+            threadDepth = ThreadReferenceWrapper.frameCount(t);
+        } catch (IllegalThreadStateExceptionWrapper | 
IncompatibleThreadStateException |
+                InternalExceptionWrapper | InvalidStackFrameExceptionWrapper 
ex) {
+            // We can not retrieve the frame depth
+            return true;
+        } catch (ObjectCollectedExceptionWrapper | 
VMDisconnectedExceptionWrapper ex) {
+            // A wrong state, do nothing
+            return false;
+        }
+        int stepDepth = StepUtils.getOriginalStepDepth(sr);
+        if (stepDepth > 0) {
+            // If the depth at which the step was submitted is less than the 
current depth,
+            // do not disable the step as it will not interfere with the 
method invocation.
+            // The invocation will not go up the stack.
+            return stepDepth >= threadDepth;
+        }
+        return true;
+    }
+
     public void notifyMethodInvokeDone() {
         synchronized (suspendToCheckForMonitorsLock) {
             canSuspendToCheckForMonitors = false;
diff --git 
a/java/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/StepTest.java 
b/java/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/StepTest.java
index 636430f..792de78 100644
--- 
a/java/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/StepTest.java
+++ 
b/java/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/StepTest.java
@@ -229,6 +229,56 @@ public class StepTest extends NbTestCase {
         }
     }
 
+    public void testStepAndContinueOnBP() throws Exception {
+        String app = 
"org.netbeans.api.debugger.jpda.testapps.StepAndContinueApp";
+        try {
+            JPDASupport.removeAllBreakpoints();
+            Utils.BreakPositions bp = Utils.getBreakPositions(sourceRoot + 
app.replace('.', '/') + ".java");
+            LineBreakpoint lb = bp.getLineBreakpoints().get(0);
+            dm.addBreakpoint(lb);
+            support = JPDASupport.attach(app);
+            support.waitState (JPDADebugger.STATE_STOPPED);
+            dm.removeBreakpoint(lb);
+            assertEquals (
+                "Execution stopped in wrong class",
+                
support.getDebugger().getCurrentCallStackFrame().getClassName(),
+                app
+            );
+            assertEquals (
+                "Execution stopped at wrong line",
+                lb.getLineNumber(),
+                
support.getDebugger().getCurrentCallStackFrame().getLineNumber(null)
+            );
+            lb = bp.getLineBreakpoints().get(1);
+            dm.addBreakpoint(lb);
+            support.stepOver();
+            suspendedLineCheck(bp.getStopLine("Over1"));
+            support.stepOver();
+            breakpointCheckEvalCont(lb.getLineNumber());
+            suspendedLineCheck(bp.getStopLine("Over2"));
+            support.stepOver();
+            breakpointCheckEvalCont(lb.getLineNumber());
+            suspendedLineCheck(bp.getStopLine("Over3"));
+            support.stepOver();
+            suspendedLineCheck(bp.getStopLine("Over4"));
+            support.stepOver();
+            suspendedLineCheck(bp.getStopLine("Over5"));
+            support.stepInto();
+            suspendedLineCheck(bp.getStopLine("Into6"));
+            support.stepOut();
+            breakpointCheckEvalCont(lb.getLineNumber());
+            support.stepOver();
+            suspendedLineCheck(bp.getStopLine("Out7"));
+            support.stepInto();
+            suspendedLineCheck(bp.getStopLine("Into8"));
+            support.stepOut();
+            breakpointCheckEvalCont(lb.getLineNumber());
+            suspendedLineCheck(bp.getStopLine("Out7"));
+        } finally {
+            support.doFinish ();
+        }
+    }
+
     private void stepCheck (
         Object stepType, 
         String clsExpected, 
@@ -247,4 +297,25 @@ public class StepTest extends NbTestCase {
                 getLineNumber (null)
         );
     }
+
+    private void breakpointCheckEvalCont(int lineExpected) {
+        suspendedLineCheck(lineExpected);
+        // We invoke a method:
+        try {
+            assertEquals("10", 
support.getDebugger().evaluate("m1()").getValue());
+        } catch (InvalidExpressionException ex) {
+            throw new AssertionError(ex);
+        }
+        // Then we do Continue to finish the original step:
+        support.doContinue();
+        support.waitState(JPDADebugger.STATE_STOPPED);
+    }
+
+    private void suspendedLineCheck(int lineExpected) {
+        assertEquals (
+            "Execution stopped at wrong line",
+            lineExpected,
+            
support.getDebugger().getCurrentCallStackFrame().getLineNumber(null)
+        );
+    }
 }
diff --git 
a/java/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/testapps/StepAndContinueApp.java
 
b/java/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/testapps/StepAndContinueApp.java
new file mode 100644
index 0000000..453df94
--- /dev/null
+++ 
b/java/debugger.jpda/test/unit/src/org/netbeans/api/debugger/jpda/testapps/StepAndContinueApp.java
@@ -0,0 +1,53 @@
+/*
+ * 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.api.debugger.jpda.testapps;
+
+/**
+ * A sample application where we combine stepping and breakpoints with 
continue.
+ *
+ * @author Martin Entlicher
+ */
+public class StepAndContinueApp {
+
+    public static void main(String[] args) {
+        StepAndContinueApp sa = new StepAndContinueApp();
+        int x = sa.m1();        // STOP Over4
+        x += sa.m2();           // STOP Over5
+        x += sa.m3();           // STOP Out7
+    }
+
+    private int m1() {
+        int im1 = 10;           // LBREAKPOINT
+        m2();                   // STOP Over1
+        m3();                   // STOP Over2
+        return im1;             // STOP Over3
+    }
+
+    private int m2() {
+        int im2 = 20;           // STOP Into6
+        m3();
+        return im2;
+    }
+
+    private int m3() {
+        int im3 = 30;           // STOP Into8
+        return im3;             // LBREAKPOINT
+    }
+
+}

---------------------------------------------------------------------
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