diff options
Diffstat (limited to 'java/debugger/impl/src/com/intellij/debugger/actions/PopFrameAction.java')
-rw-r--r-- | java/debugger/impl/src/com/intellij/debugger/actions/PopFrameAction.java | 213 |
1 files changed, 179 insertions, 34 deletions
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/PopFrameAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/PopFrameAction.java index f5aa685c7994..f89ae5ce8292 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/PopFrameAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/PopFrameAction.java @@ -19,68 +19,212 @@ */ package com.intellij.debugger.actions; +import com.intellij.CommonBundle; import com.intellij.debugger.DebuggerBundle; +import com.intellij.debugger.SourcePosition; import com.intellij.debugger.engine.DebugProcessImpl; import com.intellij.debugger.engine.JavaStackFrame; import com.intellij.debugger.engine.SuspendContextImpl; import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.jdi.VirtualMachineProxyImpl; -import com.intellij.debugger.ui.impl.watch.*; +import com.intellij.debugger.settings.DebuggerSettings; +import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; +import com.intellij.debugger.ui.impl.watch.StackFrameDescriptorImpl; +import com.intellij.debugger.ui.impl.watch.ThreadDescriptorImpl; import com.intellij.idea.ActionsBundle; import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.MessageDialogBuilder; import com.intellij.openapi.ui.Messages; +import com.intellij.psi.PsiCodeBlock; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiStatement; +import com.intellij.psi.PsiTryStatement; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.UIUtil; import com.intellij.xdebugger.XDebugSession; +import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.XDebuggerManager; +import com.intellij.xdebugger.evaluation.EvaluationMode; +import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; import com.intellij.xdebugger.frame.XStackFrame; +import com.intellij.xdebugger.frame.XValue; +import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; import com.sun.jdi.InvalidStackFrameException; import com.sun.jdi.NativeMethodException; import com.sun.jdi.VMDisconnectedException; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; + public class PopFrameAction extends DebuggerAction { public void actionPerformed(AnActionEvent e) { - Project project = e.getData(CommonDataKeys.PROJECT); - StackFrameProxyImpl stackFrame = getStackFrameProxy(e); + final Project project = e.getData(CommonDataKeys.PROJECT); + final JavaStackFrame stackFrame = getStackFrame(e); if(stackFrame == null) { return; } try { - DebuggerContextImpl debuggerContext = DebuggerAction.getDebuggerContext(e.getDataContext()); - DebugProcessImpl debugProcess = debuggerContext.getDebugProcess(); + final DebuggerContextImpl debuggerContext = DebuggerAction.getDebuggerContext(e.getDataContext()); + final DebugProcessImpl debugProcess = debuggerContext.getDebugProcess(); if(debugProcess == null) { return; } - debugProcess.getManagerThread().schedule(debugProcess.createPopFrameCommand(debuggerContext, stackFrame)); + + if (!DebuggerSettings.EVALUATE_FINALLY_NEVER.equals(DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME)) { + List<PsiStatement> statements = getFinallyStatements(debuggerContext.getSourcePosition()); + if (!statements.isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (PsiStatement statement : statements) { + sb.append("\n").append(statement.getText()); + } + if (DebuggerSettings.EVALUATE_FINALLY_ALWAYS.equals(DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME)) { + evaluateAndPop(project, stackFrame, debuggerContext, debugProcess, sb); + return; + } + else { + int res = MessageDialogBuilder + .yesNoCancel(UIUtil.removeMnemonic(ActionsBundle.actionText(DebuggerActions.POP_FRAME)), + DebuggerBundle.message("warning.finally.block.detected") + sb) + .project(project) + .icon(Messages.getWarningIcon()) + .yesText(DebuggerBundle.message("button.execute.finally")) + .noText(DebuggerBundle.message("button.drop.anyway")) + .cancelText(CommonBundle.message("button.cancel")) + .doNotAsk( + new DialogWrapper.DoNotAskOption() { + @Override + public boolean isToBeShown() { + return !DebuggerSettings.EVALUATE_FINALLY_ALWAYS.equals(DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME) && + !DebuggerSettings.EVALUATE_FINALLY_NEVER.equals(DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME); + } + + @Override + public void setToBeShown(boolean value, int exitCode) { + if (!value) { + DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME = + exitCode == Messages.YES ? DebuggerSettings.EVALUATE_FINALLY_ALWAYS : DebuggerSettings.EVALUATE_FINALLY_NEVER; + } + else { + DebuggerSettings.getInstance().EVALUATE_FINALLY_ON_POP_FRAME = DebuggerSettings.EVALUATE_FINALLY_ASK; + } + } + + @Override + public boolean canBeHidden() { + return true; + } + + @Override + public boolean shouldSaveOptionsOnCancel() { + return false; + } + + @NotNull + @Override + public String getDoNotShowMessage() { + return CommonBundle.message("dialog.options.do.not.show"); + } + }) + .show(); + + switch (res) { + case Messages.CANCEL: + return; + case Messages.NO: + break; + case Messages.YES: // evaluate finally + evaluateAndPop(project, stackFrame, debuggerContext, debugProcess, sb); + return; + } + } + } + } + debugProcess.getManagerThread().schedule(debugProcess.createPopFrameCommand(debuggerContext, stackFrame.getStackFrameProxy())); } catch (NativeMethodException e2){ - Messages.showMessageDialog(project, DebuggerBundle.message("error.native.method.exception"), ActionsBundle.actionText(DebuggerActions.POP_FRAME), Messages.getErrorIcon()); + Messages.showMessageDialog(project, DebuggerBundle.message("error.native.method.exception"), + UIUtil.removeMnemonic(ActionsBundle.actionText(DebuggerActions.POP_FRAME)), Messages.getErrorIcon()); } catch (InvalidStackFrameException ignored) { } - catch(VMDisconnectedException vde) { + catch(VMDisconnectedException ignored) { } } - @Nullable - private static StackFrameProxyImpl getStackFrameProxy(AnActionEvent e) { - DebuggerTreeNodeImpl selectedNode = getSelectedNode(e.getDataContext()); - if(selectedNode != null) { - NodeDescriptorImpl descriptor = selectedNode.getDescriptor(); - if(descriptor instanceof StackFrameDescriptorImpl) { - if(selectedNode.getNextSibling() != null) { - StackFrameDescriptorImpl frameDescriptor = ((StackFrameDescriptorImpl)descriptor); - return frameDescriptor.getFrameProxy(); - } - return null; - } - else if(descriptor instanceof ThreadDescriptorImpl || descriptor instanceof ThreadGroupDescriptorImpl) { - return null; + private static void evaluateAndPop(final Project project, + final JavaStackFrame stackFrame, + final DebuggerContextImpl debuggerContext, + final DebugProcessImpl debugProcess, StringBuilder sb) { + XDebuggerEvaluator evaluator = stackFrame.getEvaluator(); + if (evaluator != null) { + evaluator.evaluate(XExpressionImpl.fromText(sb.toString(), EvaluationMode.CODE_FRAGMENT), + new XDebuggerEvaluator.XEvaluationCallback() { + @Override + public void evaluated(@NotNull XValue result) { + debugProcess.getManagerThread() + .schedule(debugProcess.createPopFrameCommand(debuggerContext, stackFrame.getStackFrameProxy())); + } + + @Override + public void errorOccurred(@NotNull final String errorMessage) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + Messages + .showMessageDialog(project, DebuggerBundle.message("error.executing.finally", errorMessage), + UIUtil.removeMnemonic(ActionsBundle.actionText(DebuggerActions.POP_FRAME)), + Messages.getErrorIcon()); + } + }); + } + }, stackFrame.getSourcePosition()); + } + else { + Messages.showMessageDialog(project, XDebuggerBundle.message("xdebugger.evaluate.stack.frame.has.not.evaluator"), + UIUtil.removeMnemonic(ActionsBundle.actionText(DebuggerActions.POP_FRAME)), + Messages.getErrorIcon()); + } + } + + private static List<PsiStatement> getFinallyStatements(SourcePosition position) { + List<PsiStatement> res = new ArrayList<PsiStatement>(); + PsiElement element = position.getFile().findElementAt(position.getOffset()); + PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(element, PsiTryStatement.class); + while (tryStatement != null) { + PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock(); + if (finallyBlock != null) { + ContainerUtil.addAll(res, finallyBlock.getStatements()); } + tryStatement = PsiTreeUtil.getParentOfType(tryStatement, PsiTryStatement.class); } + return res; + } + + @Nullable + private static JavaStackFrame getStackFrame(AnActionEvent e) { + //DebuggerTreeNodeImpl selectedNode = getSelectedNode(e.getDataContext()); + //if(selectedNode != null) { + // NodeDescriptorImpl descriptor = selectedNode.getDescriptor(); + // if(descriptor instanceof StackFrameDescriptorImpl) { + // if(selectedNode.getNextSibling() != null) { + // StackFrameDescriptorImpl frameDescriptor = ((StackFrameDescriptorImpl)descriptor); + // return frameDescriptor.getFrameProxy(); + // } + // return null; + // } + // else if(descriptor instanceof ThreadDescriptorImpl || descriptor instanceof ThreadGroupDescriptorImpl) { + // return null; + // } + //} Project project = e.getProject(); if (project != null) { @@ -89,18 +233,19 @@ public class PopFrameAction extends DebuggerAction { XStackFrame frame = session.getCurrentStackFrame(); if (frame instanceof JavaStackFrame) { StackFrameProxyImpl proxy = ((JavaStackFrame)frame).getStackFrameProxy(); - return !proxy.isBottom() ? proxy : null; + return !proxy.isBottom() ? ((JavaStackFrame)frame) : null; } } } - DebuggerContextImpl debuggerContext = DebuggerAction.getDebuggerContext(e.getDataContext()); - StackFrameProxyImpl frameProxy = debuggerContext.getFrameProxy(); - - if(frameProxy == null || frameProxy.isBottom()) { - return null; - } - return frameProxy; + //DebuggerContextImpl debuggerContext = DebuggerAction.getDebuggerContext(e.getDataContext()); + //StackFrameProxyImpl frameProxy = debuggerContext.getFrameProxy(); + // + //if(frameProxy == null || frameProxy.isBottom()) { + // return null; + //} + //return frameProxy; + return null; } private static boolean isAtBreakpoint(AnActionEvent e) { @@ -118,14 +263,14 @@ public class PopFrameAction extends DebuggerAction { public void update(AnActionEvent e) { boolean enable = false; - StackFrameProxyImpl stackFrameProxy = getStackFrameProxy(e); + JavaStackFrame stackFrame = getStackFrame(e); - if(stackFrameProxy != null && isAtBreakpoint(e)) { - VirtualMachineProxyImpl virtualMachineProxy = stackFrameProxy.getVirtualMachine(); + if(stackFrame != null && isAtBreakpoint(e)) { + VirtualMachineProxyImpl virtualMachineProxy = stackFrame.getStackFrameProxy().getVirtualMachine(); enable = virtualMachineProxy.canPopFrames(); } - if(ActionPlaces.MAIN_MENU.equals(e.getPlace()) || ActionPlaces.DEBUGGER_TOOLBAR.equals(e.getPlace())) { + if(ActionPlaces.isMainMenuOrActionSearch(e.getPlace()) || ActionPlaces.DEBUGGER_TOOLBAR.equals(e.getPlace())) { e.getPresentation().setEnabled(enable); } else { |