diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java index a3a0ef818978..e18a86d6a304 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java @@ -1,6 +1,7 @@ package com.intellij.debugger.engine; import com.intellij.debugger.DebuggerBundle; +import com.intellij.debugger.DebuggerInvocationUtil; import com.intellij.debugger.DebuggerManagerEx; import com.intellij.debugger.engine.events.DebuggerCommandImpl; import com.intellij.debugger.engine.events.SuspendContextCommandImpl; @@ -10,13 +11,16 @@ import com.intellij.debugger.jdi.ThreadReferenceProxyImpl; import com.intellij.debugger.jdi.VirtualMachineProxyImpl; import com.intellij.debugger.requests.Requestor; import com.intellij.debugger.settings.DebuggerSettings; +import com.intellij.debugger.ui.DebuggerPanelsManager; import com.intellij.debugger.ui.breakpoints.Breakpoint; import com.intellij.debugger.ui.breakpoints.BreakpointManager; import com.intellij.debugger.ui.breakpoints.LineBreakpoint; import com.intellij.execution.configurations.RemoteConnection; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Pair; import com.sun.jdi.InternalException; import com.sun.jdi.ThreadReference; @@ -351,17 +355,36 @@ public class DebugProcessEvents extends DebugProcessImpl { return; } - LocatableEventRequestor requestor = (LocatableEventRequestor) getRequestsManager().findRequestor(event.request()); + final LocatableEventRequestor requestor = (LocatableEventRequestor) getRequestsManager().findRequestor(event.request()); - final boolean requestorAsksResume = (requestor == null) || requestor.processLocatableEvent(this, event); - final boolean userWantsResume = (requestor instanceof Breakpoint) && DebuggerSettings.SUSPEND_NONE.equals(((Breakpoint)requestor).SUSPEND_POLICY); + boolean resumePreferred = requestor != null && DebuggerSettings.SUSPEND_NONE.equals(requestor.getSuspendPolicy()); + boolean requestHit = false; + try { + requestHit = (requestor != null) && requestor.processLocatableEvent(this, event); + } + catch (final LocatableEventRequestor.EventProcessingException ex) { + if (LOG.isDebugEnabled()) { + LOG.debug(ex.getMessage()); + } + final boolean[] considerRequestHit = new boolean[]{true}; + DebuggerInvocationUtil.invokeAndWait(getProject(), new Runnable() { + public void run() { + DebuggerPanelsManager.getInstance(getProject()).toFront(mySession); + final String displayName = requestor instanceof Breakpoint? ((Breakpoint)requestor).getDisplayName() : requestor.getClass().getSimpleName(); + final String message = DebuggerBundle.message("error.evaluating.breakpoint.condition.or.action", displayName, ex.getMessage()); + considerRequestHit[0] = Messages.showYesNoDialog(getProject(), message, ex.getTitle(), Messages.getQuestionIcon()) == 0; + } + }, ModalityState.NON_MODAL); + requestHit = considerRequestHit[0]; + resumePreferred = !requestHit; + } - if (requestor instanceof Breakpoint && !requestorAsksResume) { + if (requestHit && requestor instanceof Breakpoint) { // if requestor is a breakpoint and this breakpoint was hit, no matter its suspend policy myBreakpointManager.processBreakpointHit((Breakpoint)requestor); } - if(requestorAsksResume || userWantsResume) { + if(!requestHit || resumePreferred) { suspendManager.voteResume(suspendContext); } else { diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index 427cbd919ecb..12c10a7e6012 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -124,7 +124,7 @@ public abstract class DebugProcessImpl implements DebugProcess { private final Semaphore myWaitFor = new Semaphore(); private final AtomicBoolean myBreakpointsMuted = new AtomicBoolean(false); private boolean myIsFailed = false; - private DebuggerSession mySession; + protected DebuggerSession mySession; protected @Nullable MethodReturnValueWatcher myReturnValueWatcher; private final Alarm myStatusUpdateAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD); diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/requests/LocatableEventRequestor.java b/java/debugger/impl/src/com/intellij/debugger/engine/requests/LocatableEventRequestor.java index 4122f10a6be6..08c5fbf772b9 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/requests/LocatableEventRequestor.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/requests/LocatableEventRequestor.java @@ -13,7 +13,25 @@ import com.sun.jdi.event.LocatableEvent; */ public interface LocatableEventRequestor extends Requestor { /** - * returns whether should resume + * @returns true if requesto was hit by the event, false otherwise */ - boolean processLocatableEvent(SuspendContextCommandImpl action, LocatableEvent event); + boolean processLocatableEvent(SuspendContextCommandImpl action, LocatableEvent event) throws EventProcessingException; + + /** + * @return either DebuggerSettings.SUSPEND_NONE or DebuggerSettings.SUSPEND_ALL or DebuggerSettings.SUSPEND_THREAD + */ + String getSuspendPolicy(); + + class EventProcessingException extends Exception { + private final String myTitle; + + public EventProcessingException(String title, String message, Throwable cause) { + super(message, cause); + myTitle = title; + } + + public String getTitle() { + return myTitle; + } + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java index 50738e5f5306..e25e756fc190 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java @@ -11,16 +11,12 @@ import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl; import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator; import com.intellij.debugger.engine.events.SuspendContextCommandImpl; import com.intellij.debugger.engine.requests.RequestManagerImpl; -import com.intellij.debugger.impl.DebuggerSession; import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.jdi.ThreadReferenceProxyImpl; import com.intellij.debugger.requests.ClassPrepareRequestor; -import com.intellij.debugger.ui.DebuggerPanelsManager; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.*; import com.intellij.psi.PsiClass; import com.intellij.util.StringBuilderSpinAllocator; @@ -136,12 +132,11 @@ public abstract class Breakpoint extends FilteredRequestor implements ClassPrepa return null; } - // returns whether should resume - public boolean processLocatableEvent(final SuspendContextCommandImpl action, final LocatableEvent event) { + public boolean processLocatableEvent(final SuspendContextCommandImpl action, final LocatableEvent event) throws EventProcessingException { final SuspendContextImpl context = action.getSuspendContext(); if(!isValid()) { context.getDebugProcess().getRequestsManager().deleteRequest(this); - return true; + return false; } final String[] title = new String[] {DebuggerBundle.message("title.error.evaluating.breakpoint.condition") }; @@ -150,7 +145,7 @@ public abstract class Breakpoint extends FilteredRequestor implements ClassPrepa final StackFrameProxyImpl frameProxy = context.getThread().frame(0); if (frameProxy == null) { // might be if the thread has been collected - return true; + return false; } final EvaluationContextImpl evaluationContext = new EvaluationContextImpl( @@ -160,7 +155,7 @@ public abstract class Breakpoint extends FilteredRequestor implements ClassPrepa ); if(!evaluateCondition(evaluationContext, event)) { - return true; + return false; } title[0] = DebuggerBundle.message("title.error.evaluating.breakpoint.action"); @@ -169,26 +164,13 @@ public abstract class Breakpoint extends FilteredRequestor implements ClassPrepa catch (final EvaluateException ex) { if(ApplicationManager.getApplication().isUnitTestMode()) { System.out.println(ex.getMessage()); - return true; + return false; } - final boolean[] shouldResume = new boolean[]{true}; - DebuggerInvocationUtil.invokeAndWait(getProject(), new Runnable() { - public void run() { - DebuggerSession session = DebuggerManagerEx.getInstanceEx(getProject()).getSession(context.getDebugProcess()); - DebuggerPanelsManager.getInstance(getProject()).toFront(session); - final String text = DebuggerBundle.message("error.evaluating.breakpoint.condition.or.action", getDisplayName(), ex.getMessage()); - if (LOG.isDebugEnabled()) { - LOG.debug(text); - } - shouldResume[0] = Messages.showYesNoDialog(getProject(), text, title[0], Messages.getQuestionIcon()) != 0; - } - }, ModalityState.NON_MODAL); - - return shouldResume[0]; + throw new EventProcessingException(title[0], ex.getMessage(), ex); } - return false; + return true; } private void runAction(final EvaluationContextImpl context, LocatableEvent event) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestor.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestor.java index 2a24e5cf5d2f..d382d5120fde 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestor.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestor.java @@ -66,6 +66,10 @@ public abstract class FilteredRequestor implements LocatableEventRequestor, JDOM myInstanceFilters = instanceFilters != null? instanceFilters : InstanceFilter.EMPTY_ARRAY; } + public String getSuspendPolicy() { + return SUSPEND_POLICY; + } + /** * @return true if the ID was added or false otherwise */ diff --git a/platform/lang-api/src/com/intellij/execution/runners/ProgramRunnerUtil.java b/platform/lang-api/src/com/intellij/execution/runners/ProgramRunnerUtil.java index 264bf0681f96..d29ce24b28f9 100644 --- a/platform/lang-api/src/com/intellij/execution/runners/ProgramRunnerUtil.java +++ b/platform/lang-api/src/com/intellij/execution/runners/ProgramRunnerUtil.java @@ -26,7 +26,7 @@ public class ProgramRunnerUtil { return; } - String message = ExecutionBundle.message("error.running.configuration.with.error.error.message", runProfile.getName(), e.getMessage()); + String message = ExecutionBundle.message("error.running.configuration.with.error.error.message", runProfile != null? runProfile.getName() : "Run profile", e.getMessage()); if (ApplicationManager.getApplication().isUnitTestMode()) { LOG.assertTrue(false, message); }