diff options
Diffstat (limited to 'java/debugger/impl/src/com/intellij/debugger/engine')
13 files changed, 249 insertions, 130 deletions
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 4714ca49bd06..7640a959597e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java @@ -29,7 +29,6 @@ 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; @@ -57,15 +56,15 @@ import com.sun.jdi.request.ThreadStartRequest; * @author lex */ public class DebugProcessEvents extends DebugProcessImpl { - private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.DebugProcessEvents"); + private static final Logger LOG = Logger.getInstance(DebugProcessEvents.class); + private DebuggerEventThread myEventThread; - private final BreakpointManager myBreakpointManager; public DebugProcessEvents(Project project) { super(project); - myBreakpointManager = DebuggerManagerEx.getInstanceEx(getProject()).getBreakpointManager(); } + @Override protected void commitVM(final VirtualMachine vm) { super.commitVM(vm); if(vm != null) { @@ -134,18 +133,19 @@ public class DebugProcessEvents extends DebugProcessImpl { return myIsStopped; } + @Override public void run() { try { EventQueue eventQueue = myVmProxy.eventQueue(); while (!isStopped()) { try { final EventSet eventSet = eventQueue.remove(); - + final boolean methodWatcherActive = myReturnValueWatcher != null && myReturnValueWatcher.isEnabled(); int processed = 0; for (EventIterator eventIterator = eventSet.eventIterator(); eventIterator.hasNext();) { final Event event = eventIterator.nextEvent(); - + if (methodWatcherActive) { if (event instanceof MethodExitEvent) { if (myReturnValueWatcher.processMethodExitEvent((MethodExitEvent)event)) { @@ -158,6 +158,7 @@ public class DebugProcessEvents extends DebugProcessImpl { processed++; final ThreadReference thread = ((ThreadStartEvent)event).thread(); getManagerThread().schedule(new DebuggerCommandImpl() { + @Override protected void action() throws Exception { getVirtualMachineProxy().threadStarted(thread); myDebugProcessDispatcher.getMulticaster().threadStarted(DebugProcessEvents.this, thread); @@ -168,6 +169,7 @@ public class DebugProcessEvents extends DebugProcessImpl { processed++; final ThreadReference thread = ((ThreadDeathEvent)event).thread(); getManagerThread().schedule(new DebuggerCommandImpl() { + @Override protected void action() throws Exception { getVirtualMachineProxy().threadStopped(thread); myDebugProcessDispatcher.getMulticaster().threadStopped(DebugProcessEvents.this, thread); @@ -175,15 +177,15 @@ public class DebugProcessEvents extends DebugProcessImpl { }); } } - + if (processed == eventSet.size()) { eventSet.resume(); continue; } getManagerThread().invokeAndWait(new DebuggerCommandImpl() { + @Override protected void action() throws Exception { - if (eventSet.suspendPolicy() == EventRequest.SUSPEND_ALL && !DebuggerSession.enableBreakpointsDuringEvaluation()) { // check if there is already one request with policy SUSPEND_ALL for (SuspendContextImpl context : getSuspendManager().getEventContexts()) { @@ -193,12 +195,10 @@ public class DebugProcessEvents extends DebugProcessImpl { } } } - + final SuspendContextImpl suspendContext = getSuspendManager().pushSuspendContext(eventSet); - for (EventIterator eventIterator = eventSet.eventIterator(); eventIterator.hasNext();) { final Event event = eventIterator.nextEvent(); - //if (LOG.isDebugEnabled()) { // LOG.debug("EVENT : " + event); //} @@ -207,10 +207,7 @@ public class DebugProcessEvents extends DebugProcessImpl { //Sun WTK fails when J2ME when event set is resumed on VMStartEvent processVMStartEvent(suspendContext, (VMStartEvent)event); } - else if (event instanceof VMDeathEvent) { - processVMDeathEvent(suspendContext, event); - } - else if (event instanceof VMDisconnectEvent) { + else if (event instanceof VMDeathEvent || event instanceof VMDisconnectEvent) { processVMDeathEvent(suspendContext, event); } else if (event instanceof ClassPrepareEvent) { @@ -240,7 +237,6 @@ public class DebugProcessEvents extends DebugProcessImpl { } } }); - } catch (InternalException e) { LOG.debug(e); @@ -264,13 +260,15 @@ public class DebugProcessEvents extends DebugProcessImpl { } catch (VMDisconnectedException e) { invokeVMDeathEvent(); - } finally { + } + finally { Thread.interrupted(); // reset interrupted status } } private void invokeVMDeathEvent() { getManagerThread().invokeAndWait(new DebuggerCommandImpl() { + @Override protected void action() throws Exception { SuspendContextImpl suspendContext = getSuspendManager().pushSuspendContext(EventRequest.SUSPEND_NONE, 1); processVMDeathEvent(suspendContext, null); @@ -307,7 +305,7 @@ public class DebugProcessEvents extends DebugProcessImpl { if(myState.compareAndSet(STATE_INITIAL, STATE_ATTACHED)) { final VirtualMachineProxyImpl machineProxy = getVirtualMachineProxy(); final EventRequestManager requestManager = machineProxy.eventRequestManager(); - + if (machineProxy.canGetMethodReturnValues()) { myReturnValueWatcher = new MethodReturnValueWatcher(requestManager); } @@ -378,7 +376,7 @@ public class DebugProcessEvents extends DebugProcessImpl { RequestHint hint = (RequestHint)event.request().getProperty("hint"); deleteStepRequests(event.thread()); - + boolean shouldResume = false; final Project project = getProject(); @@ -426,8 +424,9 @@ public class DebugProcessEvents extends DebugProcessImpl { preprocessEvent(suspendContext, thread); //we use schedule to allow processing other events during processing this one - //this is especially nesessary if a method is breakpoint condition + //this is especially necessary if a method is breakpoint condition getManagerThread().schedule(new SuspendContextCommandImpl(suspendContext) { + @Override public void contextAction() throws Exception { final SuspendManager suspendManager = getSuspendManager(); SuspendContextImpl evaluatingContext = SuspendManagerUtil.getEvaluatingContext(suspendManager, getSuspendContext().getThread()); @@ -441,7 +440,7 @@ public class DebugProcessEvents extends DebugProcessImpl { final LocatableEventRequestor requestor = (LocatableEventRequestor) getRequestsManager().findRequestor(event.request()); boolean resumePreferred = requestor != null && DebuggerSettings.SUSPEND_NONE.equals(requestor.getSuspendPolicy()); - boolean requestHit = false; + boolean requestHit; try { requestHit = (requestor != null) && requestor.processLocatableEvent(this, event); } @@ -451,6 +450,7 @@ public class DebugProcessEvents extends DebugProcessImpl { } final boolean[] considerRequestHit = new boolean[]{true}; DebuggerInvocationUtil.invokeAndWait(getProject(), new Runnable() { + @Override public void run() { DebuggerPanelsManager.getInstance(getProject()).toFront(mySession); final String displayName = requestor instanceof Breakpoint? ((Breakpoint)requestor).getDisplayName() : requestor.getClass().getSimpleName(); 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 613217f93ac2..4f10e68440b9 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -17,6 +17,7 @@ package com.intellij.debugger.engine; import com.intellij.Patches; import com.intellij.debugger.*; +import com.intellij.debugger.actions.DebuggerAction; import com.intellij.debugger.actions.DebuggerActions; import com.intellij.debugger.apiAdapters.ConnectionServiceWrapper; import com.intellij.debugger.engine.evaluation.*; @@ -43,10 +44,7 @@ import com.intellij.execution.CantRunException; import com.intellij.execution.ExecutionException; import com.intellij.execution.ExecutionResult; import com.intellij.execution.configurations.RemoteConnection; -import com.intellij.execution.process.ProcessAdapter; -import com.intellij.execution.process.ProcessEvent; -import com.intellij.execution.process.ProcessListener; -import com.intellij.execution.process.ProcessOutputTypes; +import com.intellij.execution.process.*; import com.intellij.execution.runners.ExecutionUtil; import com.intellij.idea.ActionsBundle; import com.intellij.openapi.Disposable; @@ -170,10 +168,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb final DebuggerSession session = mySession; if (session != null && session.isAttached()) { session.refresh(true); - XDebugSession xDebugSession = mySession.getXDebugSession(); - if (xDebugSession != null) { - xDebugSession.rebuildViews(); - } + DebuggerAction.refreshViews(mySession.getXDebugSession()); } } }); @@ -354,10 +349,16 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb return new CompoundPositionManager(new PositionManagerImpl(this)); } + @Override public void printToConsole(final String text) { myExecutionResult.getProcessHandler().notifyTextAvailable(text, ProcessOutputTypes.SYSTEM); } + @Override + public ProcessHandler getProcessHandler() { + return myExecutionResult.getProcessHandler(); + } + /** * * @param suspendContext @@ -653,8 +654,8 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb public void addProcessListener(ProcessListener processListener) { synchronized(myProcessListeners) { - if(getExecutionResult() != null) { - getExecutionResult().getProcessHandler().addProcessListener(processListener); + if(getProcessHandler() != null) { + getProcessHandler().addProcessListener(processListener); } else { myProcessListeners.add(processListener); @@ -664,8 +665,8 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb public void removeProcessListener(ProcessListener processListener) { synchronized (myProcessListeners) { - if(getExecutionResult() != null) { - getExecutionResult().getProcessHandler().removeProcessListener(processListener); + if(getProcessHandler() != null) { + getProcessHandler().removeProcessListener(processListener); } else { myProcessListeners.remove(processListener); @@ -917,11 +918,32 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException; - public E start(EvaluationContextImpl evaluationContext, Method method) throws EvaluateException { - return start(evaluationContext, method, false); + + + E start(EvaluationContextImpl evaluationContext, Method method, boolean internalEvaluate) throws EvaluateException { + while (true) { + try { + return startInternal(evaluationContext, method, internalEvaluate); + } + catch (ClassNotLoadedException e) { + ReferenceType loadedClass = null; + try { + if (evaluationContext.isAutoLoadClasses()) { + loadedClass = loadClass(evaluationContext, e.className(), evaluationContext.getClassLoader()); + } + } + catch (Exception ignored) { + loadedClass = null; + } + if (loadedClass == null) { + throw EvaluateExceptionUtil.createEvaluateException(e); + } + } + } } - public E start(EvaluationContextImpl evaluationContext, Method method, boolean internalEvaluate) throws EvaluateException { + E startInternal(EvaluationContextImpl evaluationContext, Method method, boolean internalEvaluate) + throws EvaluateException, ClassNotLoadedException { DebuggerManagerThreadImpl.assertIsManagerThread(); SuspendContextImpl suspendContext = evaluationContext.getSuspendContext(); SuspendManagerUtil.assertSuspendContext(suspendContext); @@ -956,26 +978,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb getVirtualMachineProxy().clearCaches(); - while (true) { - try { - return invokeMethodAndFork(suspendContext); - } - catch (ClassNotLoadedException e) { - ReferenceType loadedClass; - try { - loadedClass = evaluationContext.isAutoLoadClasses() ? loadClass(evaluationContext, e.className(), evaluationContext.getClassLoader()) : null; - } - catch (EvaluateException ignored) { - loadedClass = null; - } - if (loadedClass == null) { - throw EvaluateExceptionUtil.createEvaluateException(e); - } - } - } - } - catch (ClassNotLoadedException e) { - throw EvaluateExceptionUtil.createEvaluateException(e); + return invokeMethodAndFork(suspendContext); } catch (InvocationException e) { throw EvaluateExceptionUtil.createEvaluateException(e); @@ -1115,7 +1118,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb } return objRef.invokeMethod(thread, method, args, invokePolicy | invocationOptions); } - }.start((EvaluationContextImpl)evaluationContext, method); + }.start((EvaluationContextImpl)evaluationContext, method, false); } private static ThreadReference getEvaluationThread(final EvaluationContext evaluationContext) throws EvaluateException { @@ -1182,7 +1185,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb return classType.newInstance(thread, method, args, invokePolicy); } }; - return invokeCommand.start((EvaluationContextImpl)evaluationContext, method); + return invokeCommand.start((EvaluationContextImpl)evaluationContext, method, false); } public void clearCashes(int suspendPolicy) { @@ -1711,15 +1714,17 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb createVirtualMachine(environment.getSessionName(), environment.isPollConnection()); + ExecutionResult executionResult; try { synchronized (myProcessListeners) { - myExecutionResult = environment.createExecutionResult(); - if (myExecutionResult == null) { + executionResult = environment.createExecutionResult(); + myExecutionResult = executionResult; + if (executionResult == null) { fail(); return null; } for (ProcessListener processListener : myProcessListeners) { - myExecutionResult.getProcessHandler().addProcessListener(processListener); + executionResult.getProcessHandler().addProcessListener(processListener); } myProcessListeners.clear(); } @@ -1732,7 +1737,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb // writing to volatile field ensures the other threads will see the right values in non-volatile fields if (ApplicationManager.getApplication().isUnitTestMode()) { - return myExecutionResult; + return executionResult; } /* @@ -1760,7 +1765,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb }); */ - return myExecutionResult; + return executionResult; } private void fail() { @@ -1885,8 +1890,8 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb } MyProcessAdapter processListener = new MyProcessAdapter(); addProcessListener(processListener); - if(myExecutionResult != null) { - if(myExecutionResult.getProcessHandler().isStartNotified()) { + if (myExecutionResult != null) { + if (myExecutionResult.getProcessHandler().isStartNotified()) { processListener.run(); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JVMNameUtil.java b/java/debugger/impl/src/com/intellij/debugger/engine/JVMNameUtil.java index 13e8f155dff4..eeaa1c21015e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JVMNameUtil.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JVMNameUtil.java @@ -285,13 +285,20 @@ public class JVMNameUtil { return DebuggerManager.getInstance(aClass.getProject()).getVMClassQualifiedName(aClass); } + public static JVMName getJVMConstructorSignature(@Nullable PsiMethod method, @Nullable PsiClass declaringClass) { + return getJVMSignature(method, true, declaringClass); + } + + public static JVMName getJVMSignature(@NotNull PsiMethod method) { + return getJVMSignature(method, method.isConstructor(), method.getContainingClass()); + } + @SuppressWarnings({"HardCodedStringLiteral"}) - public static JVMName getJVMSignature(PsiMethod method) { + private static JVMName getJVMSignature(@Nullable PsiMethod method, boolean constructor, @Nullable PsiClass declaringClass) { JVMNameBuffer signature = new JVMNameBuffer(); signature.append("("); - if (method.isConstructor()) { - final PsiClass declaringClass = method.getContainingClass(); + if (constructor) { if (declaringClass != null) { final PsiClass outerClass = declaringClass.getContainingClass(); if (outerClass != null) { @@ -302,11 +309,13 @@ public class JVMNameUtil { } } } - for (PsiParameter psiParameter : method.getParameterList().getParameters()) { - appendJVMSignature(signature, psiParameter.getType()); + if (method != null) { + for (PsiParameter psiParameter : method.getParameterList().getParameters()) { + appendJVMSignature(signature, psiParameter.getType()); + } } signature.append(")"); - if (!method.isConstructor()) { + if (!constructor && method != null) { appendJVMSignature(signature, method.getReturnType()); } else { diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java index 37ee00b94eaf..af55182e3607 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java @@ -18,20 +18,18 @@ package com.intellij.debugger.engine; import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.actions.DebuggerActions; import com.intellij.debugger.engine.evaluation.EvaluationContext; -import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; import com.intellij.debugger.engine.events.DebuggerCommandImpl; import com.intellij.debugger.engine.events.DebuggerContextCommandImpl; import com.intellij.debugger.impl.*; +import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.settings.DebuggerSettings; import com.intellij.debugger.ui.DebuggerContentInfo; import com.intellij.debugger.ui.breakpoints.Breakpoint; import com.intellij.debugger.ui.impl.ThreadsPanel; import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; import com.intellij.debugger.ui.impl.watch.MessageDescriptor; -import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl; import com.intellij.debugger.ui.impl.watch.NodeManagerImpl; import com.intellij.debugger.ui.tree.NodeDescriptor; -import com.intellij.debugger.ui.tree.render.DescriptorLabelListener; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.ui.ExecutionConsole; import com.intellij.execution.ui.ExecutionConsoleEx; @@ -150,29 +148,40 @@ public class JavaDebugProcess extends XDebugProcess { }; session.addSessionListener(new XDebugSessionAdapter() { @Override - public void beforeSessionResume() { - myJavaSession.getProcess().getManagerThread().schedule(new DebuggerCommandImpl() { - @Override - protected void action() throws Exception { - myNodeManager.setHistoryByContext(getDebuggerStateManager().getContext()); - } - @Override - public Priority getPriority() { - return Priority.NORMAL; - } - }); + public void sessionPaused() { + saveNodeHistory(); } @Override public void stackFrameChanged() { XStackFrame frame = session.getCurrentStackFrame(); if (frame instanceof JavaStackFrame) { - DebuggerContextUtil.setStackFrame(javaSession.getContextManager(), ((JavaStackFrame)frame).getStackFrameProxy()); + StackFrameProxyImpl frameProxy = ((JavaStackFrame)frame).getStackFrameProxy(); + DebuggerContextUtil.setStackFrame(javaSession.getContextManager(), frameProxy); + saveNodeHistory(frameProxy); } } }); } + public void saveNodeHistory() { + saveNodeHistory(getDebuggerStateManager().getContext().getFrameProxy()); + } + + private void saveNodeHistory(final StackFrameProxyImpl frameProxy) { + myJavaSession.getProcess().getManagerThread().invoke(new DebuggerCommandImpl() { + @Override + protected void action() throws Exception { + myNodeManager.setHistoryByContext(frameProxy); + } + + @Override + public Priority getPriority() { + return Priority.NORMAL; + } + }); + } + private DebuggerStateManager getDebuggerStateManager() { return myJavaSession.getContextManager(); } @@ -243,7 +252,7 @@ public class JavaDebugProcess extends XDebugProcess { @Nullable @Override protected ProcessHandler doGetProcessHandler() { - return myJavaSession.getProcess().getExecutionResult().getProcessHandler(); + return myJavaSession.getProcess().getProcessHandler(); } @NotNull @@ -302,23 +311,16 @@ public class JavaDebugProcess extends XDebugProcess { } @Override - public void registerAdditionalActions(@NotNull DefaultActionGroup leftToolbar, @NotNull DefaultActionGroup topToolbar) { + public void registerAdditionalActions(@NotNull DefaultActionGroup leftToolbar, @NotNull DefaultActionGroup topToolbar, @NotNull DefaultActionGroup settings) { Constraints beforeRunner = new Constraints(Anchor.BEFORE, "Runner.Layout"); leftToolbar.add(Separator.getInstance(), beforeRunner); leftToolbar.add(ActionManager.getInstance().getAction(DebuggerActions.EXPORT_THREADS), beforeRunner); leftToolbar.add(ActionManager.getInstance().getAction(DebuggerActions.DUMP_THREADS), beforeRunner); leftToolbar.add(Separator.getInstance(), beforeRunner); - for (AnAction action : leftToolbar.getChildren(null)) { - //TODO: maybe introduce API for extra settings? - if (action instanceof DefaultActionGroup && "DebuggerSettings".equals(action.getTemplatePresentation().getText())) { - DefaultActionGroup settings = (DefaultActionGroup)action; - addActionToGroup(settings, XDebuggerActions.AUTO_TOOLTIP); - settings.addAction(new AutoVarsSwitchAction(), Constraints.FIRST); - settings.addAction(new WatchLastMethodReturnValueAction(), Constraints.FIRST); - break; - } - } + addActionToGroup(settings, XDebuggerActions.AUTO_TOOLTIP); + settings.addAction(new AutoVarsSwitchAction(), Constraints.FIRST); + settings.addAction(new WatchLastMethodReturnValueAction(), Constraints.FIRST); } private static class AutoVarsSwitchAction extends ToggleAction { diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java index f2178c1d4fb5..2eab90666967 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java @@ -82,9 +82,11 @@ public class JavaDebuggerEvaluator extends XDebuggerEvaluator { return; } JavaDebugProcess process = myDebugProcess.getXdebugProcess(); - if (process != null) { - callback.evaluated(JavaValue.create(null, descriptor, evalContext, process.getNodeManager(), true)); + if (process == null) { + callback.errorOccurred("No debug process"); + return; } + callback.evaluated(JavaValue.create(null, descriptor, evalContext, process.getNodeManager(), true)); } }); } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaStaticGroup.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaStaticGroup.java index 1293a0fdd0c0..60d0b708befb 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaStaticGroup.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaStaticGroup.java @@ -17,7 +17,9 @@ package com.intellij.debugger.engine; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; import com.intellij.debugger.engine.events.SuspendContextCommandImpl; +import com.intellij.debugger.settings.NodeRendererSettings; import com.intellij.debugger.ui.impl.watch.*; +import com.intellij.debugger.ui.tree.render.ClassRenderer; import com.intellij.xdebugger.frame.*; import com.sun.jdi.Field; import com.sun.jdi.ReferenceType; @@ -57,8 +59,14 @@ public class JavaStaticGroup extends XValueGroup implements NodeDescriptorProvid final ReferenceType refType = myStaticDescriptor.getType(); List<Field> fields = refType.allFields(); + + final ClassRenderer classRenderer = NodeRendererSettings.getInstance().getClassRenderer(); for (Field field : fields) { if (field.isStatic()) { + boolean isSynthetic = DebuggerUtils.isSynthetic(field); + if (!classRenderer.SHOW_SYNTHETICS && isSynthetic) { + continue; + } final FieldDescriptorImpl fieldDescriptor = myNodeManager.getFieldDescriptor(myStaticDescriptor, null, field); children.add(JavaValue.create(fieldDescriptor, myEvaluationContext, myNodeManager)); //final DebuggerTreeNodeImpl node = myNodeManager.createNode(fieldDescriptor, myEvaluationContext); diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java index 7b0ffffe98d5..b678cf30d661 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java @@ -15,6 +15,7 @@ */ package com.intellij.debugger.engine; +import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.DebuggerInvocationUtil; import com.intellij.debugger.SourcePosition; import com.intellij.debugger.actions.JavaReferringObjectsValue; @@ -102,6 +103,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV } @Override + @NotNull public ValueDescriptorImpl getDescriptor() { return myValueDescriptor; } @@ -273,7 +275,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV @Override public void computeChildren(@NotNull final XCompositeNode node) { - if (myEvaluationContext.getSuspendContext().isResumed()) return; + if (checkContextNotResumed(node)) return; myEvaluationContext.getDebugProcess().getManagerThread().schedule(new SuspendContextCommandImpl(myEvaluationContext.getSuspendContext()) { @Override public Priority getPriority() { @@ -335,6 +337,14 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV }); } + protected boolean checkContextNotResumed(XCompositeNode node) { + if (myEvaluationContext.getSuspendContext().isResumed()) { + node.setErrorMessage(DebuggerBundle.message("error.context.has.changed")); + return true; + } + return false; + } + @Override public void computeSourcePosition(@NotNull final XNavigatable navigatable) { if (myEvaluationContext.getSuspendContext().isResumed()) return; @@ -419,6 +429,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV public String getEvaluationExpression() { if (evaluationExpression == null) { // TODO: change API to allow to calculate it asynchronously + if (myEvaluationContext.getSuspendContext().isResumed()) return null; DebugProcessImpl debugProcess = myEvaluationContext.getDebugProcess(); debugProcess.getManagerThread().invokeAndWait(new DebuggerCommandImpl() { @Override diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java index c7e59106beb8..5aa037191c17 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java @@ -34,6 +34,7 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.util.ProgressIndicatorListenerAdapter; import com.intellij.openapi.progress.util.ProgressWindowWithNotification; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.ui.SimpleColoredComponent; @@ -62,9 +63,12 @@ public class JavaValueModifier extends XValueModifier { @Override public String getInitialValueEditorText() { Value value = myJavaValue.getDescriptor().getValue(); - if (value instanceof PrimitiveValue || value instanceof StringReference) { + if (value instanceof PrimitiveValue) { return myJavaValue.getValueString(); } + else if (value instanceof StringReference) { + return StringUtil.wrapWithDoubleQuote(DebuggerUtils.translateStringValue(myJavaValue.getValueString())); + } return null; } @@ -96,10 +100,12 @@ public class JavaValueModifier extends XValueModifier { @Override public void setValue(@NotNull String expression, @NotNull XModificationCallback callback) { final NodeDescriptorImpl descriptor = myJavaValue.getDescriptor(); - if (!(descriptor instanceof ValueDescriptorImpl)) { + if(!((ValueDescriptorImpl)descriptor).canSetValue()) { return; } - if(!((ValueDescriptorImpl)descriptor).canSetValue()) { + + if (myJavaValue.getEvaluationContext().getSuspendContext().isResumed()) { + callback.errorOccurred(DebuggerBundle.message("error.context.has.changed")); return; } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/EvaluationContextImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/EvaluationContextImpl.java index b6ca9eafe1f1..759d92fd57a8 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/EvaluationContextImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/EvaluationContextImpl.java @@ -30,6 +30,7 @@ public final class EvaluationContextImpl implements EvaluationContext{ private final SuspendContextImpl mySuspendContext; private final StackFrameProxyImpl myFrameProxy; private boolean myAutoLoadClasses = true; + private ClassLoaderReference myClassLoader; public EvaluationContextImpl(@NotNull SuspendContextImpl suspendContext, StackFrameProxyImpl frameProxy, @Nullable Value thisObject) { myThisObject = thisObject; @@ -77,9 +78,16 @@ public final class EvaluationContextImpl implements EvaluationContext{ @Override public ClassLoaderReference getClassLoader() throws EvaluateException { DebuggerManagerThreadImpl.assertIsManagerThread(); + if (myClassLoader != null) { + return myClassLoader; + } return myFrameProxy != null ? myFrameProxy.getClassLoader() : null; } + public void setClassLoader(ClassLoaderReference classLoader) { + myClassLoader = classLoader; + } + public boolean isAutoLoadClasses() { return myAutoLoadClasses; } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java index 83ad91b4e27d..7d0a4aeb0989 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java @@ -31,7 +31,7 @@ import com.intellij.debugger.engine.DebuggerUtils; import com.intellij.debugger.engine.JVMName; import com.intellij.debugger.engine.JVMNameUtil; import com.intellij.debugger.engine.evaluation.*; -import com.intellij.debugger.ui.DebuggerEditorImpl; +import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.psi.*; @@ -66,8 +66,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { final Project project = contextElement.getProject(); - CodeFragmentFactory factory = DebuggerEditorImpl.findAppropriateFactory(text, contextElement); - PsiCodeFragment codeFragment = new CodeFragmentFactoryContextWrapper(factory).createCodeFragment(text, contextElement, project); + CodeFragmentFactory factory = DebuggerUtilsEx.findAppropriateCodeFragmentFactory(text, contextElement); + PsiCodeFragment codeFragment = factory.createCodeFragment(text, contextElement, project); if (codeFragment == null) { throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", text.getText())); } @@ -185,6 +185,11 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { } @Override + public void visitTryStatement(PsiTryStatement statement) { + throw new EvaluateRuntimeException(new UnsupportedExpressionException(statement.getText())); + } + + @Override public void visitStatement(PsiStatement statement) { throwEvaluateException(DebuggerBundle.message("evaluation.error.statement.not.supported", statement.getText())); } @@ -741,24 +746,28 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { } private int calcIterationCount(final PsiJavaCodeReferenceElement qualifier) { - int iterationCount = 0; if (qualifier != null) { - PsiElement targetClass = qualifier.resolve(); - if (targetClass == null || getContextPsiClass() == null) { - throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", qualifier.getText())); - } - try { - PsiClass aClass = getContextPsiClass(); - while (aClass != null && !aClass.equals(targetClass)) { - iterationCount++; - aClass = getOuterClass(aClass); - } - } - catch (Exception e) { - //noinspection ThrowableResultOfMethodCallIgnored - throw new EvaluateRuntimeException(EvaluateExceptionUtil.createEvaluateException(e)); + return calcIterationCount(qualifier.resolve(), qualifier.getText()); + } + return 0; + } + + private int calcIterationCount(PsiElement targetClass, String name) { + int iterationCount = 0; + if (targetClass == null || getContextPsiClass() == null) { + throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", name)); + } + try { + PsiClass aClass = getContextPsiClass(); + while (aClass != null && !aClass.equals(targetClass)) { + iterationCount++; + aClass = getOuterClass(aClass); } } + catch (Exception e) { + //noinspection ThrowableResultOfMethodCallIgnored + throw new EvaluateRuntimeException(EvaluateExceptionUtil.createEvaluateException(e)); + } return iterationCount; } @@ -962,12 +971,16 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { } } + boolean defaultInterfaceMethod = false; + if (psiMethod != null) { processBoxingConversions(psiMethod.getParameterList().getParameters(), argExpressions, resolveResult.getSubstitutor(), argumentEvaluators); argumentEvaluators = wrapVarargs(psiMethod.getParameterList().getParameters(), argExpressions, resolveResult.getSubstitutor(), argumentEvaluators); + defaultInterfaceMethod = psiMethod.hasModifierProperty(PsiModifier.DEFAULT); } - myResult = new MethodEvaluator(objectEvaluator, contextClass, methodExpr.getReferenceName(), psiMethod != null ? JVMNameUtil.getJVMSignature(psiMethod) : null, argumentEvaluators); + myResult = new MethodEvaluator(objectEvaluator, contextClass, methodExpr.getReferenceName(), + psiMethod != null ? JVMNameUtil.getJVMSignature(psiMethod) : null, argumentEvaluators, defaultInterfaceMethod); } @Override @@ -1082,6 +1095,16 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { } @Override + public void visitLambdaExpression(PsiLambdaExpression expression) { + throw new EvaluateRuntimeException(new UnsupportedExpressionException(DebuggerBundle.message("evaluation.error.lambda.evaluation.not.supported"))); + } + + @Override + public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) { + throw new EvaluateRuntimeException(new UnsupportedExpressionException(DebuggerBundle.message("evaluation.error.method.reference.evaluation.not.supported"))); + } + + @Override public void visitNewExpression(final PsiNewExpression expression) { PsiType expressionPsiType = expression.getType(); if (expressionPsiType instanceof PsiArrayType) { @@ -1142,7 +1165,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { else if (expressionPsiType instanceof PsiClassType){ // must be a class ref PsiClass aClass = ((PsiClassType)expressionPsiType).resolve(); if(aClass instanceof PsiAnonymousClass) { - throwEvaluateException(DebuggerBundle.message("evaluation.error.anonymous.class.evaluation.not.supported")); + throw new EvaluateRuntimeException(new UnsupportedExpressionException(DebuggerBundle.message("evaluation.error.anonymous.class.evaluation.not.supported"))); } PsiExpressionList argumentList = expression.getArgumentList(); if (argumentList == null) { @@ -1173,8 +1196,11 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { argumentEvaluators = wrapVarargs(constructor.getParameterList().getParameters(), argExpressions, constructorResolveResult.getSubstitutor(), argumentEvaluators); } - //noinspection HardCodedStringLiteral - JVMName signature = constructor != null ? JVMNameUtil.getJVMSignature(constructor) : JVMNameUtil.getJVMRawText("()V"); + if (aClass != null && aClass.getContainingClass() != null && !aClass.hasModifierProperty(PsiModifier.STATIC)) { + argumentEvaluators = addThisEvaluator(argumentEvaluators, aClass.getContainingClass()); + } + + JVMName signature = JVMNameUtil.getJVMConstructorSignature(constructor, aClass); myResult = new NewClassInstanceEvaluator( new TypeEvaluator(JVMNameUtil.getJVMQualifiedName(expressionPsiType)), signature, @@ -1191,6 +1217,14 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { } } + private Evaluator[] addThisEvaluator(Evaluator[] argumentEvaluators, PsiClass cls) { + Evaluator[] res = new Evaluator[argumentEvaluators.length+1]; + int depth = calcIterationCount(cls, "this"); + res[0] = new ThisEvaluator(depth); + System.arraycopy(argumentEvaluators, 0, res, 1, argumentEvaluators.length); + return res; + } + @Override public void visitArrayInitializerExpression(PsiArrayInitializerExpression expression) { PsiExpression[] initializers = expression.getInitializers(); diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java index 6ba88653749b..80e42e3b61e2 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java @@ -43,13 +43,19 @@ public class MethodEvaluator implements Evaluator { private final String myMethodName; private final Evaluator[] myArgumentEvaluators; private final Evaluator myObjectEvaluator; + private final boolean myCheckDefaultInterfaceMethod; public MethodEvaluator(Evaluator objectEvaluator, JVMName className, String methodName, JVMName signature, Evaluator[] argumentEvaluators) { + this(objectEvaluator, className, methodName, signature, argumentEvaluators, false); + } + + public MethodEvaluator(Evaluator objectEvaluator, JVMName className, String methodName, JVMName signature, Evaluator[] argumentEvaluators, boolean checkDefaultInterfaceMethod) { myObjectEvaluator = new DisableGC(objectEvaluator); myClassName = className; myMethodName = methodName; myMethodSignature = signature; myArgumentEvaluators = argumentEvaluators; + myCheckDefaultInterfaceMethod = checkDefaultInterfaceMethod; } @Override @@ -148,7 +154,7 @@ public class MethodEvaluator implements Evaluator { return debugProcess.invokeInstanceMethod(context, objRef, jdiMethod, args, ObjectReference.INVOKE_NONVIRTUAL); } // fix for default methods in interfaces, see IDEA-124066 - if (Boolean.valueOf(System.getProperty("debugger.invoke.default")) && jdiMethod.declaringType() instanceof InterfaceType) { + if (myCheckDefaultInterfaceMethod && jdiMethod.declaringType() instanceof InterfaceType) { return invokeDefaultMethod(debugProcess, context, objRef, myMethodName); } else { diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/NewClassInstanceEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/NewClassInstanceEvaluator.java index c3e7f8173322..3bbb0c633cd6 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/NewClassInstanceEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/NewClassInstanceEvaluator.java @@ -21,13 +21,13 @@ */ package com.intellij.debugger.engine.evaluation.expression; +import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.engine.DebugProcessImpl; +import com.intellij.debugger.engine.DebuggerUtils; import com.intellij.debugger.engine.JVMName; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; -import com.intellij.debugger.impl.DebuggerUtilsEx; -import com.intellij.debugger.DebuggerBundle; import com.sun.jdi.ClassType; import com.sun.jdi.Method; import com.sun.jdi.ObjectReference; @@ -55,7 +55,7 @@ class NewClassInstanceEvaluator implements Evaluator { } ClassType classType = (ClassType)obj; // find constructor - Method method = DebuggerUtilsEx.findMethod(classType, "<init>", myConstructorSignature.getName(debugProcess)); + Method method = DebuggerUtils.findMethod(classType, "<init>", myConstructorSignature.getName(debugProcess)); if (method == null) { throw EvaluateExceptionUtil.createEvaluateException( DebuggerBundle.message("evaluation.error.cannot.resolve.constructor", myConstructorSignature.getDisplayName(debugProcess))); diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/UnsupportedExpressionException.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/UnsupportedExpressionException.java new file mode 100644 index 000000000000..f4c513d4036c --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/UnsupportedExpressionException.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed 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 com.intellij.debugger.engine.evaluation.expression; + +import com.intellij.debugger.DebuggerBundle; +import com.intellij.debugger.engine.evaluation.EvaluateException; + +/** + * @author egor + */ +public class UnsupportedExpressionException extends EvaluateException { + public UnsupportedExpressionException(String message) { + super(message); + } +} |