From 8a4b15323aa005088e67c003f01dbbe6a6aba2cc Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Thu, 26 Jun 2014 18:03:04 +0200 Subject: [PATCH 1/3] another fix for IDEA-126598 Find in open files does not find occurrences in files outside of project --- .../psi/search/GlobalSearchScope.java | 23 ++++++++++++------- .../psi/search/GlobalSearchScopes.java | 18 +++------------ .../intellij/find/impl/FindInProjectTask.java | 4 ++++ 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.java b/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.java index fbb148a74de0..0b74f65ae63f 100644 --- a/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.java +++ b/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.java @@ -30,10 +30,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import java.util.*; public abstract class GlobalSearchScope extends SearchScope implements ProjectAwareFileFilter { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.search.GlobalSearchScope"); @@ -586,8 +583,8 @@ public abstract class GlobalSearchScope extends SearchScope implements ProjectAw public static final GlobalSearchScope EMPTY_SCOPE = new EmptyScope(); - private static class FileScope extends GlobalSearchScope { - private final VirtualFile myVirtualFile; + private static class FileScope extends GlobalSearchScope implements Iterable { + private final VirtualFile myVirtualFile; // files can be out of project roots private final Module myModule; private FileScope(@NotNull Project project, VirtualFile virtualFile) { @@ -620,10 +617,15 @@ public abstract class GlobalSearchScope extends SearchScope implements ProjectAw public String toString() { return "File :"+myVirtualFile; } + + @Override + public Iterator iterator() { + return Collections.singletonList(myVirtualFile).iterator(); + } } - public static class FilesScope extends GlobalSearchScope { - private final Collection myFiles; + public static class FilesScope extends GlobalSearchScope implements Iterable { + private final Collection myFiles; // files can be out of project roots public FilesScope(final Project project, @NotNull Collection files) { super(project); @@ -666,5 +668,10 @@ public abstract class GlobalSearchScope extends SearchScope implements ProjectAw List files = myFiles.size() <= 20 ? new ArrayList(myFiles) : new ArrayList(myFiles).subList(0,20); return "Files: ("+ files +")"; } + + @Override + public Iterator iterator() { + return myFiles.iterator(); + } } } diff --git a/platform/lang-api/src/com/intellij/psi/search/GlobalSearchScopes.java b/platform/lang-api/src/com/intellij/psi/search/GlobalSearchScopes.java index bbeb3e888492..3acfe338d499 100644 --- a/platform/lang-api/src/com/intellij/psi/search/GlobalSearchScopes.java +++ b/platform/lang-api/src/com/intellij/psi/search/GlobalSearchScopes.java @@ -18,13 +18,9 @@ package com.intellij.psi.search; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiManager; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.List; +import java.util.Arrays; /** * @author yole @@ -34,16 +30,8 @@ public class GlobalSearchScopes extends GlobalSearchScopesCore { } @NotNull - public static SearchScope openFilesScope(@NotNull Project project) { + public static GlobalSearchScope openFilesScope(@NotNull Project project) { final VirtualFile[] files = FileEditorManager.getInstance(project).getOpenFiles(); - // We can not use GlobalSearchScope as it is usually bound to project and used via filtering of project / library roots - // Open files can be out of project roots e.g. arbitrary open file so we go LocalSearchScope way, filling it with elements to process - List psiFiles = new ArrayList(files.length); - PsiManager psiManager = PsiManager.getInstance(project); - for(VirtualFile file:files) { - PsiFile psiFile = psiManager.findFile(file); - if (psiFile != null) psiFiles.add(psiFile); - } - return new LocalSearchScope(psiFiles.toArray(new PsiElement[psiFiles.size()]), "Open Files"); + return GlobalSearchScope.filesScope(project, Arrays.asList(files), "Open Files"); } } diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java index aa344c44be47..59adf1e62bd0 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java @@ -290,6 +290,10 @@ class FindInProjectTask { for (VirtualFile file : getLocalScopeFiles((LocalSearchScope)customScope)) { iterator.processFile(file); } + } else if (customScope instanceof Iterable) { // GlobalSearchScope can span files out of project roots e.g. FileScope / FilesScope + for (VirtualFile file : (Iterable)customScope) { + iterator.processFile(file); + } } else if (myPsiDirectory != null) { ApplicationManager.getApplication().runReadAction(new Runnable() { From a7fe9de63c5b16e7ad4a0d37bc8ab4368e0173e6 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 26 Jun 2014 16:17:59 +0400 Subject: [PATCH 2/3] increase responsiveness in remote debugging - lazy load stack frames one by one --- .../debugger/engine/JavaExecutionStack.java | 62 +++++++++++++------ .../ui/impl/watch/MethodsTracker.java | 10 ++- .../impl/watch/StackFrameDescriptorImpl.java | 6 +- 3 files changed, 55 insertions(+), 23 deletions(-) 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 2eb2ca8e78a8..d75175f6bd26 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java @@ -18,6 +18,8 @@ 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; import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.jdi.ThreadGroupReferenceProxyImpl; @@ -31,8 +33,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.ArrayList; -import java.util.List; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicInteger; /** * @author egor @@ -112,33 +115,24 @@ public class JavaExecutionStack extends XExecutionStack { @Override public void computeStackFrames(final int firstFrameIndex, final XStackFrameContainer container) { - myDebugProcess.getManagerThread().schedule(new DebuggerCommandImpl() { + final AtomicInteger skipCounter = new AtomicInteger(firstFrameIndex); + myDebugProcess.getManagerThread().schedule(new DebuggerContextCommandImpl(myDebugProcess.getDebuggerContext()) { @Override - protected void action() throws Exception { - boolean showLibraryStackframes = DebuggerSettings.getInstance().SHOW_LIBRARY_STACKFRAMES; + public void threadAction() { if (!myThreadProxy.isCollected() && myDebugProcess.getSuspendManager().isSuspended(myThreadProxy)) { - List frames = new ArrayList(); int status = myThreadProxy.status(); if (!(status == ThreadReference.THREAD_STATUS_UNKNOWN) && !(status == ThreadReference.THREAD_STATUS_NOT_STARTED) && !(status == ThreadReference.THREAD_STATUS_ZOMBIE)) { try { - int framesToSkip = firstFrameIndex; boolean first = true; for (StackFrameProxyImpl stackFrame : myThreadProxy.frames()) { - if (first && framesToSkip > 0) { - framesToSkip--; + if (first && firstFrameIndex > 0) { + skipCounter.decrementAndGet(); first = false; continue; } - JavaStackFrame frame = new JavaStackFrame(stackFrame, myDebugProcess, myTracker); - if (showLibraryStackframes || (!frame.getDescriptor().isSynthetic() && !frame.getDescriptor().isInLibraryContent())) { - if (framesToSkip > 0) { - framesToSkip--; - continue; - } - frames.add(frame); - } + myDebugProcess.getManagerThread().schedule(new AppendFrameCommand(getSuspendContext(), stackFrame, container, skipCounter)); } } catch (EvaluateException e) { @@ -146,7 +140,12 @@ public class JavaExecutionStack extends XExecutionStack { return; } } - container.addStackFrames(frames, true); + myDebugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(getSuspendContext()) { + @Override + public void contextAction() throws Exception { + container.addStackFrames(Collections.emptyList(), true); + } + }); } else { container.errorOccurred(DebuggerBundle.message("frame.panel.frames.not.available")); @@ -155,6 +154,33 @@ public class JavaExecutionStack extends XExecutionStack { }); } + private class AppendFrameCommand extends SuspendContextCommandImpl { + private final StackFrameProxyImpl myStackFrameProxy; + private final XStackFrameContainer myContainer; + private final AtomicInteger mySkipCounter; + + public AppendFrameCommand(SuspendContextImpl suspendContext, + StackFrameProxyImpl stackFrame, + XStackFrameContainer container, + AtomicInteger skipCounter) { + super(suspendContext); + myStackFrameProxy = stackFrame; + myContainer = container; + mySkipCounter = skipCounter; + } + + @Override + public void contextAction() throws Exception { + boolean showLibraryStackframes = DebuggerSettings.getInstance().SHOW_LIBRARY_STACKFRAMES; + JavaStackFrame frame = new JavaStackFrame(myStackFrameProxy, myDebugProcess, myTracker); + if (showLibraryStackframes || (!frame.getDescriptor().isSynthetic() && !frame.getDescriptor().isInLibraryContent())) { + if (mySkipCounter.getAndDecrement() <= 0) { + myContainer.addStackFrames(Arrays.asList(frame), false); + } + } + } + } + private static String calcRepresentation(ThreadReferenceProxyImpl thread) { DebuggerManagerThreadImpl.assertIsManagerThread(); String name = thread.name(); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/MethodsTracker.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/MethodsTracker.java index 8547e48d3a46..0662112bca6a 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/MethodsTracker.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/MethodsTracker.java @@ -26,6 +26,7 @@ import java.util.Map; */ public class MethodsTracker { private final Map myMethodToOccurrenceMap = new HashMap(); + private final Map myOccurences = new HashMap(); public final class MethodOccurrence { private final Method myMethod; @@ -49,8 +50,13 @@ public class MethodsTracker { } } - public MethodOccurrence getMethodOccurrence(Method method) { - return new MethodOccurrence(method, assignOccurrenceIndex(method)); + public MethodOccurrence getMethodOccurrence(int frameIndex, Method method) { + MethodOccurrence occurrence = myOccurences.get(frameIndex); + if (occurrence == null) { + occurrence = new MethodOccurrence(method, assignOccurrenceIndex(method)); + myOccurences.put(frameIndex, occurrence); + } + return occurrence; } private int getOccurrenceCount(Method method) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/StackFrameDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/StackFrameDescriptorImpl.java index 28062f09c3d0..ab0f579d170c 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/StackFrameDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/StackFrameDescriptorImpl.java @@ -68,7 +68,7 @@ public class StackFrameDescriptorImpl extends NodeDescriptorImpl implements Stac myUiIndex = frame.getFrameIndex(); myLocation = frame.location(); myThisObject = frame.thisObject(); - myMethodOccurrence = tracker.getMethodOccurrence(myLocation.method()); + myMethodOccurrence = tracker.getMethodOccurrence(myUiIndex, myLocation.method()); myIsSynthetic = DebuggerUtils.isSynthetic(myMethodOccurrence.getMethod()); ApplicationManager.getApplication().runReadAction(new Runnable() { @Override @@ -91,14 +91,14 @@ public class StackFrameDescriptorImpl extends NodeDescriptorImpl implements Stac catch (InternalException e) { LOG.info(e); myLocation = null; - myMethodOccurrence = tracker.getMethodOccurrence(null); + myMethodOccurrence = tracker.getMethodOccurrence(0, null); myIsSynthetic = false; myIsInLibraryContent = false; } catch (EvaluateException e) { LOG.info(e); myLocation = null; - myMethodOccurrence = tracker.getMethodOccurrence(null); + myMethodOccurrence = tracker.getMethodOccurrence(0, null); myIsSynthetic = false; myIsInLibraryContent = false; } From 5203032f4d027f9c7ec2366cddf98c19d93bcb4e Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 26 Jun 2014 19:09:34 +0400 Subject: [PATCH 3/3] increase responsiveness in remote debugging - increased priority for variables update --- .../debugger/engine/JavaExecutionStack.java | 10 +++ .../debugger/engine/JavaStackFrame.java | 5 ++ .../intellij/debugger/engine/JavaValue.java | 89 ++++++++++++------- 3 files changed, 73 insertions(+), 31 deletions(-) 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 d75175f6bd26..c5bbe0bded29 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java @@ -103,6 +103,11 @@ public class JavaExecutionStack extends XExecutionStack { } else { myDebugProcess.getManagerThread().invokeAndWait(new DebuggerCommandImpl() { + @Override + public Priority getPriority() { + return Priority.HIGH; + } + @Override protected void action() throws Exception { myTopFrame = calcTopFrame(); @@ -117,6 +122,11 @@ public class JavaExecutionStack extends XExecutionStack { public void computeStackFrames(final int firstFrameIndex, final XStackFrameContainer container) { final AtomicInteger skipCounter = new AtomicInteger(firstFrameIndex); myDebugProcess.getManagerThread().schedule(new DebuggerContextCommandImpl(myDebugProcess.getDebuggerContext()) { + @Override + public Priority getPriority() { + return Priority.NORMAL; + } + @Override public void threadAction() { if (!myThreadProxy.isCollected() && myDebugProcess.getSuspendManager().isSuspended(myThreadProxy)) { 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 316c49201e4c..5af05ebb1ec4 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java @@ -150,6 +150,11 @@ public class JavaStackFrame extends XStackFrame { return; } myDebugProcess.getManagerThread().schedule(new DebuggerContextCommandImpl(myDebugProcess.getDebuggerContext()) { + @Override + public Priority getPriority() { + return Priority.NORMAL; + } + @Override public void threadAction() { XValueChildrenList children = new XValueChildrenList(); 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 a06f831c0413..0a8c557a4e95 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java @@ -68,10 +68,6 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider { private static JavaValue create(JavaValue parent, @NotNull ValueDescriptorImpl valueDescriptor, EvaluationContextImpl evaluationContext, NodeManagerImpl nodeManager, boolean init) { DebuggerManagerThreadImpl.assertIsManagerThread(); - if (init) { - valueDescriptor.setContext(evaluationContext); - valueDescriptor.updateRepresentation(evaluationContext, DescriptorLabelListener.DUMMY_LISTENER); - } return new JavaValue(parent, valueDescriptor, evaluationContext, nodeManager); } @@ -98,42 +94,58 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider { public void computePresentation(@NotNull final XValueNode node, @NotNull XValuePlace place) { if (myEvaluationContext.getSuspendContext().isResumed()) return; myEvaluationContext.getDebugProcess().getManagerThread().schedule(new DebuggerContextCommandImpl(getDebuggerContext()) { + @Override + public Priority getPriority() { + return Priority.NORMAL; + } + @Override public void threadAction() { - Icon nodeIcon = DebuggerTreeRenderer.getValueIcon(myValueDescriptor); - final String[] strings = splitValue(myValueDescriptor.getValueLabel()); - final String value = StringUtil.notNullize(strings[1]); - String type = strings[0]; - XValuePresentation presentation; - if (myValueDescriptor.isString()) { - presentation = new TypedStringValuePresentation(StringUtil.unquoteString(value), type); - } - else if (myValueDescriptor.getLastRenderer() instanceof ToStringRenderer) { - presentation = new XRegularValuePresentation(StringUtil.wrapWithDoubleQuote(value), type); - } - else { - presentation = new XRegularValuePresentation(value, type); - } - if (value.length() > XValueNode.MAX_VALUE_LENGTH) { - node.setFullValueEvaluator(new XFullValueEvaluator() { - @Override - public void startEvaluation(@NotNull final XFullValueEvaluationCallback callback) { - myEvaluationContext.getDebugProcess().getManagerThread().schedule(new DebuggerContextCommandImpl(getDebuggerContext()) { + myValueDescriptor.setContext(myEvaluationContext); + myValueDescriptor.updateRepresentation(myEvaluationContext, new DescriptorLabelListener() { + @Override + public void labelChanged() { + Icon nodeIcon = DebuggerTreeRenderer.getValueIcon(myValueDescriptor); + final String[] strings = splitValue(myValueDescriptor.getValueLabel()); + final String value = StringUtil.notNullize(strings[1]); + String type = strings[0]; + XValuePresentation presentation; + if (myValueDescriptor.isString()) { + presentation = new TypedStringValuePresentation(StringUtil.unquoteString(value), type); + } + else if (myValueDescriptor.getLastRenderer() instanceof ToStringRenderer) { + presentation = new XRegularValuePresentation(StringUtil.wrapWithDoubleQuote(value), type); + } + else { + presentation = new XRegularValuePresentation(value, type); + } + if (value.length() > XValueNode.MAX_VALUE_LENGTH) { + node.setFullValueEvaluator(new XFullValueEvaluator() { @Override - public void threadAction() { - final String valueAsString = DebuggerUtilsEx.getValueOrErrorAsString(myEvaluationContext, myValueDescriptor.getValue()); - DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() { + public void startEvaluation(@NotNull final XFullValueEvaluationCallback callback) { + myEvaluationContext.getDebugProcess().getManagerThread().schedule(new DebuggerContextCommandImpl(getDebuggerContext()) { @Override - public void run() { - callback.evaluated(valueAsString); + public Priority getPriority() { + return Priority.NORMAL; + } + + @Override + public void threadAction() { + final String valueAsString = DebuggerUtilsEx.getValueOrErrorAsString(myEvaluationContext, myValueDescriptor.getValue()); + DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() { + @Override + public void run() { + callback.evaluated(valueAsString); + } + }); } }); } }); } - }); - } - node.setPresentation(nodeIcon, presentation, myValueDescriptor.isExpandable()); + node.setPresentation(nodeIcon, presentation, myValueDescriptor.isExpandable()); + } + }); } }); } @@ -173,6 +185,11 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider { public void computeChildren(@NotNull final XCompositeNode node) { if (myEvaluationContext.getSuspendContext().isResumed()) return; myEvaluationContext.getDebugProcess().getManagerThread().schedule(new SuspendContextCommandImpl(myEvaluationContext.getSuspendContext()) { + @Override + public Priority getPriority() { + return Priority.NORMAL; + } + @Override public void contextAction() throws Exception { final XValueChildrenList children = new XValueChildrenList(); @@ -278,6 +295,11 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider { if (myEvaluationContext.getSuspendContext().isResumed()) return; DebugProcessImpl debugProcess = myEvaluationContext.getDebugProcess(); debugProcess.getManagerThread().schedule(new JumpToObjectAction.NavigateCommand(getDebuggerContext(), myValueDescriptor, debugProcess, null) { + @Override + public Priority getPriority() { + return Priority.HIGH; + } + @Override protected void doAction(@Nullable final SourcePosition sourcePosition) { if (sourcePosition != null) { @@ -307,6 +329,11 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider { // TODO: change API to allow to calculate it asynchronously DebugProcessImpl debugProcess = myEvaluationContext.getDebugProcess(); debugProcess.getManagerThread().invokeAndWait(new DebuggerCommandImpl() { + @Override + public Priority getPriority() { + return Priority.HIGH; + } + @Override protected void action() throws Exception { evaluationExpression = ApplicationManager.getApplication().runReadAction(new Computable() {