Snapshot of commit d5ec1d5018ed24f1b4f32b1d09df6dbd7e2fc425
from branch master of git://git.jetbrains.org/idea/community.git
diff --git a/java/java-indexing-api/java-indexing-api.iml b/java/java-indexing-api/java-indexing-api.iml
new file mode 100644
index 0000000..51bc4aa
--- /dev/null
+++ b/java/java-indexing-api/java-indexing-api.iml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="core-api" />
+ <orderEntry type="module" module-name="java-psi-api" />
+ <orderEntry type="module" module-name="indexing-api" />
+ </component>
+</module>
+
diff --git a/java/java-indexing-api/src/com/intellij/openapi/roots/ModulePackageIndex.java b/java/java-indexing-api/src/com/intellij/openapi/roots/ModulePackageIndex.java
new file mode 100644
index 0000000..6e2e35a
--- /dev/null
+++ b/java/java-indexing-api/src/com/intellij/openapi/roots/ModulePackageIndex.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2009 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.openapi.roots;
+
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleServiceManager;
+
+public abstract class ModulePackageIndex extends PackageIndex {
+ public static ModulePackageIndex getInstance(Module module) {
+ return ModuleServiceManager.getService(module, ModulePackageIndex.class);
+ }
+}
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/PsiShortNamesCache.java b/java/java-indexing-api/src/com/intellij/psi/search/PsiShortNamesCache.java
new file mode 100644
index 0000000..b85bd97
--- /dev/null
+++ b/java/java-indexing-api/src/com/intellij/psi/search/PsiShortNamesCache.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2000-2009 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.search;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.HashSet;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Allows to retrieve files and Java classes, methods and fields in a project by
+ * non-qualified names.
+ *
+ */
+public abstract class PsiShortNamesCache {
+ /**
+ * Return the composite short names cache, uniting all short name cache instances registered via extensions.
+ *
+ * @param project the project to return the cache for.
+ * @return the cache instance.
+ */
+
+ public static PsiShortNamesCache getInstance(Project project) {
+ return ServiceManager.getService(project, PsiShortNamesCache.class);
+ }
+
+ public static final ExtensionPointName<PsiShortNamesCache> EP_NAME = ExtensionPointName.create("com.intellij.java.shortNamesCache");
+
+ /**
+ * Returns the list of files with the specified name.
+ *
+ * @param name the name of the files to find.
+ * @return the list of files in the project which have the specified name.
+ */
+ @NotNull
+ public PsiFile[] getFilesByName(@NotNull String name) {
+ return PsiFile.EMPTY_ARRAY;
+ }
+
+ /**
+ * Returns the list of names of all files in the project.
+ *
+ * @return the list of all file names in the project.
+ */
+ @NotNull
+ public String[] getAllFileNames() {
+ return ArrayUtil.EMPTY_STRING_ARRAY;
+ }
+
+ /**
+ * Returns the list of all classes with the specified name in the specified scope.
+ *
+ * @param name the non-qualified name of the classes to find.
+ * @param scope the scope in which classes are searched.
+ * @return the list of found classes.
+ */
+ @NotNull
+ public abstract PsiClass[] getClassesByName(@NotNull @NonNls String name, @NotNull GlobalSearchScope scope);
+
+ /**
+ * Returns the list of names of all classes in the project and
+ * (optionally) libraries.
+ *
+ * @return the list of all class names.
+ */
+ @NotNull
+ public abstract String[] getAllClassNames();
+
+ /**
+ * Adds the names of all classes in the project and (optionally) libraries
+ * to the specified set.
+ *
+ * @param dest the set to add the names to.
+ */
+ public abstract void getAllClassNames(@NotNull HashSet<String> dest);
+
+ /**
+ * Returns the list of all methods with the specified name in the specified scope.
+ *
+ * @param name the name of the methods to find.
+ * @param scope the scope in which methods are searched.
+ * @return the list of found methods.
+ */
+ @NotNull
+ public abstract PsiMethod[] getMethodsByName(@NonNls @NotNull String name, @NotNull GlobalSearchScope scope);
+
+ @NotNull
+ public abstract PsiMethod[] getMethodsByNameIfNotMoreThan(@NonNls @NotNull String name, @NotNull GlobalSearchScope scope, int maxCount);
+ @NotNull
+ public abstract PsiField[] getFieldsByNameIfNotMoreThan(@NonNls @NotNull String name, @NotNull GlobalSearchScope scope, int maxCount);
+
+ public abstract boolean processMethodsWithName(@NonNls @NotNull String name, @NotNull GlobalSearchScope scope, @NotNull Processor<PsiMethod> processor);
+
+ /**
+ * Returns the list of names of all methods in the project and
+ * (optionally) libraries.
+ *
+ * @return the list of all method names.
+ */
+ @NotNull
+ public abstract String[] getAllMethodNames();
+
+ /**
+ * Adds the names of all methods in the project and (optionally) libraries
+ * to the specified set.
+ *
+ * @param set the set to add the names to.
+ */
+ public abstract void getAllMethodNames(@NotNull HashSet<String> set);
+
+ /**
+ * Returns the list of all fields with the specified name in the specified scope.
+ *
+ * @param name the name of the fields to find.
+ * @param scope the scope in which fields are searched.
+ * @return the list of found fields.
+ */
+ @NotNull
+ public abstract PsiField[] getFieldsByName(@NotNull @NonNls String name, @NotNull GlobalSearchScope scope);
+
+ /**
+ * Returns the list of names of all fields in the project and
+ * (optionally) libraries.
+ *
+ * @return the list of all field names.
+ */
+ @NotNull
+ public abstract String[] getAllFieldNames();
+
+ /**
+ * Adds the names of all methods in the project and (optionally) libraries
+ * to the specified set.
+ *
+ * @param set the set to add the names to.
+ */
+ public abstract void getAllFieldNames(@NotNull HashSet<String> set);
+}
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/AllClassesSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/AllClassesSearch.java
new file mode 100644
index 0000000..5ce8995
--- /dev/null
+++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/AllClassesSearch.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2000-2009 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.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.psi.search.searches;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.util.Query;
+import com.intellij.util.QueryExecutor;
+
+public class AllClassesSearch extends ExtensibleQueryFactory<PsiClass, AllClassesSearch.SearchParameters> {
+ public static ExtensionPointName<QueryExecutor> EP_NAME = ExtensionPointName.create("com.intellij.allClassesSearch");
+ public static final AllClassesSearch INSTANCE = new AllClassesSearch();
+
+ public static class SearchParameters {
+ private final SearchScope myScope;
+ private final Project myProject;
+ private final Condition<String> myShortNameCondition;
+
+ public SearchParameters(final SearchScope scope, final Project project) {
+ this(scope, project, Condition.TRUE);
+ }
+
+ public SearchParameters(final SearchScope scope, final Project project, final Condition<String> shortNameCondition) {
+ myScope = scope;
+ myProject = project;
+ myShortNameCondition = shortNameCondition;
+ }
+
+ public SearchScope getScope() {
+ return myScope;
+ }
+
+ public Project getProject() {
+ return myProject;
+ }
+
+ public boolean nameMatches(String name) {
+ return myShortNameCondition.value(name);
+ }
+ }
+
+ public static Query<PsiClass> search(SearchScope scope, Project project) {
+ return INSTANCE.createQuery(new SearchParameters(scope, project));
+ }
+
+ public static Query<PsiClass> search(SearchScope scope, Project project, Condition<String> shortNameCondition) {
+ return INSTANCE.createQuery(new SearchParameters(scope, project, shortNameCondition));
+ }
+}
\ No newline at end of file
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/AllOverridingMethodsSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/AllOverridingMethodsSearch.java
new file mode 100644
index 0000000..ff34ed4
--- /dev/null
+++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/AllOverridingMethodsSearch.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2009 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.search.searches;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiModifier;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.EmptyQuery;
+import com.intellij.util.Query;
+import com.intellij.util.QueryExecutor;
+
+/**
+ * @author ven
+ * Searches deeply for all overriding methods of all methods in a class, processing pairs
+ * (method in original class, overriding method)
+ */
+public class AllOverridingMethodsSearch extends ExtensibleQueryFactory<Pair<PsiMethod, PsiMethod>, AllOverridingMethodsSearch.SearchParameters> {
+ public static ExtensionPointName<QueryExecutor> EP_NAME = ExtensionPointName.create("com.intellij.allOverridingMethodsSearch");
+ public static final AllOverridingMethodsSearch INSTANCE = new AllOverridingMethodsSearch();
+
+ public static class SearchParameters {
+ private final PsiClass myClass;
+ private final SearchScope myScope;
+
+ public SearchParameters(final PsiClass aClass, SearchScope scope) {
+ myClass = aClass;
+ myScope = scope;
+ }
+
+ public PsiClass getPsiClass() {
+ return myClass;
+ }
+
+ public SearchScope getScope() {
+ return myScope;
+ }
+ }
+
+ private AllOverridingMethodsSearch() {
+ }
+
+ public static Query<Pair<PsiMethod, PsiMethod>> search(final PsiClass aClass, SearchScope scope) {
+ if (aClass.hasModifierProperty(PsiModifier.FINAL)) return EmptyQuery.getEmptyQuery(); // Optimization
+ return INSTANCE.createUniqueResultsQuery(new SearchParameters(aClass, scope));
+ }
+
+ public static Query<Pair<PsiMethod, PsiMethod>> search(final PsiClass aClass) {
+ return search(aClass, GlobalSearchScope.allScope(aClass.getProject()));
+ }
+}
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/AnnotatedElementsSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/AnnotatedElementsSearch.java
new file mode 100644
index 0000000..7f68eaf
--- /dev/null
+++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/AnnotatedElementsSearch.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2009 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.search.searches;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.*;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.util.InstanceofQuery;
+import com.intellij.util.Query;
+import com.intellij.util.QueryExecutor;
+import org.jetbrains.annotations.NotNull;
+
+public class AnnotatedElementsSearch extends ExtensibleQueryFactory<PsiModifierListOwner, AnnotatedElementsSearch.Parameters> {
+ public static ExtensionPointName<QueryExecutor> EP_NAME = ExtensionPointName.create("com.intellij.annotatedElementsSearch");
+ public static final AnnotatedElementsSearch INSTANCE = new AnnotatedElementsSearch();
+
+ public static class Parameters {
+ private final PsiClass myAnnotationClass;
+ private final SearchScope myScope;
+ private final Class<? extends PsiModifierListOwner>[] myTypes;
+
+ public Parameters(final PsiClass annotationClass, final SearchScope scope, Class<? extends PsiModifierListOwner>... types) {
+ myAnnotationClass = annotationClass;
+ myScope = scope;
+ myTypes = types;
+ }
+
+ public PsiClass getAnnotationClass() {
+ return myAnnotationClass;
+ }
+
+ public SearchScope getScope() {
+ return myScope;
+ }
+
+ public Class<? extends PsiModifierListOwner>[] getTypes() {
+ return myTypes;
+ }
+ }
+
+ private static Query<PsiModifierListOwner> createDelegateQuery(PsiClass annotationClass, SearchScope scope, Class<? extends PsiModifierListOwner>... types) {
+ return INSTANCE.createQuery(new Parameters(annotationClass, scope, types));
+ }
+
+ public static <T extends PsiModifierListOwner> Query<T> searchElements(@NotNull PsiClass annotationClass, @NotNull SearchScope scope, Class<? extends T>... types) {
+ return new InstanceofQuery<T>(createDelegateQuery(annotationClass, scope, types), types);
+ }
+
+ public static Query<PsiClass> searchPsiClasses(@NotNull PsiClass annotationClass, @NotNull SearchScope scope) {
+ return searchElements(annotationClass, scope, PsiClass.class);
+ }
+
+ public static Query<PsiMethod> searchPsiMethods(@NotNull PsiClass annotationClass, @NotNull SearchScope scope) {
+ return searchElements(annotationClass, scope, PsiMethod.class);
+ }
+
+ public static Query<PsiMember> searchPsiMembers(@NotNull PsiClass annotationClass, @NotNull SearchScope scope) {
+ return searchElements(annotationClass, scope, PsiMember.class);
+ }
+
+ public static Query<PsiField> searchPsiFields(@NotNull PsiClass annotationClass, @NotNull SearchScope scope) {
+ return searchElements(annotationClass, scope, PsiField.class);
+ }
+
+ public static Query<PsiParameter> searchPsiParameters(@NotNull PsiClass annotationClass, @NotNull SearchScope scope) {
+ return searchElements(annotationClass, scope, PsiParameter.class);
+ }
+}
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java
new file mode 100644
index 0000000..233bb42
--- /dev/null
+++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2000-2009 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.search.searches;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressIndicatorProvider;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.Ref;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.PsiSearchScopeUtil;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.reference.SoftReference;
+import com.intellij.util.Processor;
+import com.intellij.util.Query;
+import com.intellij.util.QueryExecutor;
+import com.intellij.util.containers.Stack;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.ref.Reference;
+import java.util.Set;
+
+/**
+ * @author max
+ */
+public class ClassInheritorsSearch extends ExtensibleQueryFactory<PsiClass, ClassInheritorsSearch.SearchParameters> {
+ public static ExtensionPointName<QueryExecutor> EP_NAME = ExtensionPointName.create("com.intellij.classInheritorsSearch");
+ private static final Logger LOG = Logger.getInstance("#com.intellij.psi.search.searches.ClassInheritorsSearch");
+
+ public static final ClassInheritorsSearch INSTANCE = new ClassInheritorsSearch();
+
+ static {
+ INSTANCE.registerExecutor(new QueryExecutor<PsiClass, SearchParameters>() {
+ @Override
+ public boolean execute(@NotNull final SearchParameters parameters, @NotNull final Processor<PsiClass> consumer) {
+ final PsiClass baseClass = parameters.getClassToProcess();
+ final SearchScope searchScope = parameters.getScope();
+
+ LOG.assertTrue(searchScope != null);
+
+ ProgressIndicator progress = ProgressIndicatorProvider.getGlobalProgressIndicator();
+ if (progress != null) {
+ progress.pushState();
+ String className = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+ @Override
+ public String compute() {
+ return baseClass.getName();
+ }
+ });
+ progress.setText(className != null ?
+ PsiBundle.message("psi.search.inheritors.of.class.progress", className) :
+ PsiBundle.message("psi.search.inheritors.progress"));
+ }
+
+ boolean result = processInheritors(consumer, baseClass, searchScope, parameters);
+
+ if (progress != null) {
+ progress.popState();
+ }
+
+ return result;
+ }
+ });
+ }
+
+ public static class SearchParameters {
+ private final PsiClass myClass;
+ private final SearchScope myScope;
+ private final boolean myCheckDeep;
+ private final boolean myCheckInheritance;
+ private final boolean myIncludeAnonymous;
+ private final Condition<String> myNameCondition;
+
+ public SearchParameters(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance, boolean includeAnonymous) {
+ this(aClass, scope, checkDeep, checkInheritance, includeAnonymous, Condition.TRUE);
+ }
+
+ public SearchParameters(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance,
+ boolean includeAnonymous, @NotNull final Condition<String> nameCondition) {
+ myClass = aClass;
+ myScope = scope;
+ myCheckDeep = checkDeep;
+ myCheckInheritance = checkInheritance;
+ myIncludeAnonymous = includeAnonymous;
+ myNameCondition = nameCondition;
+ }
+
+ @NotNull
+ public PsiClass getClassToProcess() {
+ return myClass;
+ }
+
+ @NotNull public Condition<String> getNameCondition() {
+ return myNameCondition;
+ }
+
+ public boolean isCheckDeep() {
+ return myCheckDeep;
+ }
+
+ public SearchScope getScope() {
+ return myScope;
+ }
+
+ public boolean isCheckInheritance() {
+ return myCheckInheritance;
+ }
+
+ public boolean isIncludeAnonymous() {
+ return myIncludeAnonymous;
+ }
+ }
+
+ private ClassInheritorsSearch() {}
+
+ public static Query<PsiClass> search(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance, boolean includeAnonymous) {
+ return search(new SearchParameters(aClass, scope, checkDeep, checkInheritance, includeAnonymous));
+ }
+
+ public static Query<PsiClass> search(@NotNull SearchParameters parameters) {
+ return INSTANCE.createQuery(parameters);
+ }
+
+ public static Query<PsiClass> search(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance) {
+ return search(aClass, scope, checkDeep, checkInheritance, true);
+ }
+
+ public static Query<PsiClass> search(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep) {
+ return search(aClass, scope, checkDeep, true);
+ }
+
+ public static Query<PsiClass> search(@NotNull final PsiClass aClass, final boolean checkDeep) {
+ return search(aClass, aClass.getUseScope(), checkDeep);
+ }
+
+ public static Query<PsiClass> search(@NotNull PsiClass aClass) {
+ return search(aClass, true);
+ }
+
+ private static boolean processInheritors(@NotNull final Processor<PsiClass> consumer,
+ @NotNull final PsiClass baseClass,
+ @NotNull final SearchScope searchScope,
+ @NotNull final SearchParameters parameters) {
+ if (baseClass instanceof PsiAnonymousClass || isFinal(baseClass)) return true;
+
+ final String qname = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+ @Override
+ public String compute() {
+ return baseClass.getQualifiedName();
+ }
+ });
+ if (CommonClassNames.JAVA_LANG_OBJECT.equals(qname)) {
+ return AllClassesSearch.search(searchScope, baseClass.getProject(), parameters.getNameCondition()).forEach(new Processor<PsiClass>() {
+ @Override
+ public boolean process(final PsiClass aClass) {
+ ProgressIndicatorProvider.checkCanceled();
+ final String qname1 = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+ @Override
+ @Nullable
+ public String compute() {
+ return aClass.getQualifiedName();
+ }
+ });
+ return CommonClassNames.JAVA_LANG_OBJECT.equals(qname1) || consumer.process(aClass);
+ }
+ });
+ }
+
+ final Ref<PsiClass> currentBase = Ref.create(null);
+ final Stack<Pair<Reference<PsiClass>, String>> stack = new Stack<Pair<Reference<PsiClass>, String>>();
+ // there are two sets for memory optimization: it's cheaper to hold FQN than PsiClass
+ final Set<String> processedFqns = new THashSet<String>(); // FQN of processed classes if the class has one
+ final Set<PsiClass> processed = new THashSet<PsiClass>(); // processed classes without FQN (e.g. anonymous)
+
+ final Processor<PsiClass> processor = new Processor<PsiClass>() {
+ @Override
+ public boolean process(final PsiClass candidate) {
+ ProgressIndicatorProvider.checkCanceled();
+
+ final Ref<Boolean> result = new Ref<Boolean>();
+ final String[] fqn = new String[1];
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ fqn[0] = candidate.getQualifiedName();
+ if (parameters.isCheckInheritance() || parameters.isCheckDeep() && !(candidate instanceof PsiAnonymousClass)) {
+ if (!candidate.isInheritor(currentBase.get(), false)) {
+ result.set(true);
+ return;
+ }
+ }
+
+ if (PsiSearchScopeUtil.isInScope(searchScope, candidate)) {
+ if (candidate instanceof PsiAnonymousClass) {
+ result.set(consumer.process(candidate));
+ }
+ else {
+ final String name = candidate.getName();
+ if (name != null && parameters.getNameCondition().value(name) && !consumer.process(candidate)) result.set(false);
+ }
+ }
+ }
+ });
+ if (!result.isNull()) return result.get().booleanValue();
+
+ if (parameters.isCheckDeep() && !(candidate instanceof PsiAnonymousClass) && !isFinal(candidate)) {
+ Reference<PsiClass> ref = fqn[0] == null ? createHardReference(candidate) : new SoftReference<PsiClass>(candidate);
+ stack.push(Pair.create(ref, fqn[0]));
+ }
+
+ return true;
+ }
+ };
+ stack.push(Pair.create(createHardReference(baseClass), qname));
+ final GlobalSearchScope projectScope = GlobalSearchScope.allScope(baseClass.getProject());
+ final JavaPsiFacade facade = JavaPsiFacade.getInstance(projectScope.getProject());
+ while (!stack.isEmpty()) {
+ ProgressIndicatorProvider.checkCanceled();
+
+ Pair<Reference<PsiClass>, String> pair = stack.pop();
+ PsiClass psiClass = pair.getFirst().get();
+ final String fqn = pair.getSecond();
+ if (psiClass == null) {
+ psiClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
+ @Override
+ public PsiClass compute() {
+ return facade.findClass(fqn, projectScope);
+ }
+ });
+ if (psiClass == null) continue;
+ }
+ if (fqn == null) {
+ if (!processed.add(psiClass)) continue;
+ }
+ else {
+ if (!processedFqns.add(fqn)) continue;
+ }
+
+ currentBase.set(psiClass);
+ if (!DirectClassInheritorsSearch.search(psiClass, projectScope, parameters.isIncludeAnonymous(), false).forEach(processor)) return false;
+ }
+ return true;
+ }
+
+ private static Reference<PsiClass> createHardReference(final PsiClass candidate) {
+ return new SoftReference<PsiClass>(candidate){
+ @Override
+ public PsiClass get() {
+ return candidate;
+ }
+ };
+ }
+
+ private static boolean isFinal(@NotNull final PsiClass baseClass) {
+ return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
+ @Override
+ public Boolean compute() {
+ return Boolean.valueOf(baseClass.hasModifierProperty(PsiModifier.FINAL));
+ }
+ }).booleanValue();
+ }
+}
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/DirectClassInheritorsSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/DirectClassInheritorsSearch.java
new file mode 100644
index 0000000..da798a1
--- /dev/null
+++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/DirectClassInheritorsSearch.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2000-2009 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.search.searches;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.PsiAnonymousClass;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.util.FilteredQuery;
+import com.intellij.util.Query;
+import com.intellij.util.QueryExecutor;
+
+/**
+ * @author max
+ */
+public class DirectClassInheritorsSearch extends ExtensibleQueryFactory<PsiClass, DirectClassInheritorsSearch.SearchParameters> {
+ public static ExtensionPointName<QueryExecutor> EP_NAME = ExtensionPointName.create("com.intellij.directClassInheritorsSearch");
+ public static DirectClassInheritorsSearch INSTANCE = new DirectClassInheritorsSearch();
+
+ public static class SearchParameters {
+ private final PsiClass myClass;
+ private final SearchScope myScope;
+ private final boolean myIncludeAnonymous;
+ private final boolean myCheckInheritance;
+
+ public SearchParameters(PsiClass aClass, SearchScope scope, boolean includeAnonymous, boolean checkInheritance) {
+ myClass = aClass;
+ myScope = scope;
+ myIncludeAnonymous = includeAnonymous;
+ myCheckInheritance = checkInheritance;
+ }
+
+ public SearchParameters(final PsiClass aClass, SearchScope scope, final boolean includeAnonymous) {
+ this(aClass, scope, includeAnonymous, true);
+ }
+
+ public SearchParameters(final PsiClass aClass, final SearchScope scope) {
+ this(aClass, scope, true);
+ }
+
+ public PsiClass getClassToProcess() {
+ return myClass;
+ }
+
+ public SearchScope getScope() {
+ return myScope;
+ }
+
+ public boolean isCheckInheritance() {
+ return myCheckInheritance;
+ }
+
+ public boolean includeAnonymous() {
+ return myIncludeAnonymous;
+ }
+ }
+
+ private DirectClassInheritorsSearch() {}
+
+ public static Query<PsiClass> search(final PsiClass aClass) {
+ return search(aClass, GlobalSearchScope.allScope(aClass.getProject()));
+ }
+
+ public static Query<PsiClass> search(final PsiClass aClass, SearchScope scope) {
+ return INSTANCE.createUniqueResultsQuery(new SearchParameters(aClass, scope));
+ }
+
+ public static Query<PsiClass> search(final PsiClass aClass, SearchScope scope, boolean includeAnonymous) {
+ return search(aClass, scope, includeAnonymous, true);
+ }
+
+ public static Query<PsiClass> search(final PsiClass aClass,
+ SearchScope scope,
+ boolean includeAnonymous,
+ final boolean checkInheritance) {
+ final Query<PsiClass> raw = INSTANCE.createUniqueResultsQuery(new SearchParameters(aClass, scope, includeAnonymous, checkInheritance));
+
+ if (!includeAnonymous) {
+ return new FilteredQuery<PsiClass>(raw, new Condition<PsiClass>() {
+ @Override
+ public boolean value(final PsiClass psiClass) {
+ return !(psiClass instanceof PsiAnonymousClass);
+ }
+ });
+ }
+
+ return raw;
+ }
+}
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/MethodReferencesSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/MethodReferencesSearch.java
new file mode 100644
index 0000000..f13ae0f
--- /dev/null
+++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/MethodReferencesSearch.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2000-2009 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.search.searches;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.search.*;
+import com.intellij.util.*;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author max
+ */
+public class MethodReferencesSearch extends ExtensibleQueryFactory<PsiReference, MethodReferencesSearch.SearchParameters> {
+ public static ExtensionPointName<QueryExecutor> EP_NAME = ExtensionPointName.create("com.intellij.methodReferencesSearch");
+ public static final MethodReferencesSearch INSTANCE = new MethodReferencesSearch();
+
+ public static class SearchParameters {
+ private final PsiMethod myMethod;
+ private final SearchScope myScope;
+ private final boolean myStrictSignatureSearch;
+ private final SearchRequestCollector myOptimizer;
+ private final boolean isSharedOptimizer;
+
+ public SearchParameters(PsiMethod method, SearchScope scope, boolean strictSignatureSearch, @Nullable SearchRequestCollector optimizer) {
+ myMethod = method;
+ myScope = scope;
+ myStrictSignatureSearch = strictSignatureSearch;
+ isSharedOptimizer = optimizer != null;
+ myOptimizer = optimizer != null ? optimizer : new SearchRequestCollector(new SearchSession());
+ }
+
+ public SearchParameters(final PsiMethod aClass, SearchScope scope, final boolean strict) {
+ this(aClass, scope, strict, null);
+ }
+
+ public PsiMethod getMethod() {
+ return myMethod;
+ }
+
+ public boolean isStrictSignatureSearch() {
+ return myStrictSignatureSearch;
+ }
+
+ public SearchRequestCollector getOptimizer() {
+ return myOptimizer;
+ }
+
+ public SearchScope getScope() {
+ return myScope;
+ }
+ }
+
+ private MethodReferencesSearch() {}
+
+ public static Query<PsiReference> search(final PsiMethod method, SearchScope scope, final boolean strictSignatureSearch) {
+ return search(new SearchParameters(method, scope, strictSignatureSearch));
+ }
+
+ public static void searchOptimized(final PsiMethod method, SearchScope scope, final boolean strictSignatureSearch,
+ @NotNull SearchRequestCollector collector, final Processor<PsiReference> processor) {
+ searchOptimized(method, scope, strictSignatureSearch, collector, false, new PairProcessor<PsiReference, SearchRequestCollector>() {
+ @Override
+ public boolean process(PsiReference psiReference, SearchRequestCollector collector) {
+ return processor.process(psiReference);
+ }
+ });
+ }
+public static void searchOptimized(final PsiMethod method, SearchScope scope, final boolean strictSignatureSearch, SearchRequestCollector collector, final boolean inReadAction, PairProcessor<PsiReference, SearchRequestCollector> processor) {
+ final SearchRequestCollector nested = new SearchRequestCollector(collector.getSearchSession());
+ collector.searchQuery(new QuerySearchRequest(search(new SearchParameters(method, scope, strictSignatureSearch, nested)), nested,
+ inReadAction, processor));
+ }
+
+ public static Query<PsiReference> search(final SearchParameters parameters) {
+ final Query<PsiReference> result = INSTANCE.createQuery(parameters);
+ if (parameters.isSharedOptimizer) {
+ return uniqueResults(result);
+ }
+
+ final SearchRequestCollector requests = parameters.getOptimizer();
+
+ return uniqueResults(new MergeQuery<PsiReference>(result, new SearchRequestQuery(parameters.getMethod().getProject(), requests)));
+ }
+
+ public static Query<PsiReference> search(final PsiMethod method, final boolean strictSignatureSearch) {
+ return search(method, GlobalSearchScope.allScope(method.getProject()), strictSignatureSearch);
+ }
+
+ public static Query<PsiReference> search(final PsiMethod method) {
+ return search(method, true);
+ }
+
+ private static UniqueResultsQuery<PsiReference, ReferenceDescriptor> uniqueResults(@NotNull Query<PsiReference> composite) {
+ return new UniqueResultsQuery<PsiReference, ReferenceDescriptor>(composite, ContainerUtil.<ReferenceDescriptor>canonicalStrategy(), ReferenceDescriptor.MAPPER);
+ }
+}
\ No newline at end of file
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/OverridingMethodsSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/OverridingMethodsSearch.java
new file mode 100644
index 0000000..4a5f538
--- /dev/null
+++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/OverridingMethodsSearch.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2000-2012 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.search.searches;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.util.Computable;
+import com.intellij.psi.PsiAnonymousClass;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiModifier;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.util.EmptyQuery;
+import com.intellij.util.Query;
+import com.intellij.util.QueryExecutor;
+
+/**
+ * @author max
+ */
+public class OverridingMethodsSearch extends ExtensibleQueryFactory<PsiMethod, OverridingMethodsSearch.SearchParameters> {
+ public static ExtensionPointName<QueryExecutor> EP_NAME = ExtensionPointName.create("com.intellij.overridingMethodsSearch");
+ public static final OverridingMethodsSearch INSTANCE = new OverridingMethodsSearch();
+
+ public static class SearchParameters {
+ private final PsiMethod myMethod;
+ private final SearchScope myScope;
+ private final boolean myCheckDeep;
+
+ public SearchParameters(final PsiMethod aClass, SearchScope scope, final boolean checkDeep) {
+ myMethod = aClass;
+ myScope = scope;
+ myCheckDeep = checkDeep;
+ }
+
+ public PsiMethod getMethod() {
+ return myMethod;
+ }
+
+ public boolean isCheckDeep() {
+ return myCheckDeep;
+ }
+
+ public SearchScope getScope() {
+ return myScope;
+ }
+ }
+
+ private OverridingMethodsSearch() {
+ }
+
+ public static Query<PsiMethod> search(final PsiMethod method, SearchScope scope, final boolean checkDeep) {
+ if (ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
+ @Override
+ public Boolean compute() {
+ return cannotBeOverriden(method);
+ }
+ })) return EmptyQuery.getEmptyQuery(); // Optimization
+ return INSTANCE.createUniqueResultsQuery(new SearchParameters(method, scope, checkDeep));
+ }
+
+ private static boolean cannotBeOverriden(final PsiMethod method) {
+ final PsiClass parentClass = method.getContainingClass();
+ return parentClass == null
+ || method.isConstructor()
+ || method.hasModifierProperty(PsiModifier.STATIC)
+ || method.hasModifierProperty(PsiModifier.FINAL)
+ || method.hasModifierProperty(PsiModifier.PRIVATE)
+ || parentClass instanceof PsiAnonymousClass
+ || parentClass.hasModifierProperty(PsiModifier.FINAL);
+ }
+
+ public static Query<PsiMethod> search(final PsiMethod method, final boolean checkDeep) {
+ return search(method, ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() {
+ @Override
+ public SearchScope compute() {
+ return method.getUseScope();
+ }
+ }), checkDeep);
+ }
+
+ public static Query<PsiMethod> search(final PsiMethod method) {
+ return search(method, true);
+ }
+}