diff options
Diffstat (limited to 'java/debugger/impl/src/com/intellij/debugger/engine')
6 files changed, 92 insertions, 46 deletions
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 e37576bae8f4..f2178c1d4fb5 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java @@ -15,6 +15,7 @@ */ package com.intellij.debugger.engine; +import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; import com.intellij.debugger.engine.evaluation.TextWithImportsImpl; import com.intellij.debugger.engine.events.DebuggerContextCommandImpl; @@ -73,9 +74,16 @@ public class JavaDebuggerEvaluator extends XDebuggerEvaluator { callback.errorOccurred("Context is not available"); return; } + descriptor.setContext(evalContext); + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") + EvaluateException exception = descriptor.getEvaluateException(); + if (exception != null) { + callback.errorOccurred(exception.getMessage()); + return; + } JavaDebugProcess process = myDebugProcess.getXdebugProcess(); if (process != null) { - callback.evaluated(JavaValue.create(descriptor, evalContext, process.getNodeManager())); + callback.evaluated(JavaValue.create(null, descriptor, evalContext, process.getNodeManager(), true)); } } }); diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java index f2cb40008ad5..1bd95096055f 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java @@ -17,7 +17,6 @@ package com.intellij.debugger.engine; import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.engine.evaluation.EvaluateException; -import com.intellij.debugger.engine.events.DebuggerCommandImpl; import com.intellij.debugger.engine.events.DebuggerContextCommandImpl; import com.intellij.debugger.engine.events.SuspendContextCommandImpl; import com.intellij.debugger.impl.DebuggerUtilsEx; @@ -46,7 +45,7 @@ public class JavaExecutionStack extends XExecutionStack { private final DebugProcessImpl myDebugProcess; private final NodeManagerImpl myNodeManager; private volatile JavaStackFrame myTopFrame; - private boolean myTopFrameReady = false; + private volatile boolean myTopFrameReady = false; private final MethodsTracker myTracker = new MethodsTracker(); public JavaExecutionStack(@NotNull ThreadReferenceProxyImpl threadProxy, @NotNull DebugProcessImpl debugProcess, boolean current) { @@ -99,25 +98,7 @@ public class JavaExecutionStack extends XExecutionStack { @Nullable @Override public JavaStackFrame getTopFrame() { - if (!myTopFrameReady) { - //TODO: remove sync calculation - if (DebuggerManagerThreadImpl.isManagerThread()) { - myTopFrame = calcTopFrame(); - } - else { - myDebugProcess.getManagerThread().invokeAndWait(new DebuggerCommandImpl() { - @Override - public Priority getPriority() { - return Priority.HIGH; - } - - @Override - protected void action() throws Exception { - myTopFrame = calcTopFrame(); - } - }); - } - } + assert myTopFrameReady : "Top frame must be already calculated here"; return myTopFrame; } @@ -183,8 +164,20 @@ public class JavaExecutionStack extends XExecutionStack { @Override public void contextAction() throws Exception { if (myStackFramesIterator.hasNext()) { - JavaStackFrame frame = new JavaStackFrame(myStackFramesIterator.next(), myDebugProcess, myTracker, myNodeManager); - if (DebuggerSettings.getInstance().SHOW_LIBRARY_STACKFRAMES || (!frame.getDescriptor().isSynthetic() && !frame.getDescriptor().isInLibraryContent())) { + JavaStackFrame frame; + boolean first = myAdded == 0; + if (first && myTopFrameReady) { + frame = myTopFrame; + myStackFramesIterator.next(); + } + else { + frame = new JavaStackFrame(myStackFramesIterator.next(), myDebugProcess, myTracker, myNodeManager); + if (first && !myTopFrameReady) { + myTopFrame = frame; + myTopFrameReady = true; + } + } + if (first || DebuggerSettings.getInstance().SHOW_LIBRARY_STACKFRAMES || (!frame.getDescriptor().isSynthetic() && !frame.getDescriptor().isInLibraryContent())) { if (++myAdded > mySkip) { myContainer.addStackFrames(Arrays.asList(frame), false); } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java index 3f649e2b1dab..e7db635abe13 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java @@ -370,7 +370,7 @@ public class JavaStackFrame extends XStackFrame { ArgumentValueDescriptorImpl descriptor = myNodeManager.getArgumentValueDescriptor(null, index, value, name); // setContext is required to calculate correct name descriptor.setContext(evaluationContext); - return JavaValue.create(descriptor, evaluationContext, myNodeManager); + return JavaValue.create(null, descriptor, evaluationContext, myNodeManager, true); } protected void superBuildVariables(final EvaluationContextImpl evaluationContext, XValueChildrenList children) throws EvaluateException { 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 9cfb2bfde84e..7b0ffffe98d5 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java @@ -17,6 +17,7 @@ package com.intellij.debugger.engine; import com.intellij.debugger.DebuggerInvocationUtil; import com.intellij.debugger.SourcePosition; +import com.intellij.debugger.actions.JavaReferringObjectsValue; import com.intellij.debugger.actions.JumpToObjectAction; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; @@ -66,27 +67,34 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV private final ValueDescriptorImpl myValueDescriptor; private final EvaluationContextImpl myEvaluationContext; private final NodeManagerImpl myNodeManager; + private final boolean myContextSet; - private JavaValue(JavaValue parent, + protected JavaValue(JavaValue parent, @NotNull ValueDescriptorImpl valueDescriptor, @NotNull EvaluationContextImpl evaluationContext, - NodeManagerImpl nodeManager) { + NodeManagerImpl nodeManager, + boolean contextSet) { super(valueDescriptor.getName()); myParent = parent; myValueDescriptor = valueDescriptor; myEvaluationContext = evaluationContext; myNodeManager = nodeManager; + myContextSet = contextSet; } - private static JavaValue create(JavaValue parent, @NotNull ValueDescriptorImpl valueDescriptor, EvaluationContextImpl evaluationContext, NodeManagerImpl nodeManager, boolean init) { + static JavaValue create(JavaValue parent, + @NotNull ValueDescriptorImpl valueDescriptor, + EvaluationContextImpl evaluationContext, + NodeManagerImpl nodeManager, + boolean contextSet) { DebuggerManagerThreadImpl.assertIsManagerThread(); - return new JavaValue(parent, valueDescriptor, evaluationContext, nodeManager); + return new JavaValue(parent, valueDescriptor, evaluationContext, nodeManager, contextSet); } - public static JavaValue create(@NotNull ValueDescriptorImpl valueDescriptor, + static JavaValue create(@NotNull ValueDescriptorImpl valueDescriptor, EvaluationContextImpl evaluationContext, NodeManagerImpl nodeManager) { - return create(null, valueDescriptor, evaluationContext, nodeManager, true); + return create(null, valueDescriptor, evaluationContext, nodeManager, false); } public JavaValue getParent() { @@ -113,7 +121,9 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV @Override public void threadAction() { - myValueDescriptor.setContext(myEvaluationContext); + if (!myContextSet) { + myValueDescriptor.setContext(myEvaluationContext); + } myValueDescriptor.updateRepresentation(myEvaluationContext, new DescriptorLabelListener() { @Override public void labelChanged() { @@ -123,12 +133,12 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV String type = strings[0]; XValuePresentation presentation; if (myValueDescriptor.isString()) { - presentation = new TypedStringValuePresentation(StringUtil.unquoteString(value), type); + presentation = new TypedStringValuePresentation(value, type); } else { EvaluateException exception = myValueDescriptor.getEvaluateException(); if (myValueDescriptor.getLastRenderer() instanceof ToStringRenderer && exception == null) { - presentation = new XRegularValuePresentation(StringUtil.wrapWithDoubleQuote(value), type); + presentation = new XRegularValuePresentation(StringUtil.wrapWithDoubleQuote(value.substring(0,Math.min(value.length(), XValueNode.MAX_VALUE_LENGTH))), type); } else { presentation = new JavaValuePresentation(value, type, exception != null ? exception.getMessage() : null); @@ -339,15 +349,16 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV ApplicationManager.getApplication().runReadAction(new Runnable() { @Override public void run() { + final boolean nearest = navigatable instanceof XNearestSourcePosition; if (myValueDescriptor instanceof FieldDescriptorImpl) { - SourcePosition position = ((FieldDescriptorImpl)myValueDescriptor).getSourcePosition(getProject(), getDebuggerContext()); + SourcePosition position = ((FieldDescriptorImpl)myValueDescriptor).getSourcePosition(getProject(), getDebuggerContext(), nearest); if (position != null) { navigatable.setSourcePosition(DebuggerUtilsEx.toXSourcePosition(position)); } } if (myValueDescriptor instanceof LocalVariableDescriptorImpl) { SourcePosition position = - ((LocalVariableDescriptorImpl)myValueDescriptor).getSourcePosition(getProject(), getDebuggerContext()); + ((LocalVariableDescriptorImpl)myValueDescriptor).getSourcePosition(getProject(), getDebuggerContext(), nearest); if (position != null) { navigatable.setSourcePosition(DebuggerUtilsEx.toXSourcePosition(position)); } @@ -442,4 +453,14 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV public String getValueText() { return myValueDescriptor.getValueText(); } + @Nullable + @Override + public XReferrersProvider getReferrersProvider() { + return new XReferrersProvider() { + @Override + public XValue getReferringObjectsValue() { + return new JavaReferringObjectsValue(JavaValue.this, false); + } + }; + } } 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 45af0e10ac72..83ad91b4e27d 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 @@ -40,6 +40,7 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTypesUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.IncorrectOperationException; import com.sun.jdi.Value; @@ -1036,7 +1037,8 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { final PsiType castType = expression.getCastType().getType(); final PsiType operandType = operandExpr.getType(); - if (castType != null && operandType != null && !TypeConversionUtil.areTypesConvertible(operandType, castType)) { + // if operand type can not be resolved in current context - leave it for runtime checks + if (castType != null && operandType != null && !TypeConversionUtil.areTypesConvertible(operandType, castType) && PsiUtil.resolveClassInType(operandType) != null) { throw new EvaluateRuntimeException( new EvaluateException(JavaErrorMessages.message("inconvertible.type.cast", JavaHighlightUtil.formatType(operandType), JavaHighlightUtil .formatType(castType))) 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 2569559d2d11..6ba88653749b 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 @@ -21,21 +21,19 @@ package com.intellij.debugger.engine.evaluation.expression; import com.intellij.debugger.DebuggerBundle; +import com.intellij.debugger.engine.DebugProcess; 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.EvaluateRuntimeException; -import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; +import com.intellij.debugger.engine.evaluation.*; import com.intellij.debugger.impl.DebuggerUtilsEx; +import com.intellij.debugger.jdi.VirtualMachineProxyImpl; import com.intellij.openapi.diagnostic.Logger; -import com.sun.jdi.ClassType; -import com.sun.jdi.Method; -import com.sun.jdi.ObjectReference; -import com.sun.jdi.ReferenceType; +import com.intellij.rt.debugger.DefaultMethodInvoker; +import com.sun.jdi.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class MethodEvaluator implements Evaluator { @@ -149,7 +147,13 @@ public class MethodEvaluator implements Evaluator { if (requiresSuperObject) { return debugProcess.invokeInstanceMethod(context, objRef, jdiMethod, args, ObjectReference.INVOKE_NONVIRTUAL); } - return debugProcess.invokeMethod(context, objRef, jdiMethod, args); + // fix for default methods in interfaces, see IDEA-124066 + if (Boolean.valueOf(System.getProperty("debugger.invoke.default")) && jdiMethod.declaringType() instanceof InterfaceType) { + return invokeDefaultMethod(debugProcess, context, objRef, myMethodName); + } + else { + return debugProcess.invokeMethod(context, objRef, jdiMethod, args); + } } catch (Exception e) { if (LOG.isDebugEnabled()) { @@ -158,4 +162,22 @@ public class MethodEvaluator implements Evaluator { throw EvaluateExceptionUtil.createEvaluateException(e); } } + + // only methods without arguments for now + private static Value invokeDefaultMethod(DebugProcess debugProcess, EvaluationContext evaluationContext, + Value obj, String name) + throws EvaluateException, ClassNotLoadedException, InvalidTypeException { + ClassType invokerClass = (ClassType)debugProcess.findClass( + evaluationContext, DefaultMethodInvoker.class.getName(), + evaluationContext.getClassLoader()); + + if (invokerClass != null) { + List<Method> methods = invokerClass.methodsByName("invoke"); + if (!methods.isEmpty()) { + return debugProcess.invokeMethod(evaluationContext, invokerClass, methods.get(0), + Arrays.asList(obj, ((VirtualMachineProxyImpl)debugProcess.getVirtualMachineProxy()).mirrorOf(name))); + } + } + return null; + } } |