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);
+  }
+}