summaryrefslogtreecommitdiff
path: root/java/debugger
diff options
context:
space:
mode:
Diffstat (limited to 'java/debugger')
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/actions/AdjustArrayRangeAction.java41
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/actions/CustomizeThreadsViewAction.java16
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/actions/JavaReferringObjectsValue.java172
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/actions/ShowReferringObjectsAction.java131
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/actions/ToggleMethodBreakpointAction.java3
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java10
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java39
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java2
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java43
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java4
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java40
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java55
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/HotSwapProgressImpl.java2
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java2
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/CompilingEvaluator.java217
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/EvaluationDescriptor.java23
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/FieldDescriptorImpl.java15
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/LocalVariableDescriptorImpl.java12
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java1
-rw-r--r--java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java82
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;
+ });
}
}