diff options
Diffstat (limited to 'java/debugger')
20 files changed, 646 insertions, 264 deletions
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/AdjustArrayRangeAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/AdjustArrayRangeAction.java index 3a821fb10c0f..ce375815bb77 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/AdjustArrayRangeAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/AdjustArrayRangeAction.java @@ -23,12 +23,10 @@ import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl; import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; import com.intellij.debugger.ui.tree.render.*; -import com.intellij.ide.actions.ShowSettingsUtilImpl; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.options.ex.SingleConfigurableEditor; +import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; import org.jetbrains.annotations.Nullable; public class AdjustArrayRangeAction extends DebuggerAction { @@ -67,30 +65,25 @@ public class AdjustArrayRangeAction extends DebuggerAction { title = title + " " + label.substring(index); } final ArrayRenderer clonedRenderer = renderer.clone(); - final NamedArrayConfigurable configurable = new NamedArrayConfigurable(title, clonedRenderer); - SingleConfigurableEditor editor = new SingleConfigurableEditor(project, configurable, - ShowSettingsUtilImpl.createDimensionKey(configurable), false); - editor.show(); - - if(editor.getExitCode() == DialogWrapper.OK_EXIT_CODE) { + if (ShowSettingsUtil.getInstance().editConfigurable(project, new NamedArrayConfigurable(title, clonedRenderer))) { debugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(debuggerContext.getSuspendContext()) { - @Override - public void contextAction() throws Exception { - final ValueDescriptorImpl nodeDescriptor = (ValueDescriptorImpl)selectedNode.getDescriptor(); - final Renderer lastRenderer = nodeDescriptor.getLastRenderer(); - if (lastRenderer instanceof ArrayRenderer) { - selectedNode.setRenderer(clonedRenderer); - } - else if (lastRenderer instanceof CompoundNodeRenderer) { - final CompoundNodeRenderer compoundRenderer = (CompoundNodeRenderer)lastRenderer; - final ChildrenRenderer childrenRenderer = compoundRenderer.getChildrenRenderer(); - if (childrenRenderer instanceof ExpressionChildrenRenderer) { - ExpressionChildrenRenderer.setPreferableChildrenRenderer(nodeDescriptor, clonedRenderer); - selectedNode.calcRepresentation(); - } + @Override + public void contextAction() throws Exception { + final ValueDescriptorImpl nodeDescriptor = (ValueDescriptorImpl)selectedNode.getDescriptor(); + final Renderer lastRenderer = nodeDescriptor.getLastRenderer(); + if (lastRenderer instanceof ArrayRenderer) { + selectedNode.setRenderer(clonedRenderer); + } + else if (lastRenderer instanceof CompoundNodeRenderer) { + final CompoundNodeRenderer compoundRenderer = (CompoundNodeRenderer)lastRenderer; + final ChildrenRenderer childrenRenderer = compoundRenderer.getChildrenRenderer(); + if (childrenRenderer instanceof ExpressionChildrenRenderer) { + ExpressionChildrenRenderer.setPreferableChildrenRenderer(nodeDescriptor, clonedRenderer); + selectedNode.calcRepresentation(); } } - }); + } + }); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeThreadsViewAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeThreadsViewAction.java index 64705a373a21..7cef867334df 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeThreadsViewAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeThreadsViewAction.java @@ -19,23 +19,15 @@ import com.intellij.debugger.settings.ThreadsViewConfigurable; import com.intellij.debugger.settings.ThreadsViewSettings; import com.intellij.idea.ActionsBundle; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.options.ex.SingleConfigurableEditor; -import com.intellij.openapi.project.Project; +import com.intellij.openapi.options.ShowSettingsUtil; -/** - * User: lex - * Date: Sep 26, 2003 - * Time: 4:40:12 PM - */ public class CustomizeThreadsViewAction extends DebuggerAction { + @Override public void actionPerformed(AnActionEvent e) { - Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); - final SingleConfigurableEditor editor = new SingleConfigurableEditor(project, new ThreadsViewConfigurable(ThreadsViewSettings.getInstance())); - editor.show(); + ShowSettingsUtil.getInstance().editConfigurable(e.getProject(), new ThreadsViewConfigurable(ThreadsViewSettings.getInstance())); } + @Override public void update(AnActionEvent e) { e.getPresentation().setVisible(true); e.getPresentation().setText(ActionsBundle.actionText(DebuggerActions.CUSTOMIZE_THREADS_VIEW)); diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaReferringObjectsValue.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaReferringObjectsValue.java new file mode 100644 index 000000000000..815ddd231f14 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaReferringObjectsValue.java @@ -0,0 +1,172 @@ +/* + * 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.actions; + +import com.intellij.debugger.DebuggerContext; +import com.intellij.debugger.engine.JavaValue; +import com.intellij.debugger.engine.evaluation.EvaluateException; +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; +import com.intellij.debugger.engine.events.SuspendContextCommandImpl; +import com.intellij.debugger.ui.impl.watch.FieldDescriptorImpl; +import com.intellij.debugger.ui.impl.watch.NodeManagerImpl; +import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; +import com.intellij.psi.PsiExpression; +import com.intellij.xdebugger.frame.*; +import com.intellij.xdebugger.frame.presentation.XValuePresentation; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodePresentationConfigurator; +import com.sun.jdi.Field; +import com.sun.jdi.ObjectReference; +import com.sun.jdi.Value; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.List; + +public class JavaReferringObjectsValue extends JavaValue { + private static final long MAX_REFERRING = 100; + private final boolean myIsField; + + private JavaReferringObjectsValue(@Nullable JavaValue parent, + @NotNull ValueDescriptorImpl valueDescriptor, + @NotNull EvaluationContextImpl evaluationContext, + NodeManagerImpl nodeManager, + boolean isField) { + super(parent, valueDescriptor, evaluationContext, nodeManager, false); + myIsField = isField; + } + + public JavaReferringObjectsValue(@NotNull JavaValue javaValue, boolean isField) { + super(null, javaValue.getDescriptor(), javaValue.getEvaluationContext(), null, false); + myIsField = isField; + } + + @Override + public boolean canNavigateToSource() { + return true; + } + + @Override + public void computeChildren(@NotNull final XCompositeNode node) { + getEvaluationContext().getDebugProcess().getManagerThread().schedule( + new SuspendContextCommandImpl(getEvaluationContext().getSuspendContext()) { + @Override + public Priority getPriority() { + return Priority.NORMAL; + } + + @Override + public void contextAction() throws Exception { + final XValueChildrenList children = new XValueChildrenList(); + + Value value = getDescriptor().getValue(); + List<ObjectReference> references = ((ObjectReference)value).referringObjects(MAX_REFERRING); + int i = 1; + for (final ObjectReference reference : references) { + // try to find field name + Field field = findField(reference, value); + if (field != null) { + ValueDescriptorImpl descriptor = new FieldDescriptorImpl(getProject(), reference, field) { + @Override + public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException { + return reference; + } + }; + children.add(new JavaReferringObjectsValue(null, descriptor, getEvaluationContext(), null, true)); + i++; + } + else { + ValueDescriptorImpl descriptor = new ValueDescriptorImpl(getProject(), reference) { + @Override + public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException { + return reference; + } + + @Override + public String getName() { + return "Ref"; + } + + @Override + public String calcValueName() { + return "Ref"; + } + + @Override + public PsiExpression getDescriptorEvaluation(DebuggerContext context) throws EvaluateException { + return null; + } + }; + children.add("Referrer " + i++, new JavaReferringObjectsValue(null, descriptor, getEvaluationContext(), null, false)); + } + } + + node.addChildren(children, true); + } + } + ); + } + + @Override + public void computePresentation(@NotNull final XValueNode node, @NotNull final XValuePlace place) { + if (!myIsField) { + super.computePresentation(node, place); + } + else { + super.computePresentation(new XValueNodePresentationConfigurator.ConfigurableXValueNodeImpl() { + @Override + public void applyPresentation(@Nullable Icon icon, @NotNull final XValuePresentation valuePresenter, boolean hasChildren) { + node.setPresentation(icon, new XValuePresentation() { + @NotNull + @Override + public String getSeparator() { + return " in "; + } + + @Nullable + @Override + public String getType() { + return valuePresenter.getType(); + } + + @Override + public void renderValue(@NotNull XValueTextRenderer renderer) { + valuePresenter.renderValue(renderer); + } + }, hasChildren); + } + + @Override + public void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator) { + } + + @Override + public boolean isObsolete() { + return false; + } + }, place); + } + } + + private static Field findField(ObjectReference reference, Value value) { + for (Field field : reference.referenceType().allFields()) { + if (reference.getValue(field) == value) { + return field; + } + } + return null; + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ShowReferringObjectsAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ShowReferringObjectsAction.java deleted file mode 100644 index 68275af275c4..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ShowReferringObjectsAction.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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.actions; - -import com.intellij.debugger.DebuggerContext; -import com.intellij.debugger.engine.JavaValue; -import com.intellij.debugger.engine.evaluation.EvaluateException; -import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; -import com.intellij.debugger.engine.events.SuspendContextCommandImpl; -import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.psi.PsiExpression; -import com.intellij.xdebugger.frame.*; -import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; -import com.intellij.xdebugger.impl.ui.tree.XInspectDialog; -import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase; -import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; -import com.sun.jdi.ObjectReference; -import com.sun.jdi.Value; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -/** - * @author egor - */ -public class ShowReferringObjectsAction extends XDebuggerTreeActionBase { - private static final long MAX_REFERRING = 100; - - @Override - public void update(AnActionEvent e) { - super.update(e); - } - - @Override - protected void perform(XValueNodeImpl node, @NotNull String nodeName, AnActionEvent e) { - XValue container = node.getValueContainer(); - JavaValue javaValue = null; - if (container instanceof ReferringObjectsValue) { - javaValue = ((ReferringObjectsValue)container).myJavaValue; - } - else if (container instanceof JavaValue) { - javaValue = ((JavaValue)container); - } - if (javaValue != null) { - XDebuggerTree tree = XDebuggerTree.getTree(e.getDataContext()); - XInspectDialog dialog = new XInspectDialog(tree.getProject(), - tree.getEditorsProvider(), - tree.getSourcePosition(), - nodeName, - new ReferringObjectsValue(javaValue), - tree.getValueMarkers()); - dialog.setTitle("Referring objects for " + nodeName); - dialog.show(); - } - } - - private static class ReferringObjectsValue extends XValue { - private final JavaValue myJavaValue; - - public ReferringObjectsValue(JavaValue javaValue) { - myJavaValue = javaValue; - } - - @Override - public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) { - myJavaValue.computePresentation(node, place); - } - - @Override - public void computeChildren(@NotNull final XCompositeNode node) { - myJavaValue.getEvaluationContext().getDebugProcess().getManagerThread().schedule( - new SuspendContextCommandImpl(myJavaValue.getEvaluationContext().getSuspendContext()) { - @Override - public Priority getPriority() { - return Priority.NORMAL; - } - - @Override - public void contextAction() throws Exception { - final XValueChildrenList children = new XValueChildrenList(); - - Value value = myJavaValue.getDescriptor().getValue(); - List<ObjectReference> references = ((ObjectReference)value).referringObjects(MAX_REFERRING); - int i = 1; - for (final ObjectReference reference : references) { - ValueDescriptorImpl descriptor = new ValueDescriptorImpl(myJavaValue.getProject(), reference) { - @Override - public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException { - return reference; - } - - @Override - public String getName() { - return "Ref"; - } - - @Override - public String calcValueName() { - return "Ref"; - } - - @Override - public PsiExpression getDescriptorEvaluation(DebuggerContext context) throws EvaluateException { - return null; - } - }; - JavaValue jValue = JavaValue.create(descriptor, myJavaValue.getEvaluationContext(), null); - children.add("Referrer " + i++ ,new ReferringObjectsValue(jValue)); - } - - node.addChildren(children, true); - } - } - ); - } - } -} diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ToggleMethodBreakpointAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ToggleMethodBreakpointAction.java index 097039b0f9f4..b239fee363fc 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ToggleMethodBreakpointAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ToggleMethodBreakpointAction.java @@ -38,6 +38,7 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiMethod; +import com.intellij.util.DocumentUtil; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.Nullable; @@ -66,7 +67,7 @@ public class ToggleMethodBreakpointAction extends AnAction { } final BreakpointManager manager = debugManager.getBreakpointManager(); final PlaceInDocument place = getPlace(e); - if(place != null) { + if(place != null && DocumentUtil.isValidOffset(place.getOffset(), place.getDocument())) { Breakpoint breakpoint = manager.findBreakpoint(place.getDocument(), place.getOffset(), MethodBreakpoint.CATEGORY); if(breakpoint == null) { final int methodLine = place.getDocument().getLineNumber(place.getOffset()); 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; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java index e75abd2f1e52..8408364f7e73 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -15,13 +15,27 @@ */ package com.intellij.debugger.impl; +import com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPass; +import com.intellij.debugger.SourcePosition; import com.intellij.debugger.engine.SuspendContextImpl; import com.intellij.debugger.engine.SuspendManagerUtil; import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.ui.impl.watch.ThreadDescriptorImpl; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Couple; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiUtilBase; +import com.intellij.xdebugger.XDebugSession; +import com.intellij.xdebugger.XSourcePosition; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + public class DebuggerContextUtil { public static void setStackFrame(DebuggerStateManager manager, final StackFrameProxyImpl stackFrame) { ApplicationManager.getApplication().assertIsDispatchThread(); @@ -53,4 +67,43 @@ public class DebuggerContextUtil { public static DebuggerContextImpl createDebuggerContext(@NotNull DebuggerSession session, SuspendContextImpl suspendContext){ return DebuggerContextImpl.createDebuggerContext(session, suspendContext, suspendContext != null ? suspendContext.getThread() : null, null); } + + public static SourcePosition findNearest(@NotNull DebuggerContextImpl context, @NotNull PsiElement psi, @NotNull PsiFile file) { + final DebuggerSession session = context.getDebuggerSession(); + if (session != null) { + try { + final XDebugSession debugSession = session.getXDebugSession(); + if (debugSession != null) { + final XSourcePosition position = debugSession.getCurrentPosition(); + final Editor editor = PsiUtilBase.findEditor(psi); + if (editor != null && position != null && file.getVirtualFile().equals(position.getFile())) { + final Couple<Collection<TextRange>> usages = IdentifierHighlighterPass.getHighlightUsages(psi, file); + final List<TextRange> ranges = new ArrayList<TextRange>(); + ranges.addAll(usages.first); + ranges.addAll(usages.second); + final int breakPointLine = position.getLine(); + int bestLine = -1; + boolean hasSameLine = false; + for (TextRange range : ranges) { + final int line = editor.offsetToLogicalPosition(range.getStartOffset()).line; + if (line > bestLine && line < breakPointLine) { + bestLine = line; + } else if (line == breakPointLine) { + hasSameLine = true; + } + } + if (bestLine > 0) { + if (hasSameLine && breakPointLine - bestLine > 4) { + return SourcePosition.createFromLine(file, breakPointLine); + } + return SourcePosition.createFromLine(file, bestLine); + } + } + } + } + catch (Exception ignore) { + } + } + return SourcePosition.createFromOffset(file, psi.getTextOffset()); + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapProgressImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapProgressImpl.java index b2b0091fc949..601ec7957849 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapProgressImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapProgressImpl.java @@ -38,7 +38,7 @@ import java.util.Collections; import java.util.List; public class HotSwapProgressImpl extends HotSwapProgress{ - static final NotificationGroup NOTIFICATION_GROUP = NotificationGroup.toolWindowGroup("HotSwap", ToolWindowId.DEBUG, true); + static final NotificationGroup NOTIFICATION_GROUP = NotificationGroup.toolWindowGroup("HotSwap", ToolWindowId.DEBUG); TIntObjectHashMap<List<String>> myMessages = new TIntObjectHashMap<List<String>>(); private final ProgressWindow myProgressWindow; diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java index 20d95f8fff3d..ec2288fa7a57 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java @@ -165,7 +165,7 @@ public class JavaDebuggerSupport extends DebuggerSupport { @NotNull @Override public DebuggerActionHandler getAddToWatchesActionHandler() { - return myAddToWatchedActionHandler; + return DISABLED; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/CompilingEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/CompilingEvaluator.java new file mode 100644 index 000000000000..042216c40f05 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/CompilingEvaluator.java @@ -0,0 +1,217 @@ +/* + * 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.ui.impl.watch; + +import com.intellij.debugger.engine.DebugProcess; +import com.intellij.debugger.engine.evaluation.EvaluateException; +import com.intellij.debugger.engine.evaluation.EvaluationContext; +import com.intellij.debugger.engine.evaluation.TextWithImports; +import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator; +import com.intellij.debugger.engine.evaluation.expression.Modifier; +import com.intellij.debugger.jdi.VirtualMachineProxyImpl; +import com.sun.jdi.*; + +import javax.tools.*; +import java.io.ByteArrayOutputStream; +import java.net.URI; +import java.util.*; + +/** +* @author egor +*/ +class CompilingEvaluator implements ExpressionEvaluator { + private final TextWithImports myText; + + public CompilingEvaluator(TextWithImports text) { + myText = text; + } + + @Override + public Value getValue() { + return null; + } + + @Override + public Modifier getModifier() { + return null; + } + + @Override + public Value evaluate(EvaluationContext context) throws EvaluateException { + try { + DebugProcess process = context.getDebugProcess(); + ThreadReference threadReference = context.getSuspendContext().getThread().getThreadReference(); + + ClassLoaderReference classLoader = getClassLoader(context); + + Collection<OutputFileObject> classes = compile(); + + ClassType mainClass = defineClasses(classes, context, process, threadReference, classLoader); + + Method foo = mainClass.methodsByName(GEN_METHOD_NAME).get(0); + return mainClass.invokeMethod(threadReference, foo, Collections.<Value>emptyList() ,ClassType.INVOKE_SINGLE_THREADED); + } + catch (Exception e) { + throw new EvaluateException(e.getMessage()); + } + } + + private static ClassLoaderReference getClassLoader(EvaluationContext context) + throws EvaluateException, InvocationException, InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException { + // TODO: cache + DebugProcess process = context.getDebugProcess(); + ClassType loaderClass = (ClassType)process.findClass(context, "java.net.URLClassLoader", context.getClassLoader()); + Method ctorMethod = loaderClass.concreteMethodByName("<init>", "([Ljava/net/URL;)V"); + ThreadReference threadReference = context.getSuspendContext().getThread().getThreadReference(); + return (ClassLoaderReference)loaderClass.newInstance(threadReference, ctorMethod, + Arrays.asList(createURLArray(context)), ClassType.INVOKE_SINGLE_THREADED); + } + + private static ClassType defineClasses(Collection<OutputFileObject> classes, + EvaluationContext context, + DebugProcess process, + ThreadReference threadReference, + ClassLoaderReference classLoader) + throws EvaluateException, InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException { + + VirtualMachineProxyImpl proxy = (VirtualMachineProxyImpl)process.getVirtualMachineProxy(); + for (OutputFileObject cls : classes) { + Method defineMethod = ((ClassType)classLoader.referenceType()).concreteMethodByName("defineClass", "(Ljava/lang/String;[BII)Ljava/lang/Class;"); + byte[] bytes = cls.toByteArray(); + ArrayList<Value> args = new ArrayList<Value>(); + args.add(proxy.mirrorOf(cls.myOrigName)); + args.add(mirrorOf(bytes, context, process)); + args.add(proxy.mirrorOf(0)); + args.add(proxy.mirrorOf(bytes.length)); + classLoader.invokeMethod(threadReference, defineMethod, args, ClassType.INVOKE_SINGLE_THREADED); + } + return (ClassType)process.findClass(context, GEN_CLASS_FULL_NAME, classLoader); + } + + private static ArrayReference mirrorOf(byte[] bytes, EvaluationContext context, DebugProcess process) + throws EvaluateException, InvalidTypeException, ClassNotLoadedException { + ArrayType arrayClass = (ArrayType)process.findClass(context, "byte[]", context.getClassLoader()); + ArrayReference reference = process.newInstance(arrayClass, bytes.length); + reference.disableCollection(); + for (int i = 0; i < bytes.length; i++) { + reference.setValue(i, ((VirtualMachineProxyImpl)process.getVirtualMachineProxy()).mirrorOf(bytes[i])); + } + return reference; + } + + private static final String GEN_CLASS_NAME = "Evaluator"; + private static final String GEN_CLASS_PACKAGE = "dummy"; + private static final String GEN_CLASS_FULL_NAME = GEN_CLASS_PACKAGE + '.' + GEN_CLASS_NAME; + private static final String GEN_METHOD_NAME = "eval"; + + private static String createClassCode(TextWithImports body) { + StringBuilder text = new StringBuilder(); + text.append("package " + GEN_CLASS_PACKAGE + ";"); + String imports = body.getImports(); + if (!imports.isEmpty()) { + for (String s : imports.split(",")) { + text.append("import " + s + ";"); + } + } + String bodyText = body.getText(); + if (!bodyText.endsWith(";")) { + bodyText += ';'; + } + text.append("public class " + GEN_CLASS_NAME + " { public static Object " + GEN_METHOD_NAME + "() throws Exception {" + bodyText + "}}"); + return text.toString(); + } + + private static ArrayReference createURLArray(EvaluationContext context) + throws EvaluateException, InvocationException, InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException { + DebugProcess process = context.getDebugProcess(); + ArrayType arrayType = (ArrayType)process.findClass(context, "java.net.URL[]", context.getClassLoader()); + ArrayReference arrayRef = arrayType.newInstance(1); + ClassType classType = (ClassType)process.findClass(context, "java.net.URL", context.getClassLoader()); + VirtualMachineProxyImpl proxy = (VirtualMachineProxyImpl)process.getVirtualMachineProxy(); + ThreadReference threadReference = context.getSuspendContext().getThread().getThreadReference(); + ObjectReference reference = classType.newInstance(threadReference, classType.concreteMethodByName("<init>", "(Ljava/lang/String;)V"), + Arrays.asList(proxy.mirrorOf("file:a")), ClassType.INVOKE_SINGLE_THREADED); + arrayRef.setValues(Arrays.asList(reference)); + return arrayRef; + } + + ///////////////// Compiler stuff + + private Collection<OutputFileObject> compile() throws EvaluateException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + MemoryFileManager manager = new MemoryFileManager(compiler); + DiagnosticCollector<JavaFileObject> diagnostic = new DiagnosticCollector<JavaFileObject>(); + if (!compiler.getTask(null, manager, diagnostic, null, null, Arrays + .asList(new SourceFileObject(GEN_CLASS_NAME, JavaFileObject.Kind.SOURCE, createClassCode(myText)))).call()) { + // TODO: show only errors + throw new EvaluateException(diagnostic.getDiagnostics().get(0).getMessage(Locale.getDefault())); + } + return manager.classes; + } + + private static URI getUri(String name, JavaFileObject.Kind kind) { + return URI.create("memo:///" + name.replace('.', '/') + kind.extension); + } + + private static class SourceFileObject extends SimpleJavaFileObject { + private final String myContent; + + SourceFileObject(String name, Kind kind, String content) { + super(getUri(name, kind), kind); + myContent = content; + } + + @Override + public CharSequence getCharContent(boolean ignore) { + return myContent; + } + } + + private static class OutputFileObject extends SimpleJavaFileObject { + private final ByteArrayOutputStream myStream = new ByteArrayOutputStream(); + private final String myOrigName; + + OutputFileObject(String name, Kind kind) { + super(getUri(name, kind), kind); + myOrigName = name; + } + + byte[] toByteArray() { + return myStream.toByteArray(); + } + + @Override + public ByteArrayOutputStream openOutputStream() { + return myStream; + } + } + + private static class MemoryFileManager extends ForwardingJavaFileManager { + private final Collection<OutputFileObject> classes = new ArrayList<OutputFileObject>(); + + MemoryFileManager(JavaCompiler compiler) { + super(compiler.getStandardFileManager(null, null, null)); + } + + @Override + public OutputFileObject getJavaFileForOutput(Location location, String name, JavaFileObject.Kind kind, FileObject source) { + OutputFileObject mc = new OutputFileObject(name, kind); + classes.add(mc); + return mc; + } + } + +} diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/EvaluationDescriptor.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/EvaluationDescriptor.java index e09c17c979e5..1f880513cacd 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/EvaluationDescriptor.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/EvaluationDescriptor.java @@ -28,6 +28,7 @@ import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.debugger.impl.PositionUtil; import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.PsiCodeFragment; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiExpression; @@ -80,14 +81,20 @@ public abstract class EvaluationDescriptor extends ValueDescriptorImpl{ try { final EvaluationContextImpl thisEvaluationContext = getEvaluationContext(evaluationContext); - final ExpressionEvaluator evaluator = DebuggerInvocationUtil.commitAndRunReadAction(myProject, new EvaluatingComputable<ExpressionEvaluator>() { - public ExpressionEvaluator compute() throws EvaluateException { - final PsiElement psiContext = PositionUtil.getContextElement(evaluationContext); - return getEffectiveCodeFragmentFactory(psiContext).getEvaluatorBuilder().build(getEvaluationCode(thisEvaluationContext), - ContextUtil.getSourcePosition(thisEvaluationContext)); - } - }); - + final ExpressionEvaluator evaluator; + if (Registry.is("debugger.compiling.evaluator")) { + evaluator = new CompilingEvaluator(getEvaluationText()); + } + else { + evaluator = DebuggerInvocationUtil.commitAndRunReadAction(myProject, new EvaluatingComputable<ExpressionEvaluator>() { + public ExpressionEvaluator compute() throws EvaluateException { + final PsiElement psiContext = PositionUtil.getContextElement(evaluationContext); + return getEffectiveCodeFragmentFactory(psiContext).getEvaluatorBuilder().build(getEvaluationCode(thisEvaluationContext), + ContextUtil + .getSourcePosition(thisEvaluationContext)); + } + }); + } if (!thisEvaluationContext.getDebugProcess().isAttached()) { throw EvaluateExceptionUtil.PROCESS_EXITED; diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java index 6a7a57ba7670..c36630e3a973 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -26,6 +26,7 @@ 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.DebuggerContextImpl; +import com.intellij.debugger.impl.DebuggerContextUtil; import com.intellij.debugger.impl.DebuggerSession; import com.intellij.debugger.impl.PositionUtil; import com.intellij.debugger.settings.NodeRendererSettings; @@ -73,6 +74,12 @@ public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDes @SuppressWarnings({"HardCodedStringLiteral"}) @Nullable public SourcePosition getSourcePosition(final Project project, final DebuggerContextImpl context) { + return getSourcePosition(project, context, false); + } + + @SuppressWarnings({"HardCodedStringLiteral"}) + @Nullable + public SourcePosition getSourcePosition(final Project project, final DebuggerContextImpl context, boolean nearest) { if (context.getFrameProxy() == null) { return null; } @@ -95,6 +102,9 @@ public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDes if (psiVariable == null) { return null; } + if (nearest) { + return DebuggerContextUtil.findNearest(context, psiVariable, aClass.getContainingFile()); + } return SourcePosition.createFromOffset(psiVariable.getContainingFile(), psiVariable.getTextOffset()); } else { @@ -125,6 +135,9 @@ public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDes aClass = (PsiClass) aClass.getNavigationElement(); for (PsiField field : aClass.getFields()) { if (fieldName.equals(field.getName())) { + if (nearest) { + return DebuggerContextUtil.findNearest(context, field, aClass.getContainingFile()); + } return SourcePosition.createFromOffset(field.getContainingFile(), field.getTextOffset()); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/LocalVariableDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/LocalVariableDescriptorImpl.java index d2109c54f1c4..f936d79a6725 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/LocalVariableDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/LocalVariableDescriptorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -22,6 +22,7 @@ import com.intellij.debugger.engine.DebuggerUtils; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; import com.intellij.debugger.impl.DebuggerContextImpl; +import com.intellij.debugger.impl.DebuggerContextUtil; import com.intellij.debugger.impl.PositionUtil; import com.intellij.debugger.jdi.LocalVariableProxyImpl; import com.intellij.debugger.jdi.StackFrameProxyImpl; @@ -61,6 +62,11 @@ public class LocalVariableDescriptorImpl extends ValueDescriptorImpl implements @Nullable public SourcePosition getSourcePosition(final Project project, final DebuggerContextImpl context) { + return getSourcePosition(project, context, false); + } + + @Nullable + public SourcePosition getSourcePosition(final Project project, final DebuggerContextImpl context, boolean nearest) { StackFrameProxyImpl frame = context.getFrameProxy(); if (frame == null) return null; @@ -77,7 +83,9 @@ public class LocalVariableDescriptorImpl extends ValueDescriptorImpl implements PsiFile containingFile = psiVariable.getContainingFile(); if(containingFile == null) return null; - + if (nearest) { + return DebuggerContextUtil.findNearest(context, psiVariable, containingFile); + } return SourcePosition.createFromOffset(containingFile, psiVariable.getTextOffset()); } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java index f4da39f318a7..680d2ab424c3 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java @@ -203,6 +203,7 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements } catch (EvaluateException e) { myValueException = e; + setFailed(e); myValue = getTargetExceptionWithStackTraceFilled(evaluationContext, e); myIsExpandable = false; } diff --git a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java index 9028b1489970..45f50d34b922 100644 --- a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java +++ b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -128,7 +128,12 @@ public abstract class SourcePosition implements Navigatable{ return true; } final PsiElement psiElement = myPsiElement; - return psiElement != null && !psiElement.isValid(); + return psiElement != null && !ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() { + @Override + public Boolean compute() { + return psiElement.isValid(); + } + }); } @Override @@ -194,7 +199,7 @@ public abstract class SourcePosition implements Navigatable{ @Nullable protected PsiElement calcPsiElement() { - PsiFile psiFile = getFile(); + final PsiFile psiFile = getFile(); int lineNumber = getLine(); if(lineNumber < 0) { return psiFile; @@ -207,47 +212,52 @@ public abstract class SourcePosition implements Navigatable{ if (lineNumber >= document.getLineCount()) { return psiFile; } - int startOffset = document.getLineStartOffset(lineNumber); + final int startOffset = document.getLineStartOffset(lineNumber); if(startOffset == -1) { return null; } - PsiElement rootElement = psiFile; - - List<PsiFile> allFiles = psiFile.getViewProvider().getAllFiles(); - if (allFiles.size() > 1) { // jsp & gsp - PsiClassOwner owner = ContainerUtil.findInstance(allFiles, PsiClassOwner.class); - if (owner != null) { - PsiClass[] classes = owner.getClasses(); - if (classes.length == 1 && classes[0] instanceof SyntheticElement) { - rootElement = classes[0]; + return ApplicationManager.getApplication().runReadAction(new Computable<PsiElement>() { + @Override + public PsiElement compute() { + PsiElement rootElement = psiFile; + + List<PsiFile> allFiles = psiFile.getViewProvider().getAllFiles(); + if (allFiles.size() > 1) { // jsp & gsp + PsiClassOwner owner = ContainerUtil.findInstance(allFiles, PsiClassOwner.class); + if (owner != null) { + PsiClass[] classes = owner.getClasses(); + if (classes.length == 1 && classes[0] instanceof SyntheticElement) { + rootElement = classes[0]; + } + } } - } - } - PsiElement element; - while(true) { - final CharSequence charsSequence = document.getCharsSequence(); - for (; startOffset < charsSequence.length(); startOffset++) { - char c = charsSequence.charAt(startOffset); - if (c != ' ' && c != '\t') { - break; + PsiElement element; + int offset = startOffset; + while (true) { + final CharSequence charsSequence = document.getCharsSequence(); + for (; offset < charsSequence.length(); offset++) { + char c = charsSequence.charAt(offset); + if (c != ' ' && c != '\t') { + break; + } + } + element = rootElement.findElementAt(offset); + + if (element instanceof PsiComment) { + offset = element.getTextRange().getEndOffset() + 1; + } + else { + break; + } } + if (element != null && element.getParent() instanceof PsiForStatement) { + return ((PsiForStatement)element.getParent()).getInitialization(); + } + return element; } - element = rootElement.findElementAt(startOffset); - - if(element instanceof PsiComment) { - startOffset = element.getTextRange().getEndOffset() + 1; - } - else{ - break; - } - } - - if (element != null && element.getParent() instanceof PsiForStatement) { - return ((PsiForStatement)element.getParent()).getInitialization(); - } - return element; + }); } } |