diff --git a/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF index 1413400308..c95cd608dd 100644 --- a/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.debug.tests/META-INF/MANIFEST.MF @@ -39,7 +39,7 @@ Require-Bundle: org.eclipse.ui.ide;resolution:=optional, org.eclipse.jdt.core;bundle-version="[3.34.0,4.0.0)", org.eclipse.jdt.ui;bundle-version="[3.33.0,4.0.0)", org.eclipse.jdt.launching;bundle-version="[3.20.0,4.0.0)", - org.eclipse.jdt.debug;bundle-version="[3.21.0,4.0.0)", + org.eclipse.jdt.debug;bundle-version="[3.23.0,4.0.0)", org.eclipse.jdt.debug.ui;bundle-version="[3.13.0,4.0.0)", org.eclipse.debug.core;bundle-version="[3.22.0,4.0.0)", org.eclipse.debug.ui;bundle-version="[3.13.0,4.0.0)", diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/TriggerPointBreakpointsTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/TriggerPointBreakpointsTests.java index adff135727..93dc00ca64 100644 --- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/TriggerPointBreakpointsTests.java +++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/TriggerPointBreakpointsTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 IBM Corporation and others. + * Copyright (c) 2016, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -14,6 +14,7 @@ package org.eclipse.jdt.debug.tests.breakpoints; import org.eclipse.debug.core.model.IVariable; +import org.eclipse.jdt.debug.core.IJavaBreakpoint; import org.eclipse.jdt.debug.core.IJavaLineBreakpoint; import org.eclipse.jdt.debug.core.IJavaPrimitiveValue; import org.eclipse.jdt.debug.core.IJavaStackFrame; @@ -69,4 +70,69 @@ public void testTriggerPointBreakpoint() throws Exception { removeAllBreakpoints(); } } + + public void testTriggerPointBreakpointWithResume() throws Exception { + String typeName = "TriggerPoint_01"; + IJavaLineBreakpoint bp1 = createLineBreakpoint(20, typeName); + IJavaLineBreakpoint bp2 = createLineBreakpoint(21, typeName); + bp1.setTriggerPoint(true); + bp1.setSuspendPolicy(IJavaBreakpoint.RESUME_ON_HIT); // Resume mode + IJavaThread thread = null; + try { + thread = launchToLineBreakpoint(typeName, bp2); + + IJavaStackFrame frame = (IJavaStackFrame) thread.getTopStackFrame(); + int lineNumber = frame.getLineNumber(); + assertEquals("Breakpoint should resume and hit next breakpoint", 21, lineNumber); + bp1.delete(); + bp2.delete(); + } finally { + terminateAndRemove(thread); + removeAllBreakpoints(); + } + } + + public void testTriggerPointBreakpointWithResumeAndCondition() throws Exception { + String typeName = "TriggerPoint_01"; + IJavaLineBreakpoint bp1 = createLineBreakpoint(20, typeName); + IJavaLineBreakpoint bp2 = createLineBreakpoint(21, typeName); + bp1.setTriggerPoint(true); + bp1.setConditionEnabled(true); + bp1.setCondition("false"); // this wont let breakpoint to resume + bp1.setSuspendPolicy(IJavaBreakpoint.RESUME_ON_HIT); // Resume mode + IJavaThread thread = null; + try { + thread = launchToBreakpoint(typeName); + IJavaStackFrame frame = (IJavaStackFrame) thread.getTopStackFrame(); + int lineNumber = frame.getLineNumber(); + assertEquals("Breakpoint should not resume as condition is false", 20, lineNumber); + bp1.delete(); + bp2.delete(); + } finally { + terminateAndRemove(thread); + removeAllBreakpoints(); + } + } + + public void testTriggerPointBreakpointWithResumeAndConditionAsTrue() throws Exception { + String typeName = "TriggerPoint_01"; + IJavaLineBreakpoint bp1 = createLineBreakpoint(20, typeName); + IJavaLineBreakpoint bp2 = createLineBreakpoint(21, typeName); + bp1.setTriggerPoint(true); + bp1.setConditionEnabled(true); + bp1.setCondition("true"); // this will let breakpoint to resume + bp1.setSuspendPolicy(IJavaBreakpoint.RESUME_ON_HIT); // Resume mode + IJavaThread thread = null; + try { + thread = launchToBreakpoint(typeName); + IJavaStackFrame frame = (IJavaStackFrame) thread.getTopStackFrame(); + int lineNumber = frame.getLineNumber(); + assertEquals("Breakpoint should not resume as condition is false", 21, lineNumber); + bp1.delete(); + bp2.delete(); + } finally { + terminateAndRemove(thread); + removeAllBreakpoints(); + } + } } diff --git a/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF b/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF index 16073a15cb..5dd11bc164 100644 --- a/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.debug.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jdt.debug.ui; singleton:=true -Bundle-Version: 3.14.100.qualifier +Bundle-Version: 3.15.0.qualifier Bundle-Activator: org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -40,7 +40,7 @@ Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.5.0,4.0.0)", org.eclipse.core.expressions;bundle-version="[3.4.0,4.0.0)", org.eclipse.jdt.core;bundle-version="[3.40.0,4.0.0)", org.eclipse.debug.ui;bundle-version="[3.13.400,4.0.0)", - org.eclipse.jdt.debug;bundle-version="[3.21.0,4.0.0)", + org.eclipse.jdt.debug;bundle-version="[3.23.0,4.0.0)", org.eclipse.jdt.launching;bundle-version="[3.23.0,4.0.0)", org.eclipse.jdt.ui;bundle-version="[3.33.0,4.0.0)", org.eclipse.core.runtime;bundle-version="[3.30.0,4.0.0)", diff --git a/org.eclipse.jdt.debug.ui/pom.xml b/org.eclipse.jdt.debug.ui/pom.xml index 6db08dc643..3a34032609 100644 --- a/org.eclipse.jdt.debug.ui/pom.xml +++ b/org.eclipse.jdt.debug.ui/pom.xml @@ -18,7 +18,7 @@ org.eclipse.jdt org.eclipse.jdt.debug.ui - 3.14.100-SNAPSHOT + 3.15.0-SNAPSHOT eclipse-plugin true diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/breakpoints/JavaBreakpointConditionEditor.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/breakpoints/JavaBreakpointConditionEditor.java index 6d4788c067..9c3c1708f4 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/breakpoints/JavaBreakpointConditionEditor.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/debug/ui/breakpoints/JavaBreakpointConditionEditor.java @@ -26,12 +26,14 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.debug.internal.ui.DebugUIPlugin; import org.eclipse.debug.internal.ui.SWTFactory; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.debug.core.IJavaBreakpoint; import org.eclipse.jdt.debug.core.IJavaLineBreakpoint; import org.eclipse.jdt.debug.core.IJavaWatchpoint; import org.eclipse.jdt.internal.debug.ui.BreakpointUtils; @@ -142,8 +144,7 @@ public final class JavaBreakpointConditionEditor extends AbstractJavaBreakpointE private IAction fViewRedoAction; private OperationHistoryActionHandler fViewerUndoAction; private OperationHistoryActionHandler fViewerRedoAction; - - + private boolean isResumeOnHit; /** * Property id for breakpoint condition expression. */ @@ -361,6 +362,9 @@ public Control createControl(Composite parent) { public void widgetSelected(SelectionEvent e) { boolean checked = fConditional.getSelection(); setEnabled(checked, true); + if (isResumeOnHit) { + updateConditionTextOnResume(); + } setDirty(PROP_CONDITION_ENABLED); } }); @@ -455,6 +459,9 @@ public void widgetDisposed(DisposeEvent e) { dispose(); } }); + if (isResumeOnHit) { + updateConditionTextOnResume(); + } return parent; } @@ -592,6 +599,19 @@ private void disposeViewerUndoRedoActions() { * @param focus true if focus should be set, false otherwise */ private void setEnabled(boolean enabled, boolean focus) { + try { + if (fBreakpoint != null) { + if (fBreakpoint.getSuspendPolicy() == IJavaBreakpoint.RESUME_ON_HIT) { + updateConditionTextOnResume(); + } else { + fWhenTrue.setText(PropertyPageMessages.JavaBreakpointConditionEditor_1); + fWhenChange.setText(PropertyPageMessages.JavaBreakpointConditionEditor_2); + } + } + } catch (CoreException e) { + DebugUIPlugin.log(e); + } + fViewer.setEditable(enabled); fViewer.getTextWidget().setEnabled(enabled); fWhenChange.setEnabled(enabled); @@ -843,4 +863,35 @@ private void checkIfUsedInBreakpointsView() { } } + /** + * Update label values in Condition editor for trigger points that resume on hit + * + * @since 3.15 + */ + public void updateConditionTextOnResume() { + fWhenTrue.setText(PropertyPageMessages.BreakpointResumeConditionalTrue); + fWhenChange.setText(PropertyPageMessages.BreakpointResumeConditionalValue); + } + + /** + * Update label values in Condition editor for suspending breakpoints + * + * @since 3.15 + */ + public void updateConditionTextOnSuspend() { + fWhenTrue.setText(PropertyPageMessages.JavaBreakpointConditionEditor_1); + fWhenChange.setText(PropertyPageMessages.JavaBreakpointConditionEditor_2); + } + + /** + * Set "Resume on hit" flag + * + * @see IJavaBreakpoint#RESUME_ON_HIT + * + * @since 3.15 + */ + public void setResumeOnHit(boolean resume) { + isResumeOnHit = resume; + } + } diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java index 58a8aafecd..a6fbf90131 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java @@ -179,6 +179,7 @@ public class DebugUIMessages extends NLS { public static String JDIModelPresentation_target_suspended; public static String JDIModelPresentation_thread_filtered; public static String JDIModelPresentation_uncaught_62; + public static String JDIModelPresentation_resume_on_hit; // thread label keys are built programmatically diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties index 6fef0fa103..28d6c87f80 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties @@ -118,6 +118,7 @@ JDIModelPresentation_native_method=[native method] JDIModelPresentation_not_available=not available JDIModelPresentation_Suspend_VM=[Suspend VM] JDIModelPresentation_collapsed_frames={0} collapsed frames +JDIModelPresentation_resume_on_hit=[Resume on hit] ############################################################################### # Thread label keys are built programmatically diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIModelPresentation.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIModelPresentation.java index 0bfa1b8fda..c031102792 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIModelPresentation.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIModelPresentation.java @@ -2023,6 +2023,10 @@ protected void appendSuspendPolicy(IJavaBreakpoint breakpoint, StringBuilder buf buffer.append(' '); buffer.append(DebugUIMessages.JDIModelPresentation_Suspend_VM); } + if (breakpoint.getSuspendPolicy() == IJavaBreakpoint.RESUME_ON_HIT) { + buffer.append(' '); + buffer.append(DebugUIMessages.JDIModelPresentation_resume_on_hit); + } } protected void appendThreadFilter(IJavaBreakpoint breakpoint, StringBuilder buffer) throws CoreException { diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/breakpoints/StandardJavaBreakpointEditor.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/breakpoints/StandardJavaBreakpointEditor.java index 843deec568..e36391bfd4 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/breakpoints/StandardJavaBreakpointEditor.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/breakpoints/StandardJavaBreakpointEditor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2016 IBM Corporation and others. + * Copyright (c) 2009, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -19,6 +19,7 @@ import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.internal.ui.SWTFactory; import org.eclipse.jdt.debug.core.IJavaBreakpoint; +import org.eclipse.jdt.debug.ui.breakpoints.JavaBreakpointConditionEditor; import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin; import org.eclipse.jdt.internal.debug.ui.propertypages.PropertyPageMessages; import org.eclipse.jface.util.Util; @@ -44,9 +45,12 @@ public class StandardJavaBreakpointEditor extends AbstractJavaBreakpointEditor { private Button fHitCountButton; private Text fHitCountText; private Button fSuspendThread; + private Button fResumeOnHit; private Button fSuspendVM; protected Button fTriggerPointButton; + private final JavaBreakpointConditionEditor javaBpConditionEditor; + /** * Property id for hit count enabled state. */ @@ -67,6 +71,14 @@ public class StandardJavaBreakpointEditor extends AbstractJavaBreakpointEditor { */ public static final int PROP_TRIGGER_POINT = 0x1008; + public StandardJavaBreakpointEditor() { + this(null); + } + + public StandardJavaBreakpointEditor(JavaBreakpointConditionEditor jb) { + javaBpConditionEditor = jb; + } + /* (non-Javadoc) * @see org.eclipse.jdt.internal.debug.ui.breakpoints.AbstractJavaBreakpointEditor#createControl(org.eclipse.swt.widgets.Composite) */ @@ -87,18 +99,62 @@ protected Button createCheckButton(Composite parent, String text) { * the parent composite */ protected void createTriggerPointButton(Composite parent) { - Composite composite = SWTFactory.createComposite(parent, parent.getFont(), 1, 1, 0, 0, 0); + Composite composite = SWTFactory.createComposite(parent, parent.getFont(), 2, 1, 0, 0, 0); fTriggerPointButton = createCheckButton(composite, PropertyPageMessages.JavaBreakpointPage_12); - + fTriggerPointButton.setEnabled(true); fTriggerPointButton.setSelection(isTriggerPoint()); fTriggerPointButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { + boolean resumeOnHitEnabled = fResumeOnHit.isEnabled(); + if (resumeOnHitEnabled) { + fResumeOnHit.setSelection(false); + fResumeOnHit.setEnabled(false); + } else { + fResumeOnHit.setEnabled(true); + } + if (isTriggerPoint()) { + if (suspendVmAndTreadNotSelected()) { + fSuspendThread.setSelection(true); + setConditionTextToSuspend(); + } + } else { + if (resumeOnHitEnabled) { + if (suspendVmAndTreadNotSelected()) { + fSuspendThread.setSelection(true); + setConditionTextToSuspend(); + } + } else { + setConditionTextToSuspend(); + } + } + setDirty(PROP_TRIGGER_POINT); } + private boolean suspendVmAndTreadNotSelected() { + return !fSuspendThread.getSelection() && !fSuspendVM.getSelection(); + } + }); + fResumeOnHit = SWTFactory.createRadioButton(composite, PropertyPageMessages.BreakpointResumeOnHit, 1); + fResumeOnHit.setLayoutData(new GridData()); + fResumeOnHit.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + if (javaBpConditionEditor != null) { + if (fResumeOnHit.isEnabled()) { + javaBpConditionEditor.updateConditionTextOnResume(); + } + if (fResumeOnHit.getSelection()) { + javaBpConditionEditor.setResumeOnHit(true); + } + } + setDirty(PROP_SUSPEND_POLICY); + fSuspendThread.setSelection(false); + fSuspendVM.setSelection(false); + fResumeOnHit.setEnabled(true); + } }); - } protected Control createStandardControls(Composite parent) { @@ -125,8 +181,9 @@ public void modifyText(ModifyEvent e) { setDirty(PROP_HIT_COUNT); } }); + SWTFactory.createLabel(composite, "", 1); // spacer //$NON-NLS-1$ - Composite radios = SWTFactory.createComposite(composite, composite.getFont(), 2, 1, GridData.FILL_HORIZONTAL, 0, 0); + Composite radios = SWTFactory.createComposite(composite, composite.getFont(), 3, 1, GridData.FILL_HORIZONTAL, 0, 0); fSuspendThread = SWTFactory.createRadioButton(radios, processMnemonics(PropertyPageMessages.JavaBreakpointPage_7), 1); fSuspendThread.setLayoutData(new GridData()); fSuspendVM = SWTFactory.createRadioButton(radios, processMnemonics(PropertyPageMessages.JavaBreakpointPage_8), 1); @@ -134,12 +191,14 @@ public void modifyText(ModifyEvent e) { fSuspendThread.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { + setConditionTextToSuspend(); setDirty(PROP_SUSPEND_POLICY); } }); fSuspendVM.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { + setConditionTextToSuspend(); setDirty(PROP_SUSPEND_POLICY); } }); @@ -189,6 +248,7 @@ protected void setBreakpoint(IJavaBreakpoint breakpoint) throws CoreException { boolean hasHitCount = false; String text = Util.ZERO_LENGTH_STRING; boolean suspendThread = true; + boolean resumeOnHit = false; if (breakpoint != null) { enabled = true; int hitCount = breakpoint.getHitCount(); @@ -197,6 +257,7 @@ protected void setBreakpoint(IJavaBreakpoint breakpoint) throws CoreException { hasHitCount = true; } suspendThread= breakpoint.getSuspendPolicy() == IJavaBreakpoint.SUSPEND_THREAD; + resumeOnHit = breakpoint.getSuspendPolicy() == IJavaBreakpoint.RESUME_ON_HIT && isTriggerPoint(); } fHitCountButton.setEnabled(enabled); fHitCountButton.setSelection(enabled && hasHitCount); @@ -204,8 +265,10 @@ protected void setBreakpoint(IJavaBreakpoint breakpoint) throws CoreException { fHitCountText.setText(text); fSuspendThread.setEnabled(enabled); fSuspendVM.setEnabled(enabled); - fSuspendThread.setSelection(suspendThread); - fSuspendVM.setSelection(!suspendThread); + fResumeOnHit.setEnabled(isTriggerPoint()); + fResumeOnHit.setSelection(resumeOnHit); + fSuspendThread.setSelection(suspendThread && !resumeOnHit); + fSuspendVM.setSelection(!suspendThread && !resumeOnHit); fTriggerPointButton.setEnabled(enabled); fTriggerPointButton.setSelection(isTriggerPoint()); setDirty(false); @@ -238,6 +301,9 @@ public void doSave() throws CoreException { if(fSuspendVM.getSelection()) { suspendPolicy = IJavaBreakpoint.SUSPEND_VM; } + if (fResumeOnHit.getSelection() && fTriggerPointButton.getSelection()) { + suspendPolicy = IJavaBreakpoint.RESUME_ON_HIT; + } fBreakpoint.setSuspendPolicy(suspendPolicy); int hitCount = -1; if (fHitCountButton.getSelection()) { @@ -329,4 +395,14 @@ private void storeTriggerPoint(IJavaBreakpoint breakpoint) throws CoreException DebugPlugin.getDefault().getBreakpointManager().refreshTriggerpointDisplay(); } + private void setConditionTextToSuspend() { + if (fResumeOnHit.isEnabled()) { + fResumeOnHit.setSelection(false); + } + if (javaBpConditionEditor != null) { + javaBpConditionEditor.setResumeOnHit(false); + javaBpConditionEditor.updateConditionTextOnSuspend(); + } + } + } diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/JavaBreakpointPage.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/JavaBreakpointPage.java index cfbaa40587..d7ac508119 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/JavaBreakpointPage.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/JavaBreakpointPage.java @@ -335,8 +335,9 @@ protected void createTypeSpecificEditors(Composite parent) { fEditor = new StandardJavaBreakpointEditor(); } else if (JavaLineBreakpoint.JAVA_LINE_BREAKPOINT.equals(type)) { setTitle(PropertyPageMessages.JavaLineBreakpointPage_18); + JavaBreakpointConditionEditor javaBpConditionEditor = new JavaBreakpointConditionEditor(null); fEditor = new CompositeBreakpointEditor(new AbstractJavaBreakpointEditor[] - {new StandardJavaBreakpointEditor(), new JavaBreakpointConditionEditor(null)}); + { new StandardJavaBreakpointEditor(javaBpConditionEditor), javaBpConditionEditor }); } else if (JavaExceptionBreakpoint.JAVA_EXCEPTION_BREAKPOINT.equals(type)) { setTitle(PropertyPageMessages.JavaExceptionBreakpointPage_5); fEditor = new ExceptionBreakpointEditor(); diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.java index bf17a73922..78b6a11fb5 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.java +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2019 IBM Corporation and others. + * Copyright (c) 2003, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -112,11 +112,14 @@ public class PropertyPageMessages extends NLS { public static String VMCapabilitiesPropertyPage_29; public static String VMCapabilitiesPropertyPage_3; - public static String VMCapabilitiesPropertyPage_30; public static String VMCapabilitiesPropertyPage_31; public static String VMCapabilitiesPropertyPage_4; public static String VMCapabilitiesPropertyPage_6; public static String VMCapabilitiesPropertyPage_9; + public static String BreakpointResumeOnHit; + public static String BreakpointResumeConditionalTrue; + public static String BreakpointResumeConditionalValue; + } diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.properties index ff31c098c4..d734043042 100644 --- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.properties +++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2003, 2019 IBM Corporation and others. +# Copyright (c) 2003, 2025 IBM Corporation and others. # # This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 @@ -91,3 +91,6 @@ VMCapabilitiesPropertyPage_28=&Hot Code Replace VMCapabilitiesPropertyPage_29=&Stepping VMCapabilitiesPropertyPage_30=&General VMCapabilitiesPropertyPage_31=This page displays optional debug capabilities that may be supported by the selected VM. +BreakpointResumeOnHit=Continue execution on hit +BreakpointResumeConditionalTrue=Resume when 'true' +BreakpointResumeConditionalValue=Resume when value changes diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaBreakpoint.java index 1d3131a913..0a5322e241 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaBreakpoint.java +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaBreakpoint.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -47,6 +47,12 @@ public interface IJavaBreakpoint extends IBreakpoint, ITriggerPoint { */ public static final int SUSPEND_THREAD = 2; + /** + * Suspend policy constant indicating a breakpoint will not suspend the target VM when hit. + * + * @since 3.23 + */ + public static final int RESUME_ON_HIT = 3; /** * Returns whether this breakpoint is installed in at least one debug * target. diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaBreakpoint.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaBreakpoint.java index 1ee949ea4d..f864f17020 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaBreakpoint.java +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/breakpoints/JavaBreakpoint.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2022 IBM Corporation and others. + * Copyright (c) 2000, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -702,7 +702,7 @@ protected void addToTargetForLocalType(JDIDebugTarget target, String enclosingTy */ protected int getJDISuspendPolicy() throws CoreException { int breakpointPolicy = getSuspendPolicy(); - if (breakpointPolicy == IJavaBreakpoint.SUSPEND_THREAD) { + if (breakpointPolicy == IJavaBreakpoint.SUSPEND_THREAD || breakpointPolicy == IJavaBreakpoint.RESUME_ON_HIT ) { return EventRequest.SUSPEND_EVENT_THREAD; } return EventRequest.SUSPEND_ALL; diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java index c8063b6b46..cc5b29f49d 100644 --- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java +++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java @@ -1441,8 +1441,12 @@ private boolean handleSuspendForBreakpointInternal(JavaBreakpoint breakpoint) { } } catch (CoreException e) { - e.printStackTrace(); + logError(e); } + + // Condition for a trigger breakpoint that is set to resume on hit + boolean resumeOnHit = true; + // Evaluate breakpoint condition (if any). The condition is evaluated // regardless of the current suspend vote status, since breakpoint // listeners @@ -1457,10 +1461,14 @@ private boolean handleSuspendForBreakpointInternal(JavaBreakpoint breakpoint) { ConditionalBreakpointHandler handler = new ConditionalBreakpointHandler(); int vote = handler.breakpointHit(this, breakpoint); if (vote == IJavaBreakpointListener.DONT_SUSPEND) { - // condition is false, breakpoint is not hit - synchronized (this) { - fSuspendVoteInProgress = false; - return false; + if (policy == IJavaBreakpoint.RESUME_ON_HIT) { + resumeOnHit = false; + } else { + // condition is false, breakpoint is not hit + synchronized (this) { + fSuspendVoteInProgress = false; + return false; + } } } if (handler.hasErrors()) { @@ -1478,9 +1486,21 @@ private boolean handleSuspendForBreakpointInternal(JavaBreakpoint breakpoint) { } } + try { + if (resumeOnHit && breakpoint.getSuspendPolicy() == IJavaBreakpoint.RESUME_ON_HIT) { + synchronized (this) { + fSuspendVoteInProgress = false; + return false; // Won't be suspended + } + } + } catch (CoreException e) { + logError(e); + } + // poll listeners without holding lock on thread boolean suspend = true; try { + suspend = JDIDebugPlugin.getDefault().fireBreakpointHit(this, breakpoint); } finally {