From 123c23f7f392d9abd9a4cb88a7deebd7539a9cdf Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Mon, 26 Oct 2015 20:32:42 +0300 Subject: [PATCH] FilesScope should be smart enough to make a decision about searching in libraries --- .../com/intellij/find/FindManagerTest.java | 2 +- .../psi/search/GlobalSearchScope.java | 54 +++++++++++++++++-- .../PredefinedSearchScopeProviderImpl.java | 10 +--- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java index 81d80fa3fcbc..9f1d9b69c410 100644 --- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java +++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java @@ -306,7 +306,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { findModel.setGlobal(true); findModel.setMultipleFiles(true); findModel.setCustomScope(true); - findModel.setCustomScope(new GlobalSearchScope.FilesScope(myProject, ContainerUtil.list(nonProjectFile))); + findModel.setCustomScope(GlobalSearchScope.filesScope(myProject, ContainerUtil.list(nonProjectFile))); assertSize(1, findUsages(findModel)); } 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 64f4da0c8a2e..197c772a5239 100644 --- a/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.java +++ b/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.java @@ -310,11 +310,33 @@ public abstract class GlobalSearchScope extends SearchScope implements ProjectAw }; } + + /** + * Please consider using this#filesWithLibrariesScope or this#filesWithoutLibrariesScope for optimization + */ @NotNull public static GlobalSearchScope filesScope(@NotNull Project project, @NotNull Collection files) { return filesScope(project, files, null); } + /** + * Optimization. By default FilesScope makes a decision about searching in libraries by checking that + * at least one file is placed out of module roots. So if you're sure about files placement you can explicitly say FilesScope whether + * it should include libraries or not in order to avoid checking each file. + * Also, if you have a lot of files it might be faster to always search in libraries. + */ + @NotNull + public static GlobalSearchScope filesWithoutLibrariesScope(@NotNull Project project, @NotNull Collection files) { + if (files.isEmpty()) return EMPTY_SCOPE; + return new FilesScope(project, files, false); + } + + @NotNull + public static GlobalSearchScope filesWithLibrariesScope(@NotNull Project project, @NotNull Collection files) { + if (files.isEmpty()) return EMPTY_SCOPE; + return new FilesScope(project, files, true); + } + @NotNull public static GlobalSearchScope filesScope(@NotNull Project project, @NotNull Collection files, @Nullable final String displayName) { if (files.isEmpty()) return EMPTY_SCOPE; @@ -721,11 +743,18 @@ public abstract class GlobalSearchScope extends SearchScope implements ProjectAw } public static class FilesScope extends GlobalSearchScope implements Iterable { - private final Collection myFiles; // files can be out of project roots + private final Collection myFiles; + private Boolean myHasFilesOutOfProjectRoots; - public FilesScope(final Project project, @NotNull Collection files) { + public FilesScope(@Nullable Project project, @NotNull Collection files) { + this(project, files, null); + } + + // Optimization + private FilesScope(@Nullable Project project, @NotNull Collection files, @Nullable Boolean hasFilesOutOfProjectRoots) { super(project); myFiles = files; + myHasFilesOutOfProjectRoots = hasFilesOutOfProjectRoots; } @Override @@ -745,7 +774,7 @@ public abstract class GlobalSearchScope extends SearchScope implements ProjectAw @Override public boolean isSearchInLibraries() { - return false; + return hasFilesOutOfProjectRoots(); } @Override @@ -757,11 +786,28 @@ public abstract class GlobalSearchScope extends SearchScope implements ProjectAw public int hashCode() { return myFiles.hashCode(); } + + private boolean hasFilesOutOfProjectRoots() { + if (myHasFilesOutOfProjectRoots == null) { + long i = System.currentTimeMillis(); + myHasFilesOutOfProjectRoots = false; + Project project = getProject(); + if (project != null && !project.isDefault()) { + for (VirtualFile file : myFiles) { + if (FileIndexFacade.getInstance(project).getModuleForFile(file) == null) { + myHasFilesOutOfProjectRoots = true; + break; + } + } + } + } + return myHasFilesOutOfProjectRoots; + } @Override public String toString() { List files = myFiles.size() <= 20 ? new ArrayList(myFiles) : new ArrayList(myFiles).subList(0,20); - return "Files: ("+ files +")"; + return "Files: ("+ files +"); search in libraries: " + (myHasFilesOutOfProjectRoots != null ? myHasFilesOutOfProjectRoots : "unknown"); } @Override diff --git a/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java b/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java index 8d2f71bf58b2..14912d1e409c 100644 --- a/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -250,13 +250,7 @@ public class PredefinedSearchScopeProviderImpl extends PredefinedSearchScopeProv } }); if (!selectedFiles.isEmpty()) { - return new DelegatingGlobalSearchScope(GlobalSearchScope.filesScope(project, selectedFiles)) { - @NotNull - @Override - public String getDisplayName() { - return "Selected Files"; - } - }; + return GlobalSearchScope.filesScope(project, selectedFiles, "Selected Files"); } } return null;