From 50c640a69698c3ed6df5895ffcf4c09b5de9f2d7 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 3 Oct 2011 19:17:30 +0200 Subject: [PATCH] extract handling of package prefixes to a separate PsiElementFinder --- .../intellij/psi/impl/JavaPsiFacadeImpl.java | 40 +------ .../psi/impl/PackagePrefixElementFinder.java | 102 ++++++++++++++++++ .../psi/impl/file/PsiPackageImpl.java | 3 +- resources/src/META-INF/IdeaPlugin.xml | 2 + 4 files changed, 111 insertions(+), 36 deletions(-) create mode 100644 java/java-impl/src/com/intellij/psi/impl/PackagePrefixElementFinder.java diff --git a/java/java-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java b/java/java-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java index 44d140cc579f..7f5dab51635e 100644 --- a/java/java-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java @@ -71,7 +71,6 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable { private final ConcurrentMap myPackageCache = new ConcurrentHashMap(); private final Project myProject; private final JavaFileManager myFileManager; - private final PackagePrefixIndex myPackagePrefixIndex; public JavaPsiFacadeImpl(Project project, @@ -89,10 +88,6 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable { ContainerUtil.addAll(elementFinders, myProject.getExtensions(PsiElementFinder.EP_NAME)); myElementFinders = elementFinders.toArray(new PsiElementFinder[elementFinders.size()]); - myPackagePrefixIndex = new PackagePrefixIndex(myProject); - - boolean isProjectDefault = project.isDefault(); - myFileManager = new JavaFileManagerImpl(psiManager, projectRootManagerEx, psiManager.getFileManager(), bus); final PsiModificationTrackerImpl modificationTracker = (PsiModificationTrackerImpl)psiManager.getModificationTracker(); @@ -216,15 +211,13 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable { return aPackage; } - if (DumbService.getInstance(getProject()).isDumb()) { - aPackage = findPackageDefault(qualifiedName); - if (aPackage != null) { - return ConcurrencyUtil.cacheOrGet(myPackageCache, qualifiedName, aPackage); - } - return null; + DumbService dumbService = DumbService.getInstance(getProject()); + List finders = Arrays.asList(myElementFinders); + if (dumbService.isDumb()) { + finders = dumbService.filterByDumbAwareness(finders); } - for (PsiElementFinder finder : myElementFinders) { + for (PsiElementFinder finder : finders) { aPackage = finder.findPackage(qualifiedName); if (aPackage != null) { return ConcurrencyUtil.cacheOrGet(myPackageCache, qualifiedName, aPackage); @@ -303,16 +296,6 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable { return myFileManager; } - public boolean packagePrefixExists(String packageQName) { - for (final String prefix : myPackagePrefixIndex.getAllPackagePrefixes(null)) { - if (StringUtil.startsWithConcatenationOf(prefix, packageQName, ".") || prefix.equals(packageQName)) { - return true; - } - } - - return false; - } - @Nullable private PsiPackage findPackageDefault(String qualifiedName) { final PsiPackage aPackage = myFileManager.findPackage(qualifiedName); @@ -321,10 +304,6 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable { if (migrationPackage != null) return migrationPackage; } - if (packagePrefixExists(qualifiedName)) { - return new PsiPackageImpl((PsiManagerEx)PsiManager.getInstance(myProject), qualifiedName); - } - return aPackage; } @@ -371,15 +350,6 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable { } } } - for (final String prefix : myPackagePrefixIndex.getAllPackagePrefixes(scope)) { - if (StringUtil.isEmpty(qualifiedName) || StringUtil.startsWithConcatenationOf(prefix, qualifiedName, ".")) { - final int i = prefix.indexOf('.', qualifiedName.length() + 1); - String childName = i >= 0 ? prefix.substring(0, i) : prefix; - if (!packagesMap.containsKey(childName)) { - packagesMap.put(childName, new PsiPackageImpl((PsiManagerEx)psiPackage.getManager(), childName)); - } - } - } packagesMap.remove(qualifiedName); // avoid SOE caused by returning a package as a subpackage of itself return packagesMap.values().toArray(new PsiPackage[packagesMap.size()]); diff --git a/java/java-impl/src/com/intellij/psi/impl/PackagePrefixElementFinder.java b/java/java-impl/src/com/intellij/psi/impl/PackagePrefixElementFinder.java new file mode 100644 index 000000000000..7f58413a051f --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/impl/PackagePrefixElementFinder.java @@ -0,0 +1,102 @@ +/* + * Copyright 2000-2011 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.psi.impl; + +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElementFinder; +import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiPackage; +import com.intellij.psi.impl.file.PsiPackageImpl; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.containers.HashMap; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +/** + * @author yole + */ +public class PackagePrefixElementFinder extends PsiElementFinder implements DumbAware { + private final Project myProject; + private final PackagePrefixIndex myPackagePrefixIndex; + + public PackagePrefixElementFinder(Project project) { + myProject = project; + myPackagePrefixIndex = new PackagePrefixIndex(project); + } + + @Override + public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { + return null; + } + + @NotNull + @Override + public PsiClass[] findClasses(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { + return PsiClass.EMPTY_ARRAY; + } + + @Override + public PsiPackage findPackage(@NotNull String qualifiedName) { + if (packagePrefixExists(qualifiedName)) { + return new PsiPackageImpl((PsiManagerEx)PsiManager.getInstance(myProject), qualifiedName); + } + return null; + } + + @NotNull + @Override + public PsiPackage[] getSubPackages(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + final Map packagesMap = new HashMap(); + final String qualifiedName = psiPackage.getQualifiedName(); + + for (final String prefix : myPackagePrefixIndex.getAllPackagePrefixes(scope)) { + if (StringUtil.isEmpty(qualifiedName) || StringUtil.startsWithConcatenationOf(prefix, qualifiedName, ".")) { + final int i = prefix.indexOf('.', qualifiedName.length() + 1); + String childName = i >= 0 ? prefix.substring(0, i) : prefix; + if (!packagesMap.containsKey(childName)) { + packagesMap.put(childName, new PsiPackageImpl((PsiManagerEx)psiPackage.getManager(), childName)); + } + } + } + + packagesMap.remove(qualifiedName); // avoid SOE caused by returning a package as a subpackage of itself + return packagesMap.values().toArray(new PsiPackage[packagesMap.size()]); + } + + public boolean packagePrefixExists(String packageQName) { + for (final String prefix : myPackagePrefixIndex.getAllPackagePrefixes(null)) { + if (StringUtil.startsWithConcatenationOf(prefix, packageQName, ".") || prefix.equals(packageQName)) { + return true; + } + } + + return false; + } + + public static PackagePrefixElementFinder getInstance(Project project) { + for (PsiElementFinder o : Extensions.getExtensions(PsiElementFinder.EP_NAME, project)) { + if (o instanceof PackagePrefixElementFinder) { + return (PackagePrefixElementFinder) o; + } + } + throw new UnsupportedOperationException("couldn't find self"); + } +} diff --git a/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java b/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java index b0b3418af082..03c26ea2c04d 100644 --- a/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java @@ -37,6 +37,7 @@ import com.intellij.openapi.wm.ToolWindowId; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.psi.*; import com.intellij.psi.impl.JavaPsiFacadeImpl; +import com.intellij.psi.impl.PackagePrefixElementFinder; import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.impl.migration.PsiMigrationImpl; import com.intellij.psi.impl.source.tree.java.PsiCompositeModifierList; @@ -180,7 +181,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya public boolean isValid() { final CommonProcessors.FindFirstProcessor processor = new CommonProcessors.FindFirstProcessor(); getFacade().processPackageDirectories(this, allScope(), processor); - return processor.getFoundValue() != null || getFacade().packagePrefixExists(getQualifiedName()); + return processor.getFoundValue() != null || PackagePrefixElementFinder.getInstance(getProject()).packagePrefixExists(getQualifiedName()); } public void accept(@NotNull PsiElementVisitor visitor) { diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 355eaa781588..f6a53787d719 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -1122,6 +1122,8 @@ + +