From f3d13a09b2e895b389a03b2b588c3b59238b3b8f Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Tue, 10 Mar 2020 11:43:55 +0300 Subject: [PATCH] IDEA-234690 Batch receive object's children - array elements GitOrigin-RevId: 38cf5c7f8e2a7ce276c6f95c72b4f39245345b30 --- .../watch/ArrayElementDescriptorImpl.java | 13 +- .../ui/tree/render/ArrayRenderer.java | 163 ++++++++++-------- 2 files changed, 103 insertions(+), 73 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArrayElementDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArrayElementDescriptorImpl.java index 5138b4dd3fb5..a8836a5ce668 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArrayElementDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArrayElementDescriptorImpl.java @@ -1,9 +1,9 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.ui.impl.watch; -import com.intellij.debugger.JavaDebuggerBundle; import com.intellij.debugger.DebuggerContext; import com.intellij.debugger.DebuggerManagerEx; +import com.intellij.debugger.JavaDebuggerBundle; import com.intellij.debugger.engine.JavaValue; import com.intellij.debugger.engine.JavaValueModifier; import com.intellij.debugger.engine.evaluation.EvaluateException; @@ -14,6 +14,7 @@ import com.intellij.debugger.jdi.VirtualMachineProxyImpl; import com.intellij.debugger.ui.tree.ArrayElementDescriptor; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Ref; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiElementFactory; import com.intellij.psi.PsiExpression; @@ -26,6 +27,7 @@ import org.jetbrains.annotations.NotNull; public class ArrayElementDescriptorImpl extends ValueDescriptorImpl implements ArrayElementDescriptor{ private final int myIndex; private final ArrayReference myArray; + private Ref myPresetValue; public ArrayElementDescriptorImpl(Project project, ArrayReference array, int index) { super(project); @@ -49,8 +51,15 @@ public class ArrayElementDescriptorImpl extends ValueDescriptorImpl implements A return String.valueOf(myIndex); } + public void setValue(Value value) { + myPresetValue = Ref.create(value); + } + @Override public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException { + if (myPresetValue != null) { + return myPresetValue.get(); + } return getArrayElement(myArray, myIndex); } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java index 3d7ce13e4f72..0152a8f732ae 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java @@ -1,9 +1,9 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.ui.tree.render; -import com.intellij.debugger.JavaDebuggerBundle; import com.intellij.debugger.DebuggerContext; import com.intellij.debugger.DebuggerManagerEx; +import com.intellij.debugger.JavaDebuggerBundle; import com.intellij.debugger.actions.ArrayAction; import com.intellij.debugger.engine.ContextUtil; import com.intellij.debugger.engine.DebuggerManagerThreadImpl; @@ -18,7 +18,6 @@ import com.intellij.debugger.settings.NodeRendererSettings; import com.intellij.debugger.settings.ViewsGeneralSettings; import com.intellij.debugger.ui.impl.watch.ArrayElementDescriptorImpl; import com.intellij.debugger.ui.impl.watch.NodeManagerImpl; -import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; import com.intellij.debugger.ui.tree.DebuggerTreeNode; import com.intellij.debugger.ui.tree.NodeDescriptor; import com.intellij.debugger.ui.tree.NodeDescriptorFactory; @@ -42,10 +41,7 @@ import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; import com.intellij.xdebugger.frame.XValueChildrenList; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; -import com.sun.jdi.ArrayReference; -import com.sun.jdi.ArrayType; -import com.sun.jdi.Type; -import com.sun.jdi.Value; +import com.sun.jdi.*; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -53,6 +49,7 @@ import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import java.awt.event.MouseEvent; import java.util.Collections; +import java.util.List; public class ArrayRenderer extends NodeRendererImpl{ private static final Logger LOG = Logger.getInstance(ArrayRenderer.class); @@ -115,56 +112,77 @@ public class ArrayRenderer extends NodeRendererImpl{ ENTRIES_LIMIT = 1; } - int added = 0; - boolean hiddenNulls = false; - int end = Math.min(arrayLength - 1, END_INDEX); - int idx = START_INDEX; - if (arrayLength > START_INDEX) { - for (; idx <= end; idx++) { - if (ViewsGeneralSettings.getInstance().HIDE_NULL_ARRAY_ELEMENTS && elementIsNull(array, idx)) { - hiddenNulls = true; - continue; - } + try { + int added = 0; + boolean hiddenNulls = false; + int end = Math.min(arrayLength - 1, END_INDEX); + int idx = START_INDEX; + if (arrayLength > START_INDEX) { + ArrayValuesCache arrayValuesCache = new ArrayValuesCache(array); + for (; idx <= end; idx++) { + Value val = arrayValuesCache.getValue(idx); + if (ViewsGeneralSettings.getInstance().HIDE_NULL_ARRAY_ELEMENTS && val == null) { + hiddenNulls = true; + continue; + } - DebuggerTreeNode arrayItemNode = - nodeManager.createNode(descriptorFactory.getArrayItemDescriptor(builder.getParentDescriptor(), array, idx), evaluationContext); + ArrayElementDescriptorImpl descriptor = + (ArrayElementDescriptorImpl)descriptorFactory.getArrayItemDescriptor(builder.getParentDescriptor(), array, idx); + descriptor.setValue(val); + DebuggerTreeNode arrayItemNode = nodeManager.createNode(descriptor, evaluationContext); - builder.addChildren(Collections.singletonList(arrayItemNode), false); - added++; - if (added >= ENTRIES_LIMIT) { - break; + builder.addChildren(Collections.singletonList(arrayItemNode), false); + added++; + if (added >= ENTRIES_LIMIT) { + break; + } } } - } - builder.addChildren(Collections.emptyList(), true); + builder.addChildren(Collections.emptyList(), true); - if (added == 0) { - if (START_INDEX == 0 && arrayLength - 1 <= END_INDEX) { - builder.setMessage(JavaDebuggerBundle.message("message.node.all.elements.null"), null, SimpleTextAttributes.REGULAR_ATTRIBUTES, null); + if (added == 0) { + if (START_INDEX == 0 && arrayLength - 1 <= END_INDEX) { + builder.setMessage(JavaDebuggerBundle.message("message.node.all.elements.null"), null, SimpleTextAttributes.REGULAR_ATTRIBUTES, + null); + } + else { + builder.setMessage(JavaDebuggerBundle.message("message.node.all.array.elements.null", START_INDEX, END_INDEX), null, + SimpleTextAttributes.REGULAR_ATTRIBUTES, null); + } } else { - builder.setMessage(JavaDebuggerBundle.message("message.node.all.array.elements.null", START_INDEX, END_INDEX), null, - SimpleTextAttributes.REGULAR_ATTRIBUTES, null); + if (hiddenNulls) { + builder + .setMessage(JavaDebuggerBundle.message("message.node.elements.null.hidden"), null, SimpleTextAttributes.REGULAR_ATTRIBUTES, + null); + } + if (!myForced && idx < end) { + builder.tooManyChildren(end - idx); + } } } - else { - if (hiddenNulls) { - builder.setMessage(JavaDebuggerBundle.message("message.node.elements.null.hidden"), null, SimpleTextAttributes.REGULAR_ATTRIBUTES, null); - } - if (!myForced && idx < end) { - builder.tooManyChildren(end - idx); - } + catch (ObjectCollectedException e) { + builder.setErrorMessage(JavaDebuggerBundle.message("evaluation.error.array.collected")); } } } - private static boolean elementIsNull(ArrayReference arrayReference, int index) { - try { - return ArrayElementDescriptorImpl.getArrayElement(arrayReference, index) == null; + private static class ArrayValuesCache { + private final ArrayReference myArray; + private List myCachedValues = Collections.emptyList(); + private int myCachedStartIndex; + + private ArrayValuesCache(ArrayReference array) { + myArray = array; } - catch (EvaluateException e) { - return false; + + Value getValue(int index) { + if (index < myCachedStartIndex || index >= myCachedStartIndex + myCachedValues.size()) { + myCachedStartIndex = index; + myCachedValues = myArray.getValues(index, Math.min(XCompositeNode.MAX_CHILDREN_TO_SHOW, myArray.length() - index)); + } + return myCachedValues.get(index - myCachedStartIndex); } } @@ -250,42 +268,45 @@ public class ArrayRenderer extends NodeRendererImpl{ }; cachedEvaluator.setReferenceExpression(TextWithImportsImpl.fromXExpression(myExpression)); - int added = 0; - if (arrayLength - 1 >= START_INDEX) { - ErrorsValueGroup errorsGroup = null; - for (int idx = START_INDEX; idx < arrayLength; idx++) { - try { - if (DebuggerUtilsEx.evaluateBoolean(cachedEvaluator.getEvaluator(evaluationContext.getProject()), - (EvaluationContextImpl)evaluationContext.createEvaluationContext(array.getValue(idx)))) { + try { + int added = 0; + if (arrayLength - 1 >= START_INDEX) { - DebuggerTreeNode arrayItemNode = - nodeManager - .createNode(descriptorFactory.getArrayItemDescriptor(builder.getParentDescriptor(), array, idx), evaluationContext); + ErrorsValueGroup errorsGroup = null; + ArrayValuesCache arrayValuesCache = new ArrayValuesCache(array); + for (int idx = START_INDEX; idx < arrayLength; idx++) { + ArrayElementDescriptorImpl descriptor = + (ArrayElementDescriptorImpl)descriptorFactory.getArrayItemDescriptor(builder.getParentDescriptor(), array, idx); + Value val = arrayValuesCache.getValue(idx); + descriptor.setValue(val); + try { + if (DebuggerUtilsEx.evaluateBoolean(cachedEvaluator.getEvaluator(evaluationContext.getProject()), + (EvaluationContextImpl)evaluationContext.createEvaluationContext(val))) { - builder.addChildren(Collections.singletonList(arrayItemNode), false); - added++; - //if (added > ENTRIES_LIMIT) { - // break; - //} + DebuggerTreeNode arrayItemNode = nodeManager.createNode(descriptor, evaluationContext); + builder.addChildren(Collections.singletonList(arrayItemNode), false); + added++; + //if (added > ENTRIES_LIMIT) { + // break; + //} + } } - } - catch (EvaluateException e) { - if (errorsGroup == null) { - errorsGroup = new ErrorsValueGroup(); - builder.addChildren(XValueChildrenList.bottomGroup(errorsGroup), false); + catch (EvaluateException e) { + if (errorsGroup == null) { + errorsGroup = new ErrorsValueGroup(); + builder.addChildren(XValueChildrenList.bottomGroup(errorsGroup), false); + } + JavaValue childValue = JavaValue.create(null, descriptor, ((EvaluationContextImpl)evaluationContext), nodeManager, false); + errorsGroup.addErrorValue(e.getMessage(), childValue); } - JavaValue childValue = JavaValue - .create(null, - (ValueDescriptorImpl)descriptorFactory.getArrayItemDescriptor(builder.getParentDescriptor(), array, idx), - ((EvaluationContextImpl)evaluationContext), - nodeManager, - false); - errorsGroup.addErrorValue(e.getMessage(), childValue); } } - } - builder.addChildren(Collections.emptyList(), true); + builder.addChildren(Collections.emptyList(), true); + } + catch (ObjectCollectedException e) { + builder.setErrorMessage(JavaDebuggerBundle.message("evaluation.error.array.collected")); + } //if (added != 0 && END_INDEX < arrayLength - 1) { // builder.setRemaining(arrayLength - 1 - END_INDEX);