From c1aa64896539e8479a5ccf34cbbd35d029df5419 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Thu, 18 Jul 2013 15:56:05 +0400 Subject: [PATCH] IDEA-91585 IDEA-57990 resolve inside Android SDK based on its sources, not classes --- .../intellij/psi/NonClasspathClassFinder.java | 3 +- .../impl/file/impl/JavaFileManagerBase.java | 2 +- .../impl/search/JavaSourceFilterScope.java | 26 +++++++++- .../com/intellij/psi/PsiElementFinder.java | 11 +++- .../intellij/psi/impl/JavaPsiFacadeImpl.java | 36 ++++++++----- .../psi/impl/file/PsiPackageImpl.java | 52 ++++++++++++++----- .../psi/search/GlobalSearchScope.java | 4 ++ .../psi/impl/file/PsiPackageBase.java | 9 +++- .../intellij/psi/stubs/StubTreeBuilder.java | 2 +- .../intellij/psi/SdkResolveScopeProvider.java | 19 +++++++ .../module/impl/scopes/LibraryScopeBase.java | 4 +- .../openapi/roots/impl/LibraryScopeCache.java | 19 +++++-- .../src/META-INF/LangExtensionPoints.xml | 2 + 13 files changed, 150 insertions(+), 39 deletions(-) create mode 100644 platform/indexing-api/src/com/intellij/psi/SdkResolveScopeProvider.java diff --git a/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java b/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java index 17d937611b17..af890621d62f 100644 --- a/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java +++ b/java/java-impl/src/com/intellij/psi/NonClasspathClassFinder.java @@ -178,7 +178,8 @@ public abstract class NonClasspathClassFinder extends PsiElementFinder { @Override public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope, - @NotNull Processor consumer) { + @NotNull Processor consumer, + boolean includeLibrarySources) { final List classRoots = getClassRoots(); if (classRoots.isEmpty()) { return true; diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java b/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java index af186c8bca67..dc0d372eac2a 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java @@ -121,7 +121,7 @@ public abstract class JavaFileManagerBase implements JavaFileManager, Disposable @Override @Nullable public PsiPackage findPackage(@NotNull String packageName) { - Query dirs = myPackageIndex.getDirsByPackageName(packageName, false); + Query dirs = myPackageIndex.getDirsByPackageName(packageName, true); if (dirs.findFirst() == null) return null; return new PsiPackageImpl(myManager, packageName); } diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java index 086a20eabcf7..13229d1aa67a 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java @@ -20,9 +20,13 @@ package com.intellij.psi.impl.search; import com.intellij.ide.highlighter.JavaClassFileType; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.JdkOrderEntry; +import com.intellij.openapi.roots.OrderEntry; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.SdkResolveScopeProvider; import com.intellij.psi.search.DelegatingGlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.NotNull; @@ -45,7 +49,27 @@ public class JavaSourceFilterScope extends DelegatingGlobalSearchScope { return myIndex.isInLibraryClasses(file); } - return myIndex.isInSourceContent(file); + if (myIndex.isInSourceContent(file)) { + return true; + } + final Project project = getProject(); + + if (project != null) { + for (OrderEntry entry : myIndex.getOrderEntriesForFile(file)) { + if (entry instanceof JdkOrderEntry) { + final JdkOrderEntry jdkOrderEntry = (JdkOrderEntry)entry; + + for (SdkResolveScopeProvider provider : SdkResolveScopeProvider.EP_NAME.getExtensions()) { + final GlobalSearchScope scope = provider.getScope(project, jdkOrderEntry); + + if (scope != null && scope.contains(file)) { + return true; + } + } + } + } + } + return false; } } \ No newline at end of file diff --git a/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java b/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java index 41bb666bf429..8ae3ca80e175 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java @@ -120,7 +120,16 @@ public abstract class PsiElementFinder { return names; } - public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope, @NotNull Processor consumer) { + public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, + @NotNull GlobalSearchScope scope, + @NotNull Processor consumer) { + return processPackageDirectories(psiPackage, scope, consumer, false); + } + + public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, + @NotNull GlobalSearchScope scope, + @NotNull Processor consumer, + boolean includeLibrarySources) { return true; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java index 2bde13a67ae5..b805ef4cf8f0 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java @@ -34,6 +34,7 @@ import com.intellij.psi.impl.source.JavaDummyHolderFactory; import com.intellij.psi.impl.source.resolve.FileContextUtil; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.stubs.StubTreeLoader; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.util.PsiUtilCore; import com.intellij.reference.SoftReference; @@ -249,9 +250,12 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { return result == null ? PsiClass.EMPTY_ARRAY : result.toArray(new PsiClass[result.size()]); } - public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope, @NotNull Processor consumer) { + public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, + @NotNull GlobalSearchScope scope, + @NotNull Processor consumer, + boolean includeLibrarySources) { for (PsiElementFinder finder : filteredFinders()) { - if (!finder.processPackageDirectories(psiPackage, scope, consumer)) { + if (!finder.processPackageDirectories(psiPackage, scope, consumer, includeLibrarySources)) { return false; } } @@ -371,7 +375,11 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { for (PsiFile file : dir.getFiles()) { if (file instanceof PsiClassOwner && file.getViewProvider().getLanguages().size() == 1) { VirtualFile vFile = file.getVirtualFile(); - if (vFile != null && !facade.isInSourceContent(vFile) && !(file instanceof PsiCompiledElement)) { + if (vFile != null && + !(file instanceof PsiCompiledElement) && + !facade.isInSourceContent(vFile) && + (!scope.isForceSearchingInLibrarySources() || + !StubTreeLoader.getInstance().canHaveStub(vFile))) { continue; } @@ -388,16 +396,20 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { } @Override - public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, @NotNull final GlobalSearchScope scope, @NotNull final Processor consumer) { + public boolean processPackageDirectories(@NotNull PsiPackage psiPackage, + @NotNull final GlobalSearchScope scope, + @NotNull final Processor consumer, + boolean includeLibrarySources) { final PsiManager psiManager = PsiManager.getInstance(getProject()); - return PackageIndex.getInstance(getProject()).getDirsByPackageName(psiPackage.getQualifiedName(), false).forEach(new ReadActionProcessor() { - @Override - public boolean processInReadAction(final VirtualFile dir) { - if (!scope.contains(dir)) return true; - PsiDirectory psiDir = psiManager.findDirectory(dir); - return psiDir == null || consumer.process(psiDir); - } - }); + return PackageIndex.getInstance(getProject()).getDirsByPackageName(psiPackage.getQualifiedName(), includeLibrarySources) + .forEach(new ReadActionProcessor() { + @Override + public boolean processInReadAction(final VirtualFile dir) { + if (!scope.contains(dir)) return true; + PsiDirectory psiDir = psiManager.findDirectory(dir); + return psiDir == null || consumer.process(psiDir); + } + }); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java index 20ab20211c95..d023667ef063 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java @@ -29,6 +29,7 @@ import com.intellij.psi.impl.source.tree.java.PsiCompositeModifierList; import com.intellij.psi.scope.ElementClassHint; import com.intellij.psi.scope.NameHint; import com.intellij.psi.scope.PsiScopeProcessor; +import com.intellij.psi.search.DelegatingGlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.*; import com.intellij.reference.SoftReference; @@ -47,6 +48,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya public static boolean DEBUG = false; private volatile CachedValue myAnnotationList; private volatile CachedValue> myDirectories; + private volatile CachedValue> myDirectoriesWithLibSources; private volatile SoftReference> myPublicClassNamesCache; public PsiPackageImpl(PsiManager manager, String qualifiedName) { @@ -54,19 +56,31 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya } @Override - protected Collection getAllDirectories() { - if (myDirectories == null) { - myDirectories = CachedValuesManager.getManager(myManager.getProject()).createCachedValue(new CachedValueProvider>() { - @Override - public Result> compute() { - final CommonProcessors.CollectProcessor processor = new CommonProcessors.CollectProcessor(); - getFacade().processPackageDirectories(PsiPackageImpl.this, allScope(), processor); - return Result.create(processor.getResults(), PsiPackageImplementationHelper.getInstance().getDirectoryCachedValueDependencies( - PsiPackageImpl.this)); - } - }, false); + protected Collection getAllDirectories(boolean includeLibrarySources) { + if (includeLibrarySources) { + if (myDirectoriesWithLibSources == null) { + myDirectoriesWithLibSources = createCachedDirectories(true); + } + return myDirectoriesWithLibSources.getValue(); } - return myDirectories.getValue(); + else { + if (myDirectories == null) { + myDirectories = createCachedDirectories(false); + } + return myDirectories.getValue(); + } + } + + private CachedValue> createCachedDirectories(final boolean includeLibrarySources) { + return CachedValuesManager.getManager(myManager.getProject()).createCachedValue(new CachedValueProvider>() { + @Override + public Result> compute() { + final CommonProcessors.CollectProcessor processor = new CommonProcessors.CollectProcessor(); + getFacade().processPackageDirectories(PsiPackageImpl.this, allScope(), processor, includeLibrarySources); + return Result.create(processor.getResults(), PsiPackageImplementationHelper.getInstance().getDirectoryCachedValueDependencies( + PsiPackageImpl.this)); + } + }, false); } @Override @@ -103,7 +117,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya @Override public boolean isValid() { - return PsiPackageImplementationHelper.getInstance().packagePrefixExists(this) || !getAllDirectories().isEmpty(); + return PsiPackageImplementationHelper.getInstance().packagePrefixExists(this) || !getAllDirectories(true).isEmpty(); } @Override @@ -165,7 +179,17 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya SoftReference> ref = myPublicClassNamesCache; Set cache = ref == null ? null : ref.get(); if (cache == null) { - cache = getFacade().getClassNames(this, allScope()); + GlobalSearchScope scope = allScope(); + + if (!scope.isForceSearchingInLibrarySources()) { + scope = new DelegatingGlobalSearchScope(scope) { + @Override + public boolean isForceSearchingInLibrarySources() { + return true; + } + }; + } + cache = getFacade().getClassNames(this, scope); myPublicClassNamesCache = new SoftReference>(cache); } 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 6670be3590e2..cfcf64dde6e9 100644 --- a/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.java +++ b/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.java @@ -79,6 +79,10 @@ public abstract class GlobalSearchScope extends SearchScope implements ProjectAw public abstract boolean isSearchInLibraries(); + public boolean isForceSearchingInLibrarySources() { + return false; + } + public boolean isSearchOutsideRootModel() { return false; } diff --git a/platform/core-impl/src/com/intellij/psi/impl/file/PsiPackageBase.java b/platform/core-impl/src/com/intellij/psi/impl/file/PsiPackageBase.java index 57d40a81fd00..9a1f7b69c09b 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/file/PsiPackageBase.java +++ b/platform/core-impl/src/com/intellij/psi/impl/file/PsiPackageBase.java @@ -44,7 +44,11 @@ public abstract class PsiPackageBase extends PsiElementBase implements PsiDirect final PsiManager myManager; private final String myQualifiedName; - protected abstract Collection getAllDirectories(); + protected Collection getAllDirectories() { + return getAllDirectories(false); + } + + protected abstract Collection getAllDirectories(boolean includeLibrarySources); protected abstract PsiElement findPackage(String qName); @@ -81,7 +85,8 @@ public abstract class PsiPackageBase extends PsiElementBase implements PsiDirect @NotNull public PsiDirectory[] getDirectories(@NotNull GlobalSearchScope scope) { List result = null; - final Collection directories = getAllDirectories(); + final boolean includeLibrarySources = scope.isForceSearchingInLibrarySources(); + final Collection directories = getAllDirectories(includeLibrarySources); for (final PsiDirectory directory : directories) { if (scope.contains(directory.getVirtualFile())) { if (result == null) result = new ArrayList(); diff --git a/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java b/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java index 85b75941c8ce..c5ff361a3c3d 100644 --- a/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java +++ b/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java @@ -50,7 +50,7 @@ public class StubTreeBuilder { if (builder != null) { data = builder.buildStubTree(inputData); } - else if (!fileType.isBinary()) { + if (data == null && !fileType.isBinary()) { final LanguageFileType languageFileType = (LanguageFileType)fileType; Language l = languageFileType.getLanguage(); final IFileElementType type = LanguageParserDefinitions.INSTANCE.forLanguage(l).getFileNodeType(); diff --git a/platform/indexing-api/src/com/intellij/psi/SdkResolveScopeProvider.java b/platform/indexing-api/src/com/intellij/psi/SdkResolveScopeProvider.java new file mode 100644 index 000000000000..c4e25248ca0f --- /dev/null +++ b/platform/indexing-api/src/com/intellij/psi/SdkResolveScopeProvider.java @@ -0,0 +1,19 @@ +package com.intellij.psi; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.JdkOrderEntry; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Eugene.Kudelevsky + */ +public abstract class SdkResolveScopeProvider { + public static final ExtensionPointName EP_NAME = + ExtensionPointName.create("com.intellij.sdkResolveScopeProvider"); + + @Nullable + public abstract GlobalSearchScope getScope(@NotNull Project project, @NotNull JdkOrderEntry entry); +} diff --git a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/LibraryScopeBase.java b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/LibraryScopeBase.java index 60563fe7a4d3..a7cfd086c989 100644 --- a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/LibraryScopeBase.java +++ b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/LibraryScopeBase.java @@ -33,7 +33,7 @@ import java.util.LinkedHashSet; */ public abstract class LibraryScopeBase extends GlobalSearchScope { private final LinkedHashSet myEntries; - private final ProjectFileIndex myIndex; + protected final ProjectFileIndex myIndex; public LibraryScopeBase(Project project, VirtualFile[] classes, VirtualFile[] sources) { super(project); @@ -48,7 +48,7 @@ public abstract class LibraryScopeBase extends GlobalSearchScope { } @Nullable - private VirtualFile getFileRoot(VirtualFile file) { + protected VirtualFile getFileRoot(VirtualFile file) { if (myIndex.isInLibraryClasses(file)) { return myIndex.getClassRootForFile(file); } diff --git a/platform/indexing-impl/src/com/intellij/openapi/roots/impl/LibraryScopeCache.java b/platform/indexing-impl/src/com/intellij/openapi/roots/impl/LibraryScopeCache.java index 1aad284ced03..88aac30ff3ea 100644 --- a/platform/indexing-impl/src/com/intellij/openapi/roots/impl/LibraryScopeCache.java +++ b/platform/indexing-impl/src/com/intellij/openapi/roots/impl/LibraryScopeCache.java @@ -22,6 +22,7 @@ import com.intellij.openapi.module.impl.scopes.LibraryRuntimeClasspathScope; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.JdkOrderEntry; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.SdkResolveScopeProvider; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.containers.ConcurrentHashMap; @@ -63,11 +64,21 @@ public class LibraryScopeCache { } public GlobalSearchScope getScopeForSdk(final JdkOrderEntry jdkOrderEntry) { - final String jdk = jdkOrderEntry.getJdkName(); - if (jdk == null) return GlobalSearchScope.allScope(myProject); - GlobalSearchScope scope = mySdkScopes.get(jdk); + final String jdkName = jdkOrderEntry.getJdkName(); + if (jdkName == null) return GlobalSearchScope.allScope(myProject); + GlobalSearchScope scope = mySdkScopes.get(jdkName); if (scope == null) { - return ConcurrencyUtil.cacheOrGet(mySdkScopes, jdk, new JdkScope(myProject, jdkOrderEntry)); + for (SdkResolveScopeProvider provider : SdkResolveScopeProvider.EP_NAME.getExtensions()) { + scope = provider.getScope(myProject, jdkOrderEntry); + + if (scope != null) { + break; + } + } + if (scope == null) { + scope = new JdkScope(myProject, jdkOrderEntry); + } + return ConcurrencyUtil.cacheOrGet(mySdkScopes, jdkName, scope); } return scope; } diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 56bd62e37d06..d304430b27c7 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -785,6 +785,8 @@ + +