Snapshot of commit d5ec1d5018ed24f1b4f32b1d09df6dbd7e2fc425
from branch master of git://git.jetbrains.org/idea/community.git
diff --git a/java/java-indexing-impl/java-indexing-impl.iml b/java/java-indexing-impl/java-indexing-impl.iml
new file mode 100644
index 0000000..0379d94
--- /dev/null
+++ b/java/java-indexing-impl/java-indexing-impl.iml
@@ -0,0 +1,19 @@
+<?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="java-psi-api" exported="" />
+ <orderEntry type="module" module-name="java-psi-impl" exported="" />
+ <orderEntry type="module" module-name="indexing-api" exported="" />
+ <orderEntry type="module" module-name="indexing-impl" exported="" />
+ <orderEntry type="module" module-name="projectModel-api" />
+ <orderEntry type="module" module-name="projectModel-impl" />
+ <orderEntry type="module" module-name="java-indexing-api" />
+ </component>
+</module>
+
diff --git a/java/java-indexing-impl/src/com/intellij/codeInsight/ReadableExternalAnnotationsManager.java b/java/java-indexing-impl/src/com/intellij/codeInsight/ReadableExternalAnnotationsManager.java
new file mode 100644
index 0000000..727f4a2
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/codeInsight/ReadableExternalAnnotationsManager.java
@@ -0,0 +1,81 @@
+/*
+ * 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.codeInsight;
+
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.roots.*;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.psi.PsiManager;
+import com.intellij.util.ThreeState;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ReadableExternalAnnotationsManager extends BaseExternalAnnotationsManager {
+ @NotNull private volatile ThreeState myHasAnyAnnotationsRoots = ThreeState.UNSURE;
+
+ public ReadableExternalAnnotationsManager(PsiManager psiManager) {
+ super(psiManager);
+ }
+
+ @Override
+ protected boolean hasAnyAnnotationsRoots() {
+ if (myHasAnyAnnotationsRoots == ThreeState.UNSURE) {
+ final Module[] modules = ModuleManager.getInstance(myPsiManager.getProject()).getModules();
+ for (Module module : modules) {
+ for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) {
+ final String[] urls = AnnotationOrderRootType.getUrls(entry);
+ if (urls.length > 0) {
+ myHasAnyAnnotationsRoots = ThreeState.YES;
+ return true;
+ }
+ }
+ }
+ myHasAnyAnnotationsRoots = ThreeState.NO;
+ }
+ return myHasAnyAnnotationsRoots == ThreeState.YES;
+ }
+
+ @NotNull
+ @Override
+ protected List<VirtualFile> getExternalAnnotationsRoots(@NotNull VirtualFile libraryFile) {
+ final List<OrderEntry> entries = ProjectRootManager.getInstance(myPsiManager.getProject()).getFileIndex().getOrderEntriesForFile(
+ libraryFile);
+ List<VirtualFile> result = new ArrayList<VirtualFile>();
+ for (OrderEntry entry : entries) {
+ if (entry instanceof ModuleOrderEntry) {
+ continue;
+ }
+ final String[] externalUrls = AnnotationOrderRootType.getUrls(entry);
+ for (String url : externalUrls) {
+ VirtualFile root = VirtualFileManager.getInstance().findFileByUrl(url);
+ if (root != null) {
+ result.add(root);
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ protected void dropCache() {
+ myHasAnyAnnotationsRoots = ThreeState.UNSURE;
+ super.dropCache();
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/codeInsight/navigation/ClassImplementationsSearch.java b/java/java-indexing-impl/src/com/intellij/codeInsight/navigation/ClassImplementationsSearch.java
new file mode 100644
index 0000000..a19630d
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/codeInsight/navigation/ClassImplementationsSearch.java
@@ -0,0 +1,52 @@
+/*
+ * 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.codeInsight.navigation;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.search.PsiElementProcessor;
+import com.intellij.psi.search.PsiElementProcessorAdapter;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.searches.ClassInheritorsSearch;
+import com.intellij.util.Processor;
+import com.intellij.util.QueryExecutor;
+import org.jetbrains.annotations.NotNull;
+
+public class ClassImplementationsSearch implements QueryExecutor<PsiElement, PsiElement> {
+ public boolean execute(@NotNull final PsiElement sourceElement, @NotNull final Processor<PsiElement> consumer) {
+ return !(sourceElement instanceof PsiClass) || processImplementations((PsiClass)sourceElement, consumer);
+ }
+
+ public static boolean processImplementations(final PsiClass psiClass, final Processor<? super PsiClass> processor) {
+ final boolean showInterfaces = Registry.is("ide.goto.implementation.show.interfaces");
+ return ClassInheritorsSearch.search(psiClass, ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() {
+ @Override
+ public SearchScope compute() {
+ return psiClass.getUseScope();
+ }
+ }), true).forEach(new PsiElementProcessorAdapter<PsiClass>(new PsiElementProcessor<PsiClass>() {
+ public boolean execute(@NotNull PsiClass element) {
+ if (!showInterfaces && element.isInterface()) {
+ return true;
+ }
+ return processor.process(element);
+ }
+ }));
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/codeInsight/navigation/MethodImplementationsSearch.java b/java/java-indexing-impl/src/com/intellij/codeInsight/navigation/MethodImplementationsSearch.java
new file mode 100644
index 0000000..dfe436a
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/codeInsight/navigation/MethodImplementationsSearch.java
@@ -0,0 +1,49 @@
+/*
+ * 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.codeInsight.navigation;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.search.searches.OverridingMethodsSearch;
+import com.intellij.util.QueryExecutor;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+
+public class MethodImplementationsSearch implements QueryExecutor<PsiElement, PsiElement> {
+ public boolean execute(@NotNull final PsiElement sourceElement, @NotNull final Processor<PsiElement> consumer) {
+ if (sourceElement instanceof PsiMethod) {
+ PsiMethod[] implementations = getMethodImplementations((PsiMethod)sourceElement);
+ return ContainerUtil.process(implementations, consumer);
+ }
+ return true;
+ }
+
+ public static void getOverridingMethods(PsiMethod method, ArrayList<PsiMethod> list) {
+ for (PsiMethod psiMethod : OverridingMethodsSearch.search(method)) {
+ list.add(psiMethod);
+ }
+ }
+
+ public static PsiMethod[] getMethodImplementations(final PsiMethod method) {
+ ArrayList<PsiMethod> result = new ArrayList<PsiMethod>();
+
+ getOverridingMethods(method, result);
+ return result.toArray(new PsiMethod[result.size()]);
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/openapi/roots/impl/ProjectPackageIndexImpl.java b/java/java-indexing-impl/src/com/intellij/openapi/roots/impl/ProjectPackageIndexImpl.java
new file mode 100644
index 0000000..601ff49
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/openapi/roots/impl/ProjectPackageIndexImpl.java
@@ -0,0 +1,40 @@
+/*
+ * 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.impl;
+
+import com.intellij.openapi.roots.PackageIndex;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Query;
+import org.jetbrains.annotations.NotNull;
+
+public class ProjectPackageIndexImpl extends PackageIndex {
+ private final DirectoryIndex myDirectoryIndex;
+
+ public ProjectPackageIndexImpl(DirectoryIndex directoryIndex) {
+ myDirectoryIndex = directoryIndex;
+ }
+
+ @Override
+ public VirtualFile[] getDirectoriesByPackageName(@NotNull String packageName, boolean includeLibrarySources) {
+ return getDirsByPackageName(packageName, includeLibrarySources).toArray(VirtualFile.EMPTY_ARRAY);
+ }
+
+ @Override
+ public Query<VirtualFile> getDirsByPackageName(@NotNull String packageName, boolean includeLibrarySources) {
+ return myDirectoryIndex.getDirectoriesByPackageName(packageName, includeLibrarySources);
+ }
+
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java b/java/java-indexing-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java
new file mode 100644
index 0000000..269006b
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/CompositeShortNamesCache.java
@@ -0,0 +1,243 @@
+/*
+ * 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.impl;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiField;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.PsiShortNamesCache;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.HashSet;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.Set;
+
+public class CompositeShortNamesCache extends PsiShortNamesCache {
+ private final PsiShortNamesCache[] myCaches;
+
+ public CompositeShortNamesCache(Project project) {
+ myCaches = project.isDefault() ? new PsiShortNamesCache[0] : project.getExtensions(PsiShortNamesCache.EP_NAME);
+ }
+
+ @Override
+ @NotNull
+ public PsiFile[] getFilesByName(@NotNull String name) {
+ Merger<PsiFile> merger = null;
+ for (PsiShortNamesCache cache : myCaches) {
+ PsiFile[] classes = cache.getFilesByName(name);
+ if (classes.length != 0) {
+ if (merger == null) merger = new Merger<PsiFile>();
+ merger.add(classes);
+ }
+ }
+ PsiFile[] result = merger == null ? null : merger.getResult();
+ return result != null ? result : PsiFile.EMPTY_ARRAY;
+ }
+
+ @Override
+ @NotNull
+ public String[] getAllFileNames() {
+ Merger<String> merger = new Merger<String>();
+ for (PsiShortNamesCache cache : myCaches) {
+ merger.add(cache.getAllFileNames());
+ }
+ String[] result = merger.getResult();
+ return result != null ? result : ArrayUtil.EMPTY_STRING_ARRAY;
+ }
+
+ @Override
+ @NotNull
+ public PsiClass[] getClassesByName(@NotNull String name, @NotNull GlobalSearchScope scope) {
+ Merger<PsiClass> merger = null;
+ for (PsiShortNamesCache cache : myCaches) {
+ PsiClass[] classes = cache.getClassesByName(name, scope);
+ if (classes.length != 0) {
+ if (merger == null) merger = new Merger<PsiClass>();
+ merger.add(classes);
+ }
+ }
+ PsiClass[] result = merger == null ? null : merger.getResult();
+ return result != null ? result : PsiClass.EMPTY_ARRAY;
+ }
+
+ @Override
+ @NotNull
+ public String[] getAllClassNames() {
+ Merger<String> merger = new Merger<String>();
+ for (PsiShortNamesCache cache : myCaches) {
+ String[] names = cache.getAllClassNames();
+ merger.add(names);
+ }
+ String[] result = merger.getResult();
+ return result != null ? result : ArrayUtil.EMPTY_STRING_ARRAY;
+ }
+
+ @Override
+ public void getAllClassNames(@NotNull HashSet<String> dest) {
+ for (PsiShortNamesCache cache : myCaches) {
+ cache.getAllClassNames(dest);
+ }
+ }
+
+ @Override
+ @NotNull
+ public PsiMethod[] getMethodsByName(@NotNull String name, @NotNull GlobalSearchScope scope) {
+ Merger<PsiMethod> merger = null;
+ for (PsiShortNamesCache cache : myCaches) {
+ PsiMethod[] methods = cache.getMethodsByName(name, scope);
+ if (methods.length != 0) {
+ if (merger == null) merger = new Merger<PsiMethod>();
+ merger.add(methods);
+ }
+ }
+ PsiMethod[] result = merger == null ? null : merger.getResult();
+ return result == null ? PsiMethod.EMPTY_ARRAY : result;
+ }
+
+ @Override
+ @NotNull
+ public PsiMethod[] getMethodsByNameIfNotMoreThan(@NonNls @NotNull final String name, @NotNull final GlobalSearchScope scope, final int maxCount) {
+ Merger<PsiMethod> merger = null;
+ for (PsiShortNamesCache cache : myCaches) {
+ PsiMethod[] methods = cache.getMethodsByNameIfNotMoreThan(name, scope, maxCount);
+ if (methods.length == maxCount) return methods;
+ if (methods.length != 0) {
+ if (merger == null) merger = new Merger<PsiMethod>();
+ merger.add(methods);
+ }
+ }
+ PsiMethod[] result = merger == null ? null : merger.getResult();
+ return result == null ? PsiMethod.EMPTY_ARRAY : result;
+ }
+
+ @NotNull
+ @Override
+ public PsiField[] getFieldsByNameIfNotMoreThan(@NonNls @NotNull String name, @NotNull GlobalSearchScope scope, int maxCount) {
+ Merger<PsiField> merger = null;
+ for (PsiShortNamesCache cache : myCaches) {
+ PsiField[] fields = cache.getFieldsByNameIfNotMoreThan(name, scope, maxCount);
+ if (fields.length == maxCount) return fields;
+ if (fields.length != 0) {
+ if (merger == null) merger = new Merger<PsiField>();
+ merger.add(fields);
+ }
+ }
+ PsiField[] result = merger == null ? null : merger.getResult();
+ return result == null ? PsiField.EMPTY_ARRAY : result;
+ }
+
+ @Override
+ public boolean processMethodsWithName(@NonNls @NotNull String name,
+ @NotNull GlobalSearchScope scope,
+ @NotNull Processor<PsiMethod> processor) {
+ for (PsiShortNamesCache cache : myCaches) {
+ if (!cache.processMethodsWithName(name, scope, processor)) return false;
+ }
+ return true;
+ }
+
+ @Override
+ @NotNull
+ public String[] getAllMethodNames() {
+ Merger<String> merger = new Merger<String>();
+ for (PsiShortNamesCache cache : myCaches) {
+ merger.add(cache.getAllMethodNames());
+ }
+ String[] result = merger.getResult();
+ return result != null ? result : ArrayUtil.EMPTY_STRING_ARRAY;
+ }
+
+ @Override
+ public void getAllMethodNames(@NotNull HashSet<String> set) {
+ for (PsiShortNamesCache cache : myCaches) {
+ cache.getAllMethodNames(set);
+ }
+ }
+
+ @Override
+ @NotNull
+ public PsiField[] getFieldsByName(@NotNull String name, @NotNull GlobalSearchScope scope) {
+ Merger<PsiField> merger = null;
+ for (PsiShortNamesCache cache : myCaches) {
+ PsiField[] classes = cache.getFieldsByName(name, scope);
+ if (classes.length != 0) {
+ if (merger == null) merger = new Merger<PsiField>();
+ merger.add(classes);
+ }
+ }
+ PsiField[] result = merger == null ? null : merger.getResult();
+ return result == null ? PsiField.EMPTY_ARRAY : result;
+ }
+
+ @Override
+ @NotNull
+ public String[] getAllFieldNames() {
+ Merger<String> merger = null;
+ for (PsiShortNamesCache cache : myCaches) {
+ String[] classes = cache.getAllFieldNames();
+ if (classes.length != 0) {
+ if (merger == null) merger = new Merger<String>();
+ merger.add(classes);
+ }
+ }
+ String[] result = merger == null ? null : merger.getResult();
+ return result == null ? ArrayUtil.EMPTY_STRING_ARRAY : result;
+ }
+
+ @Override
+ public void getAllFieldNames(@NotNull HashSet<String> set) {
+ for (PsiShortNamesCache cache : myCaches) {
+ cache.getAllFieldNames(set);
+ }
+ }
+
+ private static class Merger<T> {
+ private T[] mySingleItem;
+ private Set<T> myAllItems;
+
+ public void add(@NotNull T[] items) {
+ if (items.length == 0) return;
+ if (mySingleItem == null) {
+ mySingleItem = items;
+ return;
+ }
+ if (myAllItems == null) {
+ T[] elements = mySingleItem;
+ myAllItems = ContainerUtil.addAll(new THashSet<T>(elements.length), elements);
+ }
+ ContainerUtil.addAll(myAllItems, items);
+ }
+
+ public T[] getResult() {
+ if (myAllItems == null) return mySingleItem;
+ return myAllItems.toArray(mySingleItem);
+ }
+ }
+
+ @SuppressWarnings({"HardCodedStringLiteral"})
+ @Override
+ public String toString() {
+ return "Composite cache: " + Arrays.asList(myCaches);
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java b/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java
new file mode 100644
index 0000000..215c9eb
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java
@@ -0,0 +1,237 @@
+/*
+ * 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.impl;
+
+import com.intellij.openapi.progress.ProgressIndicatorProvider;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.java.stubs.index.JavaFieldNameIndex;
+import com.intellij.psi.impl.java.stubs.index.JavaMethodNameIndex;
+import com.intellij.psi.impl.java.stubs.index.JavaShortClassNameIndex;
+import com.intellij.psi.impl.java.stubs.index.JavaStubIndexKeys;
+import com.intellij.psi.impl.search.JavaSourceFilterScope;
+import com.intellij.psi.search.FilenameIndex;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.PsiShortNamesCache;
+import com.intellij.psi.stubs.StubIndex;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.CommonProcessors;
+import com.intellij.util.Processor;
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.HashSet;
+import gnu.trove.THashSet;
+import gnu.trove.TObjectHashingStrategy;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+public class PsiShortNamesCacheImpl extends PsiShortNamesCache {
+ private final PsiManagerEx myManager;
+
+ public PsiShortNamesCacheImpl(PsiManagerEx manager) {
+ myManager = manager;
+ }
+
+ @Override
+ @NotNull
+ public PsiFile[] getFilesByName(@NotNull String name) {
+ return FilenameIndex.getFilesByName(myManager.getProject(), name, GlobalSearchScope.projectScope(myManager.getProject()));
+ }
+
+ @Override
+ @NotNull
+ public String[] getAllFileNames() {
+ return FilenameIndex.getAllFilenames(myManager.getProject());
+ }
+
+ @Override
+ @NotNull
+ public PsiClass[] getClassesByName(@NotNull String name, @NotNull final GlobalSearchScope scope) {
+ final Collection<PsiClass> classes = JavaShortClassNameIndex.getInstance().get(name, myManager.getProject(), scope);
+
+ if (classes.isEmpty()) return PsiClass.EMPTY_ARRAY;
+ ArrayList<PsiClass> list = new ArrayList<PsiClass>(classes.size());
+
+ OuterLoop:
+ for (PsiClass aClass : classes) {
+ VirtualFile vFile = aClass.getContainingFile().getVirtualFile();
+ if (!scope.contains(vFile)) continue;
+
+ for (int j = 0; j < list.size(); j++) {
+ PsiClass aClass1 = list.get(j);
+
+ String qName = aClass.getQualifiedName();
+ String qName1 = aClass1.getQualifiedName();
+ if (qName != null && qName1 != null && qName.equals(qName1)) {
+ VirtualFile vFile1 = aClass1.getContainingFile().getVirtualFile();
+ int res = scope.compare(vFile1, vFile);
+ if (res > 0) {
+ continue OuterLoop; // aClass1 hides aClass
+ }
+ else if (res < 0) {
+ list.remove(j);
+ //noinspection AssignmentToForLoopParameter
+ j--; // aClass hides aClass1
+ }
+ }
+ }
+
+ list.add(aClass);
+ }
+ return list.toArray(new PsiClass[list.size()]);
+ }
+
+ @Override
+ @NotNull
+ public String[] getAllClassNames() {
+ final Collection<String> names = JavaShortClassNameIndex.getInstance().getAllKeys(myManager.getProject());
+ return ArrayUtil.toStringArray(names);
+ }
+
+ @Override
+ public void getAllClassNames(@NotNull HashSet<String> set) {
+ set.addAll(JavaShortClassNameIndex.getInstance().getAllKeys(myManager.getProject()));
+ }
+
+ @Override
+ @NotNull
+ public PsiMethod[] getMethodsByName(@NotNull String name, @NotNull final GlobalSearchScope scope) {
+ Collection<PsiMethod> methods = StubIndex.getInstance().get(JavaStubIndexKeys.METHODS, name, myManager.getProject(), new JavaSourceFilterScope(scope));
+ if (methods.isEmpty()) return PsiMethod.EMPTY_ARRAY;
+
+ List<PsiMethod> list = filterMembers(methods, scope);
+ return list.toArray(new PsiMethod[list.size()]);
+ }
+
+
+ @Override
+ @NotNull
+ public PsiMethod[] getMethodsByNameIfNotMoreThan(@NonNls @NotNull final String name, @NotNull final GlobalSearchScope scope, final int maxCount) {
+ final List<PsiMethod> methods = new SmartList<PsiMethod>();
+ StubIndex.getInstance().process(JavaStubIndexKeys.METHODS, name, myManager.getProject(), scope, new CommonProcessors.CollectProcessor<PsiMethod>(methods){
+ @Override
+ public boolean process(PsiMethod method) {
+ return methods.size() != maxCount && super.process(method);
+ }
+ });
+ if (methods.isEmpty()) return PsiMethod.EMPTY_ARRAY;
+
+ List<PsiMethod> list = filterMembers(methods, scope);
+ return list.toArray(new PsiMethod[list.size()]);
+ }
+
+ @Override
+ public boolean processMethodsWithName(@NonNls @NotNull String name,
+ @NotNull GlobalSearchScope scope,
+ @NotNull Processor<PsiMethod> processor) {
+ return StubIndex.getInstance().process(JavaStubIndexKeys.METHODS, name, myManager.getProject(), scope, processor);
+ }
+
+ @Override
+ @NotNull
+ public String[] getAllMethodNames() {
+ final Collection<String> names = JavaMethodNameIndex.getInstance().getAllKeys(myManager.getProject());
+ return ArrayUtil.toStringArray(names);
+ }
+
+ @Override
+ public void getAllMethodNames(@NotNull HashSet<String> set) {
+ set.addAll(JavaMethodNameIndex.getInstance().getAllKeys(myManager.getProject()));
+ }
+
+ @Override
+ @NotNull
+ public PsiField[] getFieldsByNameIfNotMoreThan(@NotNull String name, @NotNull final GlobalSearchScope scope, final int maxCount) {
+ final List<PsiField> methods = new SmartList<PsiField>();
+ StubIndex.getInstance().process(JavaStubIndexKeys.FIELDS, name, myManager.getProject(), scope, new CommonProcessors.CollectProcessor<PsiField>(methods){
+ @Override
+ public boolean process(PsiField method) {
+ return methods.size() != maxCount && super.process(method);
+ }
+ });
+ if (methods.isEmpty()) return PsiField.EMPTY_ARRAY;
+
+ List<PsiField> list = filterMembers(methods, scope);
+ return list.toArray(new PsiField[list.size()]);
+ }
+
+ @NotNull
+ @Override
+ public PsiField[] getFieldsByName(@NotNull String name, @NotNull final GlobalSearchScope scope) {
+ final Collection<PsiField> fields = JavaFieldNameIndex.getInstance().get(name, myManager.getProject(), scope);
+
+ if (fields.isEmpty()) return PsiField.EMPTY_ARRAY;
+
+ List<PsiField> list = filterMembers(fields, scope);
+ return list.toArray(new PsiField[list.size()]);
+ }
+
+ @Override
+ @NotNull
+ public String[] getAllFieldNames() {
+ final Collection<String> names = JavaFieldNameIndex.getInstance().getAllKeys(myManager.getProject());
+ return ArrayUtil.toStringArray(names);
+ }
+
+ @Override
+ public void getAllFieldNames(@NotNull HashSet<String> set) {
+ set.addAll(JavaFieldNameIndex.getInstance().getAllKeys(myManager.getProject()));
+ }
+
+ private <T extends PsiMember> List<T> filterMembers(Collection<T> members, final GlobalSearchScope scope) {
+ List<T> result = new ArrayList<T>(members.size());
+ Set<PsiMember> set = new THashSet<PsiMember>(members.size(), new TObjectHashingStrategy<PsiMember>() {
+ @Override
+ public int computeHashCode(PsiMember member) {
+ int code = 0;
+ final PsiClass clazz = member.getContainingClass();
+ if (clazz != null) {
+ String name = clazz.getName();
+ if (name != null) {
+ code += name.hashCode();
+ }
+ else {
+ //anonymous classes are not equivalent
+ code += clazz.hashCode();
+ }
+ }
+ if (member instanceof PsiMethod) {
+ code += 37 * ((PsiMethod)member).getParameterList().getParametersCount();
+ }
+ return code;
+ }
+
+ @Override
+ public boolean equals(PsiMember object, PsiMember object1) {
+ return myManager.areElementsEquivalent(object, object1);
+ }
+ });
+
+ for (T member : members) {
+ ProgressIndicatorProvider.checkCanceled();
+
+ if (!scope.contains(member.getContainingFile().getVirtualFile())) continue;
+ if (!set.add(member)) continue;
+ result.add(member);
+ }
+
+ return result;
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java b/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java
new file mode 100644
index 0000000..d559187
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java
@@ -0,0 +1,382 @@
+/*
+ * 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.impl.file.impl;
+
+import com.intellij.ProjectTopics;
+import com.intellij.ide.highlighter.JavaClassFileType;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.roots.*;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.openapi.vfs.VirtualFileWithId;
+import com.intellij.openapi.vfs.newvfs.BulkFileListener;
+import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiManagerEx;
+import com.intellij.psi.impl.file.PsiPackageImpl;
+import com.intellij.psi.impl.java.stubs.index.JavaFullClassNameIndex;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.util.Query;
+import com.intellij.util.containers.ConcurrentHashMap;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.indexing.FileBasedIndex;
+import com.intellij.util.messages.MessageBus;
+import com.intellij.util.messages.MessageBusConnection;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * Author: dmitrylomov
+ */
+public abstract class JavaFileManagerBase implements JavaFileManager, Disposable {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.file.impl.JavaFileManagerImpl");
+ @NonNls private static final String JAVA_EXTENSION = ".java";
+ @NonNls private static final String CLASS_EXTENSION = ".class";
+ private final ConcurrentHashMap<GlobalSearchScope, PsiClass> myCachedObjectClassMap = new ConcurrentHashMap<GlobalSearchScope, PsiClass>();
+ private final Map<String,PsiClass> myNameToClassMap = new ConcurrentHashMap<String, PsiClass>(); // used only in mode without repository
+ private final PsiManagerEx myManager;
+ private final ProjectRootManager myProjectRootManager;
+ private final FileManager myFileManager;
+ private final boolean myUseRepository;
+ private Set<String> myNontrivialPackagePrefixes = null;
+ private boolean myInitialized = false;
+ private boolean myDisposed = false;
+ private final PackageIndex myPackageIndex;
+ protected final MessageBusConnection myConnection;
+
+ public JavaFileManagerBase(
+ final PsiManagerEx manager, final ProjectRootManager projectRootManager,
+ final MessageBus bus) {
+ myManager = manager;
+ myFileManager = manager.getFileManager();
+ myProjectRootManager = projectRootManager;
+ myUseRepository = true;
+ myPackageIndex = PackageIndex.getInstance(myManager.getProject());
+ myConnection = bus.connect();
+ myConnection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
+ @Override
+ public void rootsChanged(final ModuleRootEvent event) {
+ myNontrivialPackagePrefixes = null;
+ clearNonRepositoryMaps();
+ }
+ });
+
+ myConnection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
+ @Override
+ public void before(@NotNull final List<? extends VFileEvent> events) {
+ clearNonRepositoryMaps();
+ }
+
+ @Override
+ public void after(@NotNull final List<? extends VFileEvent> events) {
+ clearNonRepositoryMaps();
+ }
+ });
+
+ myManager.registerRunnableToRunOnChange(new Runnable() {
+ @Override
+ public void run() {
+ myCachedObjectClassMap.clear();
+ }
+ });
+
+ Disposer.register(myManager.getProject(), this);
+ }
+
+ @Override
+ public void initialize() {
+ myInitialized = true;
+ }
+
+ @Override
+ public void dispose() {
+ myDisposed = true;
+ myCachedObjectClassMap.clear();
+ }
+
+ protected void clearNonRepositoryMaps() {
+ if (!myUseRepository) {
+ myNameToClassMap.clear();
+ }
+ }
+
+ @Override
+ @Nullable
+ public PsiPackage findPackage(@NotNull String packageName) {
+ Query<VirtualFile> dirs = myPackageIndex.getDirsByPackageName(packageName, false);
+ if (dirs.findFirst() == null) return null;
+ return new PsiPackageImpl(myManager, packageName);
+ }
+
+ @Override
+ public PsiClass[] findClasses(@NotNull String qName, @NotNull final GlobalSearchScope scope) {
+ final Collection<? extends PsiElement> classes = JavaFullClassNameIndex.getInstance().get(qName.hashCode(), myManager.getProject(), scope);
+ if (classes.isEmpty()) return PsiClass.EMPTY_ARRAY;
+ List<PsiClass> result = new ArrayList<PsiClass>(classes.size());
+ int count = 0;
+ PsiClass aClass = null;
+ for (PsiElement found : classes) {
+ if (notClass(found)) continue;
+
+ aClass = (PsiClass)found;
+ final String qualifiedName = aClass.getQualifiedName();
+ if (qualifiedName == null || !qualifiedName.equals(qName)) continue;
+
+ VirtualFile vFile = aClass.getContainingFile().getVirtualFile();
+ if (!hasAcceptablePackage(vFile)) continue;
+
+ result.add(aClass);
+ count++;
+ }
+
+ if (count == 0) return PsiClass.EMPTY_ARRAY;
+ if (count == 1) return new PsiClass[] {aClass};
+
+ ContainerUtil.quickSort(result, new Comparator<PsiClass>() {
+ @Override
+ public int compare(PsiClass o1, PsiClass o2) {
+ return scope.compare(o2.getContainingFile().getVirtualFile(), o1.getContainingFile().getVirtualFile());
+ }
+ });
+
+ return result.toArray(new PsiClass[count]);
+ }
+
+ @Override
+ @Nullable
+ public PsiClass findClass(@NotNull String qName, @NotNull GlobalSearchScope scope) {
+ if (!myUseRepository) {
+ return findClassWithoutRepository(qName);
+ }
+
+ if (!myInitialized) {
+ LOG.error("Access to psi files should be performed only after startup activity");
+ return null;
+ }
+ LOG.assertTrue(!myDisposed);
+
+ if (CommonClassNames.JAVA_LANG_OBJECT.equals(qName)) { // optimization
+ PsiClass cached = myCachedObjectClassMap.get(scope);
+ if (cached == null) {
+ cached = findClassInIndex(qName, scope);
+ if (cached != null) {
+ cached = myCachedObjectClassMap.cacheOrGet(scope, cached);
+ }
+ }
+
+ return cached;
+ }
+
+ return findClassInIndex(qName, scope);
+ }
+
+ @Nullable
+ private PsiClass findClassWithoutRepository(String qName) {
+ PsiClass aClass = myNameToClassMap.get(qName);
+ if (aClass != null) {
+ return aClass;
+ }
+
+ aClass = _findClassWithoutRepository(qName);
+ myNameToClassMap.put(qName, aClass);
+ return aClass;
+ }
+
+ @Nullable
+ private PsiClass _findClassWithoutRepository(String qName) {
+ VirtualFile[] sourcePath = myProjectRootManager.orderEntries().sources().usingCache().getRoots();
+ VirtualFile[] classPath = myProjectRootManager.orderEntries().withoutModuleSourceEntries().classes().usingCache().getRoots();
+
+ int index = 0;
+ while (index < qName.length()) {
+ int index1 = qName.indexOf('.', index);
+ if (index1 < 0) {
+ index1 = qName.length();
+ }
+ String name = qName.substring(index, index1);
+
+ final int sourceType = 0;
+ //final int compiledType = 1;
+
+ for (int type = 0; type < 2; type++) {
+ VirtualFile[] vDirs = type == sourceType ? sourcePath : classPath;
+ for (VirtualFile vDir : vDirs) {
+ if (vDir != null) {
+ VirtualFile vChild = type == sourceType
+ ? vDir.findChild(name + JAVA_EXTENSION)
+ : vDir.findChild(name + CLASS_EXTENSION);
+ if (vChild != null) {
+ PsiFile file = myFileManager.findFile(vChild);
+ if (file instanceof PsiJavaFile) {
+ PsiClass aClass = findClassByName((PsiJavaFile)file, name);
+ if (aClass != null) {
+ index = index1 + 1;
+ while (index < qName.length()) {
+ index1 = qName.indexOf('.', index);
+ if (index1 < 0) {
+ index1 = qName.length();
+ }
+ name = qName.substring(index, index1);
+ aClass = findClassByName(aClass, name);
+ if (aClass == null) return null;
+ index = index1 + 1;
+ }
+ return aClass;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ boolean existsDir = false;
+ for (int type = 0; type < 2; type++) {
+ VirtualFile[] vDirs = type == sourceType ? sourcePath : classPath;
+ for (int i = 0; i < vDirs.length; i++) {
+ if (vDirs[i] != null) {
+ VirtualFile vDirChild = vDirs[i].findChild(name);
+ if (vDirChild != null) {
+ PsiDirectory dir = myFileManager.findDirectory(vDirChild);
+ if (dir != null) {
+ vDirs[i] = vDirChild;
+ existsDir = true;
+ continue;
+ }
+ }
+ vDirs[i] = null;
+ }
+ }
+ }
+ if (!existsDir) return null;
+ index = index1 + 1;
+ }
+ return null;
+ }
+
+ @Nullable
+ private PsiClass findClassInIndex(String qName, GlobalSearchScope scope) {
+ VirtualFile bestFile = null;
+ PsiClass bestClass = null;
+ final Collection<? extends PsiElement> classes = JavaFullClassNameIndex.getInstance().get(qName.hashCode(), myManager.getProject(), scope);
+
+ for (PsiElement found : classes) {
+ if (notClass(found)) continue;
+
+ PsiClass aClass = (PsiClass)found;
+ PsiFile file = aClass.getContainingFile();
+ if (file == null) {
+ LOG.error("aClass=" + aClass);
+ continue;
+ }
+ final boolean valid = aClass.isValid();
+ VirtualFile vFile = file.getVirtualFile();
+ if (!valid) {
+ LOG.error("Invalid class " + aClass + "; " +
+ file + (file.isValid() ? "" : " (invalid)") +
+ "; virtualFile:" + vFile +
+ (vFile != null && !vFile.isValid() ? " (invalid)" : "") +
+ "; id=" + (vFile == null ? 0 : ((VirtualFileWithId)vFile).getId()),
+ new PsiInvalidElementAccessException(aClass));
+ continue;
+ }
+
+ final String qualifiedName = aClass.getQualifiedName();
+ if (qualifiedName == null || !qualifiedName.equals(qName)) continue;
+
+
+ if (!hasAcceptablePackage(vFile)) continue;
+ if (bestFile == null || scope.compare(vFile, bestFile) > 0) {
+ bestFile = vFile;
+ bestClass = aClass;
+ }
+ }
+ return bestClass;
+ }
+
+ private boolean hasAcceptablePackage(final VirtualFile vFile) {
+ if (vFile.getFileType() == JavaClassFileType.INSTANCE) {
+ // See IDEADEV-5626
+ final VirtualFile root = ProjectRootManager.getInstance(myManager.getProject()).getFileIndex().getClassRootForFile(vFile);
+ VirtualFile parent = vFile.getParent();
+ final PsiNameHelper nameHelper = JavaPsiFacade.getInstance(myManager.getProject()).getNameHelper();
+ while (parent != null && !Comparing.equal(parent, root)) {
+ if (!nameHelper.isIdentifier(parent.getName())) return false;
+ parent = parent.getParent();
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public Collection<String> getNonTrivialPackagePrefixes() {
+ if (myNontrivialPackagePrefixes == null) {
+ Set<String> names = new HashSet<String>();
+ final ProjectRootManager rootManager = myProjectRootManager;
+ final VirtualFile[] sourceRoots = rootManager.getContentSourceRoots();
+ final ProjectFileIndex fileIndex = rootManager.getFileIndex();
+ for (final VirtualFile sourceRoot : sourceRoots) {
+ final String packageName = fileIndex.getPackageNameByDirectory(sourceRoot);
+ if (packageName != null && !packageName.isEmpty()) {
+ names.add(packageName);
+ }
+ }
+ myNontrivialPackagePrefixes = names;
+ }
+ return myNontrivialPackagePrefixes;
+ }
+
+ private static boolean notClass(final PsiElement found) {
+ if (found instanceof PsiClass) return false;
+
+ VirtualFile faultyContainer = PsiUtilCore.getVirtualFile(found);
+ LOG.error("Non class in class list: " + faultyContainer + ". found: " + found);
+ if (faultyContainer != null && faultyContainer.isValid()) {
+ FileBasedIndex.getInstance().requestReindex(faultyContainer);
+ }
+
+ return true;
+ }
+
+ @Nullable
+ private static PsiClass findClassByName(PsiJavaFile scope, String name) {
+ PsiClass[] classes = scope.getClasses();
+ for (PsiClass aClass : classes) {
+ if (name.equals(aClass.getName())) {
+ return aClass;
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private static PsiClass findClassByName(PsiClass scope, String name) {
+ PsiClass[] classes = scope.getInnerClasses();
+ for (PsiClass aClass : classes) {
+ if (name.equals(aClass.getName())) {
+ return aClass;
+ }
+ }
+ return null;
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnnotationIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnnotationIndex.java
new file mode 100644
index 0000000..fbf4508
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnnotationIndex.java
@@ -0,0 +1,49 @@
+/*
+ * 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.impl.java.stubs.index;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiAnnotation;
+import com.intellij.psi.impl.search.JavaSourceFilterScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndexKey;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+public class JavaAnnotationIndex extends StringStubIndexExtension<PsiAnnotation> {
+
+ private static final JavaAnnotationIndex ourInstance = new JavaAnnotationIndex();
+ public static JavaAnnotationIndex getInstance() {
+ return ourInstance;
+ }
+
+ @NotNull
+ @Override
+ public StubIndexKey<String, PsiAnnotation> getKey() {
+ return JavaStubIndexKeys.ANNOTATIONS;
+ }
+
+ @Override
+ public Collection<PsiAnnotation> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
+ return super.get(s, project, new JavaSourceFilterScope(scope));
+ }
+}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnonymousClassBaseRefOccurenceIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnonymousClassBaseRefOccurenceIndex.java
new file mode 100644
index 0000000..2521522
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnonymousClassBaseRefOccurenceIndex.java
@@ -0,0 +1,50 @@
+/*
+ * 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.impl.java.stubs.index;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiAnonymousClass;
+import com.intellij.psi.impl.search.JavaSourceFilterScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndexKey;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+public class JavaAnonymousClassBaseRefOccurenceIndex extends StringStubIndexExtension<PsiAnonymousClass> {
+
+ private static final JavaAnonymousClassBaseRefOccurenceIndex ourInstance = new JavaAnonymousClassBaseRefOccurenceIndex();
+ public static JavaAnonymousClassBaseRefOccurenceIndex getInstance() {
+ return ourInstance;
+ }
+
+
+ @NotNull
+ @Override
+ public StubIndexKey<String, PsiAnonymousClass> getKey() {
+ return JavaStubIndexKeys.ANONYMOUS_BASEREF;
+ }
+
+ @Override
+ public Collection<PsiAnonymousClass> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
+ return super.get(s, project, new JavaSourceFilterScope(scope));
+ }
+}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java
new file mode 100644
index 0000000..54eb0ed
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java
@@ -0,0 +1,49 @@
+/*
+ * 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.impl.java.stubs.index;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiField;
+import com.intellij.psi.impl.search.JavaSourceFilterScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndexKey;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+public class JavaFieldNameIndex extends StringStubIndexExtension<PsiField> {
+
+ private static final JavaFieldNameIndex ourInstance = new JavaFieldNameIndex();
+ public static JavaFieldNameIndex getInstance() {
+ return ourInstance;
+ }
+
+ @NotNull
+ @Override
+ public StubIndexKey<String, PsiField> getKey() {
+ return JavaStubIndexKeys.FIELDS;
+ }
+
+ @Override
+ public Collection<PsiField> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
+ return super.get(s, project, new JavaSourceFilterScope(scope));
+ }
+}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFullClassNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFullClassNameIndex.java
new file mode 100644
index 0000000..40c75f3
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFullClassNameIndex.java
@@ -0,0 +1,49 @@
+/*
+ * 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.impl.java.stubs.index;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.impl.search.JavaSourceFilterScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.stubs.IntStubIndexExtension;
+import com.intellij.psi.stubs.StubIndexKey;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+public class JavaFullClassNameIndex extends IntStubIndexExtension<PsiClass> {
+
+ private static final JavaFullClassNameIndex ourInstance = new JavaFullClassNameIndex();
+ public static JavaFullClassNameIndex getInstance() {
+ return ourInstance;
+ }
+
+ @NotNull
+ @Override
+ public StubIndexKey<Integer, PsiClass> getKey() {
+ return JavaStubIndexKeys.CLASS_FQN;
+ }
+
+ @Override
+ public Collection<PsiClass> get(final Integer integer, final Project project, @NotNull final GlobalSearchScope scope) {
+ return super.get(integer, project, new JavaSourceFilterScope(scope));
+ }
+}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java
new file mode 100644
index 0000000..a92856f
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java
@@ -0,0 +1,49 @@
+/*
+ * 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.impl.java.stubs.index;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.impl.search.JavaSourceFilterScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndexKey;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+public class JavaMethodNameIndex extends StringStubIndexExtension<PsiMethod> {
+
+ private static final JavaMethodNameIndex ourInstance = new JavaMethodNameIndex();
+ public static JavaMethodNameIndex getInstance() {
+ return ourInstance;
+ }
+
+ @NotNull
+ @Override
+ public StubIndexKey<String, PsiMethod> getKey() {
+ return JavaStubIndexKeys.METHODS;
+ }
+
+ @Override
+ public Collection<PsiMethod> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
+ return super.get(s, project, new JavaSourceFilterScope(scope));
+ }
+}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java
new file mode 100644
index 0000000..5cd6454
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java
@@ -0,0 +1,49 @@
+/*
+ * 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.impl.java.stubs.index;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.impl.search.JavaSourceFilterScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndexKey;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+public class JavaShortClassNameIndex extends StringStubIndexExtension<PsiClass> {
+
+ private static final JavaShortClassNameIndex ourInstance = new JavaShortClassNameIndex();
+ public static JavaShortClassNameIndex getInstance() {
+ return ourInstance;
+ }
+
+ @NotNull
+ @Override
+ public StubIndexKey<String, PsiClass> getKey() {
+ return JavaStubIndexKeys.CLASS_SHORT_NAMES;
+ }
+
+ @Override
+ public Collection<PsiClass> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
+ return super.get(s, project, new JavaSourceFilterScope(scope));
+ }
+}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberNameIndex.java
new file mode 100644
index 0000000..3cb51d9
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberNameIndex.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.psi.impl.java.stubs.index;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiMember;
+import com.intellij.psi.impl.search.JavaSourceFilterScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndexKey;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+public class JavaStaticMemberNameIndex extends StringStubIndexExtension<PsiMember> {
+
+ private static final JavaStaticMemberNameIndex ourInstance = new JavaStaticMemberNameIndex();
+ public static JavaStaticMemberNameIndex getInstance() {
+ return ourInstance;
+ }
+
+ @NotNull
+ @Override
+ public StubIndexKey<String, PsiMember> getKey() {
+ return JavaStubIndexKeys.JVM_STATIC_MEMBERS_NAMES;
+ }
+
+ public Collection<PsiMember> getStaticMembers(final String name, final Project project, @NotNull final GlobalSearchScope scope) {
+ return super.get(name, project, new JavaSourceFilterScope(scope));
+ }
+}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberTypeIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberTypeIndex.java
new file mode 100644
index 0000000..3898c73
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberTypeIndex.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.psi.impl.java.stubs.index;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiMember;
+import com.intellij.psi.impl.search.JavaSourceFilterScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndexKey;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+public class JavaStaticMemberTypeIndex extends StringStubIndexExtension<PsiMember> {
+
+ private static final JavaStaticMemberTypeIndex ourInstance = new JavaStaticMemberTypeIndex();
+ public static JavaStaticMemberTypeIndex getInstance() {
+ return ourInstance;
+ }
+
+ @NotNull
+ @Override
+ public StubIndexKey<String, PsiMember> getKey() {
+ return JavaStubIndexKeys.JVM_STATIC_MEMBERS_TYPES;
+ }
+
+ public Collection<PsiMember> getStaticMembers(@NotNull final String shortTypeText, final Project project, @NotNull final GlobalSearchScope scope) {
+ return super.get(shortTypeText, project, new JavaSourceFilterScope(scope));
+ }
+}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaSuperClassNameOccurenceIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaSuperClassNameOccurenceIndex.java
new file mode 100644
index 0000000..a70b7ea
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaSuperClassNameOccurenceIndex.java
@@ -0,0 +1,55 @@
+/*
+ * 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.impl.java.stubs.index;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiReferenceList;
+import com.intellij.psi.impl.search.JavaSourceFilterScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndexKey;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+public class JavaSuperClassNameOccurenceIndex extends StringStubIndexExtension<PsiReferenceList> {
+ private static final int VERSION = 1;
+
+ private static final JavaSuperClassNameOccurenceIndex ourInstance = new JavaSuperClassNameOccurenceIndex();
+ public static JavaSuperClassNameOccurenceIndex getInstance() {
+ return ourInstance;
+ }
+
+ @NotNull
+ @Override
+ public StubIndexKey<String, PsiReferenceList> getKey() {
+ return JavaStubIndexKeys.SUPER_CLASSES;
+ }
+
+ @Override
+ public Collection<PsiReferenceList> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
+ return super.get(s, project, new JavaSourceFilterScope(scope));
+ }
+
+ @Override
+ public int getVersion() {
+ return super.getVersion() + VERSION;
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java
new file mode 100644
index 0000000..bae6155
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java
@@ -0,0 +1,134 @@
+/*
+ * 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.impl.search;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressIndicatorProvider;
+import com.intellij.openapi.util.Computable;
+import com.intellij.psi.JavaRecursiveElementWalkingVisitor;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.LocalSearchScope;
+import com.intellij.psi.search.PsiShortNamesCache;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.searches.AllClassesSearch;
+import com.intellij.util.Processor;
+import com.intellij.util.QueryExecutor;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class AllClassesSearchExecutor implements QueryExecutor<PsiClass, AllClassesSearch.SearchParameters> {
+ @Override
+ public boolean execute(@NotNull final AllClassesSearch.SearchParameters queryParameters, @NotNull final Processor<PsiClass> consumer) {
+ SearchScope scope = queryParameters.getScope();
+
+ if (scope instanceof GlobalSearchScope) {
+ return processAllClassesInGlobalScope((GlobalSearchScope)scope, consumer, queryParameters);
+ }
+
+ PsiElement[] scopeRoots = ((LocalSearchScope)scope).getScope();
+ for (final PsiElement scopeRoot : scopeRoots) {
+ if (!processScopeRootForAllClasses(scopeRoot, consumer)) return false;
+ }
+ return true;
+ }
+
+ private static boolean processAllClassesInGlobalScope(final GlobalSearchScope scope, final Processor<PsiClass> processor, AllClassesSearch.SearchParameters parameters) {
+ final PsiShortNamesCache cache = PsiShortNamesCache.getInstance(parameters.getProject());
+
+ final String[] names = ApplicationManager.getApplication().runReadAction(new Computable<String[]>() {
+ @Override
+ public String[] compute() {
+ return cache.getAllClassNames();
+ }
+ });
+
+ final ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator();
+ if (indicator != null) {
+ indicator.checkCanceled();
+ }
+
+ List<String> sorted = new ArrayList<String>(names.length);
+ for (int i = 0; i < names.length; i++) {
+ String name = names[i];
+ if (parameters.nameMatches(name)) {
+ sorted.add(name);
+ }
+ if (indicator != null && i % 512 == 0) {
+ indicator.checkCanceled();
+ }
+ }
+
+ if (indicator != null) {
+ indicator.checkCanceled();
+ }
+
+ Collections.sort(sorted, new Comparator<String>() {
+ @Override
+ public int compare(final String o1, final String o2) {
+ return o1.compareToIgnoreCase(o2);
+ }
+ });
+
+ for (final String name : sorted) {
+ ProgressIndicatorProvider.checkCanceled();
+ final PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass[]>() {
+ @Override
+ public PsiClass[] compute() {
+ return cache.getClassesByName(name, scope);
+ }
+ });
+ for (PsiClass psiClass : classes) {
+ ProgressIndicatorProvider.checkCanceled();
+ if (!processor.process(psiClass)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static boolean processScopeRootForAllClasses(PsiElement scopeRoot, final Processor<PsiClass> processor) {
+ if (scopeRoot == null) return true;
+ final boolean[] stopped = new boolean[]{false};
+
+ scopeRoot.accept(new JavaRecursiveElementWalkingVisitor() {
+ @Override
+ public void visitElement(PsiElement element) {
+ if (!stopped[0]) {
+ super.visitElement(element);
+ }
+ }
+
+ @Override public void visitClass(PsiClass aClass) {
+ stopped[0] = !processor.process(aClass);
+ super.visitClass(aClass);
+ }
+ });
+
+ return !stopped[0];
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/AnnotatedElementsSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AnnotatedElementsSearcher.java
new file mode 100644
index 0000000..a4aa952
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AnnotatedElementsSearcher.java
@@ -0,0 +1,134 @@
+package com.intellij.psi.impl.search;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiManagerImpl;
+import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.LocalSearchScope;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.searches.AnnotatedElementsSearch;
+import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.util.Processor;
+import com.intellij.util.QueryExecutor;
+import com.intellij.util.indexing.FileBasedIndex;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author max
+ */
+public class AnnotatedElementsSearcher implements QueryExecutor<PsiModifierListOwner, AnnotatedElementsSearch.Parameters> {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.search.AnnotatedMembersSearcher");
+
+ @Override
+ public boolean execute(@NotNull final AnnotatedElementsSearch.Parameters p, @NotNull final Processor<PsiModifierListOwner> consumer) {
+ final PsiClass annClass = p.getAnnotationClass();
+ assert annClass.isAnnotationType() : "Annotation type should be passed to annotated members search";
+
+ final String annotationFQN = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+ @Override
+ public String compute() {
+ return annClass.getQualifiedName();
+ }
+ });
+ assert annotationFQN != null;
+
+ final PsiManagerImpl psiManager = (PsiManagerImpl)annClass.getManager();
+
+ final SearchScope useScope = p.getScope();
+ Class<? extends PsiModifierListOwner>[] types = p.getTypes();
+
+ for (PsiElement elt : getAnnotationCandidates(annClass, useScope)) {
+ if (notAnnotation(elt)) continue;
+
+ final PsiAnnotation ann = (PsiAnnotation)elt;
+ final PsiJavaCodeReferenceElement ref = ApplicationManager.getApplication().runReadAction(new Computable<PsiJavaCodeReferenceElement>() {
+ @Override
+ public PsiJavaCodeReferenceElement compute() {
+ return ann.getNameReferenceElement();
+ }
+ });
+ if (ref == null) continue;
+
+ PsiElement parent = ann.getParent();
+ if (!(parent instanceof PsiModifierList)) continue; // Can be a PsiNameValuePair, if annotation is used to annotate annotation parameters
+
+ final PsiElement owner = parent.getParent();
+
+ if (!isInstanceof(owner, types)) continue;
+
+ final PsiModifierListOwner candidate = (PsiModifierListOwner)owner;
+
+ if (!ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
+ @Override
+ public Boolean compute() {
+ if (!candidate.isValid()) {
+ return false;
+ }
+ if (!psiManager.areElementsEquivalent(ref.resolve(), annClass)) {
+ return false;
+ }
+ return !(useScope instanceof GlobalSearchScope) ||
+ ((GlobalSearchScope)useScope).contains(candidate.getContainingFile().getVirtualFile());
+ }
+ })) {
+ continue;
+ }
+
+ if (!consumer.process(candidate)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static Collection<? extends PsiElement> getAnnotationCandidates(final PsiClass annClass, final SearchScope useScope) {
+ return ApplicationManager.getApplication().runReadAction(new Computable<Collection<? extends PsiElement>>() {
+ @Override
+ public Collection<? extends PsiElement> compute() {
+ if (useScope instanceof GlobalSearchScope) {
+ return JavaAnnotationIndex.getInstance().get(annClass.getName(), annClass.getProject(), (GlobalSearchScope)useScope);
+ }
+ final List<PsiElement> result = new ArrayList<PsiElement>();
+ for (PsiElement element : ((LocalSearchScope)useScope).getScope()) {
+ element.accept(new PsiRecursiveElementWalkingVisitor() {
+ @Override
+ public void visitElement(PsiElement element) {
+ if (element instanceof PsiAnnotation) {
+ result.add(element);
+ }
+ }
+ });
+ }
+ return result;
+ }
+ });
+ }
+
+ public static boolean isInstanceof(PsiElement owner, Class<? extends PsiModifierListOwner>[] types) {
+ for (Class<? extends PsiModifierListOwner> type : types) {
+ if(type.isInstance(owner)) return true;
+ }
+ return false;
+ }
+
+ private static boolean notAnnotation(final PsiElement found) {
+ if (found instanceof PsiAnnotation) return false;
+
+ VirtualFile faultyContainer = PsiUtilCore.getVirtualFile(found);
+ LOG.error("Non annotation in annotations list: " + faultyContainer+"; element:"+found);
+ if (faultyContainer != null && faultyContainer.isValid()) {
+ FileBasedIndex.getInstance().requestReindex(faultyContainer);
+ }
+
+ return true;
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java
new file mode 100644
index 0000000..2aad613
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java
@@ -0,0 +1,193 @@
+package com.intellij.psi.impl.search;
+
+import com.intellij.openapi.util.TextRange;
+import com.intellij.pom.java.LanguageLevel;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.light.LightMemberReference;
+import com.intellij.psi.search.PsiSearchScopeUtil;
+import com.intellij.psi.search.SearchRequestCollector;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.searches.ClassInheritorsSearch;
+import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.PairProcessor;
+import com.intellij.util.Processor;
+
+/**
+ * @author max
+ */
+public class ConstructorReferencesSearchHelper {
+ private final PsiManager myManager;
+
+ public ConstructorReferencesSearchHelper(final PsiManager manager) {
+ myManager = manager;
+ }
+
+ public boolean processConstructorReferences(final Processor<PsiReference> processor,
+ final PsiMethod constructor,
+ final SearchScope searchScope,
+ boolean ignoreAccessScope,
+ final boolean isStrictSignatureSearch, SearchRequestCollector collector) {
+ PsiClass aClass = constructor.getContainingClass();
+ if (aClass == null) {
+ return true;
+ }
+
+ if (aClass.isEnum()) {
+ for (PsiField field : aClass.getFields()) {
+ if (field instanceof PsiEnumConstant) {
+ PsiReference reference = field.getReference();
+ if (reference != null && reference.isReferenceTo(constructor)) {
+ if (!processor.process(reference)) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ // search usages like "new XXX(..)"
+ PairProcessor<PsiReference, SearchRequestCollector> processor1 = new PairProcessor<PsiReference, SearchRequestCollector>() {
+ @Override
+ public boolean process(PsiReference reference, SearchRequestCollector collector) {
+ PsiElement parent = reference.getElement().getParent();
+ if (parent instanceof PsiAnonymousClass) {
+ parent = parent.getParent();
+ }
+ if (parent instanceof PsiNewExpression) {
+ PsiMethod constructor1 = ((PsiNewExpression)parent).resolveConstructor();
+ if (constructor1 != null) {
+ if (isStrictSignatureSearch) {
+ if (myManager.areElementsEquivalent(constructor, constructor1)) {
+ return processor.process(reference);
+ }
+ }
+ else {
+ if (myManager.areElementsEquivalent(constructor.getContainingClass(), constructor1.getContainingClass())) {
+ return processor.process(reference);
+ }
+ }
+ }
+ }
+ return true;
+ }
+ };
+
+ ReferencesSearch.searchOptimized(aClass, searchScope, ignoreAccessScope, collector, true, processor1);
+ if (PsiUtil.getLanguageLevel(aClass).isAtLeast(LanguageLevel.JDK_1_8)) {
+ ReferencesSearch.search(aClass).forEach(new Processor<PsiReference>() {
+ @Override
+ public boolean process(PsiReference reference) {
+ final PsiElement element = reference.getElement();
+ if (element != null) {
+ final PsiElement parent = element.getParent();
+ if (parent instanceof PsiMethodReferenceExpression &&
+ ((PsiMethodReferenceExpression)parent).getReferenceNameElement() instanceof PsiKeyword) {
+ if (((PsiMethodReferenceExpression)parent).isReferenceTo(constructor)) {
+ processor.process((PsiReference)parent);
+ }
+ }
+ }
+ return true;
+ }
+ });
+ }
+
+ final boolean constructorCanBeCalledImplicitly = constructor.getParameterList().getParametersCount() == 0;
+ // search usages like "this(..)"
+ if (!processSuperOrThis(processor, aClass, constructor, constructorCanBeCalledImplicitly, searchScope, isStrictSignatureSearch,
+ PsiKeyword.THIS)) {
+ return false;
+ }
+
+ // search usages like "super(..)"
+ Processor<PsiClass> processor2 = new Processor<PsiClass>() {
+ @Override
+ public boolean process(PsiClass inheritor) {
+ return processSuperOrThis(processor, (PsiClass)inheritor.getNavigationElement(), constructor, constructorCanBeCalledImplicitly, searchScope, isStrictSignatureSearch,
+ PsiKeyword.SUPER);
+ }
+ };
+
+ return ClassInheritorsSearch.search(aClass, searchScope, false).forEach(processor2);
+ }
+
+ private boolean processSuperOrThis(final Processor<PsiReference> processor,
+ final PsiClass inheritor,
+ final PsiMethod constructor, final boolean constructorCanBeCalledImplicitly, final SearchScope searchScope,
+ final boolean isStrictSignatureSearch,
+ final String superOrThisKeyword) {
+ PsiMethod[] constructors = inheritor.getConstructors();
+ if (constructors.length == 0 && constructorCanBeCalledImplicitly) {
+ processImplicitConstructorCall(inheritor, processor, constructor, inheritor);
+ }
+ for (PsiMethod method : constructors) {
+ PsiCodeBlock body = method.getBody();
+ if (body == null) {
+ continue;
+ }
+ PsiStatement[] statements = body.getStatements();
+ if (statements.length != 0) {
+ PsiStatement statement = statements[0];
+ if (statement instanceof PsiExpressionStatement) {
+ PsiExpression expr = ((PsiExpressionStatement)statement).getExpression();
+ if (expr instanceof PsiMethodCallExpression) {
+ PsiReferenceExpression refExpr = ((PsiMethodCallExpression)expr).getMethodExpression();
+ if (PsiSearchScopeUtil.isInScope(searchScope, refExpr)) {
+ if (refExpr.getText().equals(superOrThisKeyword)) {
+ PsiElement referencedElement = refExpr.resolve();
+ if (referencedElement instanceof PsiMethod) {
+ PsiMethod constructor1 = (PsiMethod)referencedElement;
+ boolean match = isStrictSignatureSearch
+ ? myManager.areElementsEquivalent(constructor1, constructor)
+ : myManager.areElementsEquivalent(constructor.getContainingClass(), constructor1.getContainingClass());
+ if (match && !processor.process(refExpr)) return false;
+ }
+ //as long as we've encountered super/this keyword, no implicit ctr calls are possible here
+ continue;
+ }
+ }
+ }
+ }
+ }
+ if (constructorCanBeCalledImplicitly) {
+ processImplicitConstructorCall(method, processor, constructor, inheritor);
+ }
+ }
+
+ return true;
+ }
+
+ private void processImplicitConstructorCall(final PsiMember usage,
+ final Processor<PsiReference> processor,
+ final PsiMethod constructor,
+ final PsiClass containingClass) {
+ if (containingClass instanceof PsiAnonymousClass) return;
+ PsiClass superClass = containingClass.getSuperClass();
+ if (myManager.areElementsEquivalent(constructor.getContainingClass(), superClass)) {
+ processor.process(new LightMemberReference(myManager, usage, PsiSubstitutor.EMPTY) {
+ @Override
+ public PsiElement getElement() {
+ return usage;
+ }
+
+ @Override
+ public TextRange getRangeInElement() {
+ if (usage instanceof PsiClass) {
+ PsiIdentifier identifier = ((PsiClass)usage).getNameIdentifier();
+ if (identifier != null) return TextRange.from(identifier.getStartOffsetInParent(), identifier.getTextLength());
+ }
+ else if (usage instanceof PsiField) {
+ PsiIdentifier identifier = ((PsiField)usage).getNameIdentifier();
+ return TextRange.from(identifier.getStartOffsetInParent(), identifier.getTextLength());
+ }
+ else if (usage instanceof PsiMethod) {
+ PsiIdentifier identifier = ((PsiMethod)usage).getNameIdentifier();
+ if (identifier != null) return TextRange.from(identifier.getStartOffsetInParent(), identifier.getTextLength());
+ }
+ return super.getRangeInElement();
+ }
+ });
+ }
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearcher.java
new file mode 100644
index 0000000..933a748
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearcher.java
@@ -0,0 +1,27 @@
+package com.intellij.psi.impl.search;
+
+import com.intellij.openapi.application.QueryExecutorBase;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.util.Processor;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author max
+ */
+public class ConstructorReferencesSearcher extends QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters> {
+ public ConstructorReferencesSearcher() {
+ super(true);
+ }
+
+ @Override
+ public void processQuery(@NotNull ReferencesSearch.SearchParameters p, @NotNull Processor<PsiReference> consumer) {
+ final PsiElement element = p.getElementToSearch();
+ if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) {
+ new ConstructorReferencesSearchHelper(element.getManager())
+ .processConstructorReferences(consumer, (PsiMethod)p.getElementToSearch(), p.getScope(), p.isIgnoreAccessScope(), true, p.getOptimizer());
+ }
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java
new file mode 100644
index 0000000..d855ab6
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaAllOverridingMethodsSearcher.java
@@ -0,0 +1,84 @@
+/*
+ * 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.impl.search;
+
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.*;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.searches.AllOverridingMethodsSearch;
+import com.intellij.psi.search.searches.ClassInheritorsSearch;
+import com.intellij.psi.util.MethodSignature;
+import com.intellij.psi.util.MethodSignatureUtil;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.util.Processor;
+import com.intellij.util.QueryExecutor;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author ven
+ */
+public class JavaAllOverridingMethodsSearcher implements QueryExecutor<Pair<PsiMethod, PsiMethod>, AllOverridingMethodsSearch.SearchParameters> {
+ @Override
+ public boolean execute(@NotNull final AllOverridingMethodsSearch.SearchParameters p, @NotNull final Processor<Pair<PsiMethod, PsiMethod>> consumer) {
+ final PsiClass psiClass = p.getPsiClass();
+
+ PsiMethod[] methodsArray = psiClass.getMethods();
+ final List<PsiMethod> methods = new ArrayList<PsiMethod>(methodsArray.length);
+ for (PsiMethod method : methodsArray) {
+ if (PsiUtil.canBeOverriden(method)) methods.add(method);
+ }
+
+ final SearchScope scope = p.getScope();
+
+ Processor<PsiClass> inheritorsProcessor = new Processor<PsiClass>() {
+ @Override
+ public boolean process(PsiClass inheritor) {
+ //could be null if not java inheritor, TODO only JavaClassInheritors are needed
+ PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(psiClass, inheritor, PsiSubstitutor.EMPTY);
+ if (substitutor == null) return true;
+
+ for (PsiMethod method : methods) {
+ if (method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) &&
+ !JavaPsiFacade.getInstance(inheritor.getProject()).arePackagesTheSame(psiClass, inheritor)) continue;
+
+ MethodSignature signature = method.getSignature(substitutor);
+ PsiMethod inInheritor = MethodSignatureUtil.findMethodBySuperSignature(inheritor, signature, false);
+ if (inInheritor == null || inInheritor.hasModifierProperty(PsiModifier.STATIC)) {
+ if (psiClass.isInterface() && !inheritor.isInterface()) { //check for sibling implementation
+ final PsiClass superClass = inheritor.getSuperClass();
+ if (superClass != null && !superClass.isInheritor(psiClass, true)) {
+ inInheritor = MethodSignatureUtil.findMethodInSuperClassBySignatureInDerived(inheritor, superClass, signature, true);
+ if (inInheritor != null && !inInheritor.hasModifierProperty(PsiModifier.STATIC)) {
+ if (!consumer.process(new Pair<PsiMethod, PsiMethod>(method, inInheritor))) return false;
+ }
+ }
+ }
+ continue;
+ }
+ if (!consumer.process(new Pair<PsiMethod, PsiMethod>(method, inInheritor))) return false;
+ }
+
+ return true;
+ }
+ };
+
+ return ClassInheritorsSearch.search(psiClass, scope, true).forEach(inheritorsProcessor);
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaDirectInheritorsSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaDirectInheritorsSearcher.java
new file mode 100644
index 0000000..fb01267
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaDirectInheritorsSearcher.java
@@ -0,0 +1,205 @@
+/*
+ * 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.impl.search;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.progress.ProgressIndicatorProvider;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiManagerImpl;
+import com.intellij.psi.impl.java.stubs.index.JavaAnonymousClassBaseRefOccurenceIndex;
+import com.intellij.psi.impl.java.stubs.index.JavaSuperClassNameOccurenceIndex;
+import com.intellij.psi.search.EverythingGlobalScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.searches.AllClassesSearch;
+import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.Processor;
+import com.intellij.util.QueryExecutor;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.HashMap;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author max
+ */
+public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, DirectClassInheritorsSearch.SearchParameters> {
+ @Override
+ public boolean execute(@NotNull final DirectClassInheritorsSearch.SearchParameters p, @NotNull final Processor<PsiClass> consumer) {
+ final PsiClass aClass = p.getClassToProcess();
+ final PsiManagerImpl psiManager = (PsiManagerImpl)aClass.getManager();
+
+ final SearchScope useScope = ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() {
+ @Override
+ public SearchScope compute() {
+ return aClass.getUseScope();
+ }
+ });
+
+ final String qualifiedName = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+ @Override
+ public String compute() {
+ return aClass.getQualifiedName();
+ }
+ });
+
+ if (CommonClassNames.JAVA_LANG_OBJECT.equals(qualifiedName)) {
+ //[pasynkov]: WTF?
+ //final SearchScope scope = useScope.intersectWith(GlobalSearchScope.notScope(GlobalSearchScope.getScopeRestrictedByFileTypes(
+ // GlobalSearchScope.allScope(psiManager.getProject()), StdFileTypes.JSP, StdFileTypes.JSPX)));
+ final SearchScope scope = useScope;
+
+ return AllClassesSearch.search(scope, aClass.getProject()).forEach(new Processor<PsiClass>() {
+ @Override
+ public boolean process(final PsiClass psiClass) {
+ if (psiClass.isInterface()) {
+ return consumer.process(psiClass);
+ }
+ final PsiClass superClass = psiClass.getSuperClass();
+ if (superClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+ public String compute() {
+ return superClass.getQualifiedName();
+ }
+ }))) {
+ return consumer.process(psiClass);
+ }
+ return true;
+ }
+ });
+ }
+
+ final GlobalSearchScope scope = useScope instanceof GlobalSearchScope ? (GlobalSearchScope)useScope : new EverythingGlobalScope(psiManager.getProject());
+ final String searchKey = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+ @Override
+ public String compute() {
+ return aClass.getName();
+ }
+ });
+ if (StringUtil.isEmpty(searchKey)) {
+ return true;
+ }
+
+ Collection<PsiReferenceList> candidates = ApplicationManager.getApplication().runReadAction(new Computable<Collection<PsiReferenceList>>() {
+ @Override
+ public Collection<PsiReferenceList> compute() {
+ return JavaSuperClassNameOccurenceIndex.getInstance().get(searchKey, psiManager.getProject(), scope);
+ }
+ });
+
+ Map<String, List<PsiClass>> classes = new HashMap<String, List<PsiClass>>();
+
+ for (PsiReferenceList referenceList : candidates) {
+ ProgressIndicatorProvider.checkCanceled();
+ final PsiClass candidate = (PsiClass)referenceList.getParent();
+ if (!checkInheritance(p, aClass, candidate)) continue;
+
+ String fqn = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+ @Override
+ public String compute() {
+ return candidate.getQualifiedName();
+ }
+ });
+ List<PsiClass> list = classes.get(fqn);
+ if (list == null) {
+ list = new ArrayList<PsiClass>();
+ classes.put(fqn, list);
+ }
+ list.add(candidate);
+ }
+
+ for (List<PsiClass> sameNamedClasses : classes.values()) {
+ if (!processSameNamedClasses(consumer, aClass, sameNamedClasses)) return false;
+ }
+
+ if (p.includeAnonymous()) {
+ Collection<PsiAnonymousClass> anonymousCandidates = ApplicationManager.getApplication().runReadAction(new Computable<Collection<PsiAnonymousClass>>() {
+ @Override
+ public Collection<PsiAnonymousClass> compute() {
+ return JavaAnonymousClassBaseRefOccurenceIndex.getInstance().get(searchKey, psiManager.getProject(), scope);
+ }
+ });
+
+ for (PsiAnonymousClass candidate : anonymousCandidates) {
+ ProgressIndicatorProvider.checkCanceled();
+ if (!checkInheritance(p, aClass, candidate)) continue;
+
+ if (!consumer.process(candidate)) return false;
+ }
+
+ if (aClass.isEnum()) {
+ // abstract enum can be subclassed in the body
+ PsiField[] fields = ApplicationManager.getApplication().runReadAction(new Computable<PsiField[]>() {
+ @Override
+ public PsiField[] compute() {
+ return aClass.getFields();
+ }
+ });
+ for (final PsiField field : fields) {
+ if (field instanceof PsiEnumConstant) {
+ PsiEnumConstantInitializer initializingClass =
+ ApplicationManager.getApplication().runReadAction(new Computable<PsiEnumConstantInitializer>() {
+ @Override
+ public PsiEnumConstantInitializer compute() {
+ return ((PsiEnumConstant)field).getInitializingClass();
+ }
+ });
+ if (initializingClass != null) {
+ if (!consumer.process(initializingClass)) return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private static boolean checkInheritance(final DirectClassInheritorsSearch.SearchParameters p, final PsiClass aClass, final PsiClass candidate) {
+ return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
+ @Override
+ public Boolean compute() {
+ return !p.isCheckInheritance() || candidate.isInheritor(aClass, false);
+ }
+ });
+ }
+
+ private static boolean processSameNamedClasses(Processor<PsiClass> consumer, PsiClass aClass, List<PsiClass> sameNamedClasses) {
+ // if there is a class from the same jar, prefer it
+ boolean sameJarClassFound = false;
+
+ VirtualFile jarFile = PsiUtil.getJarFile(aClass);
+ if (jarFile != null) {
+ for (PsiClass sameNamedClass : sameNamedClasses) {
+ boolean fromSameJar = Comparing.equal(PsiUtil.getJarFile(sameNamedClass), jarFile);
+ if (fromSameJar) {
+ sameJarClassFound = true;
+ if (!consumer.process(sameNamedClass)) return false;
+ }
+ }
+ }
+
+ return sameJarClassFound || ContainerUtil.process(sameNamedClasses, consumer);
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaOverridingMethodsSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaOverridingMethodsSearcher.java
new file mode 100644
index 0000000..9ccebc2
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaOverridingMethodsSearcher.java
@@ -0,0 +1,80 @@
+package com.intellij.psi.impl.search;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.util.Computable;
+import com.intellij.psi.*;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.searches.ClassInheritorsSearch;
+import com.intellij.psi.search.searches.OverridingMethodsSearch;
+import com.intellij.psi.util.MethodSignature;
+import com.intellij.psi.util.MethodSignatureUtil;
+import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.util.Processor;
+import com.intellij.util.QueryExecutor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author max
+ */
+public class JavaOverridingMethodsSearcher implements QueryExecutor<PsiMethod, OverridingMethodsSearch.SearchParameters> {
+ @Override
+ public boolean execute(@NotNull final OverridingMethodsSearch.SearchParameters p, @NotNull final Processor<PsiMethod> consumer) {
+ final PsiMethod method = p.getMethod();
+ final SearchScope scope = p.getScope();
+
+ final PsiClass parentClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
+ @Nullable
+ @Override
+ public PsiClass compute() {
+ return method.getContainingClass();
+ }
+ });
+ assert parentClass != null;
+ Processor<PsiClass> inheritorsProcessor = new Processor<PsiClass>() {
+ @Override
+ public boolean process(final PsiClass inheritor) {
+ PsiMethod found = ApplicationManager.getApplication().runReadAction(new Computable<PsiMethod>() {
+ @Override
+ @Nullable
+ public PsiMethod compute() {
+ return findOverridingMethod(inheritor, parentClass, method);
+ }
+ });
+ return found == null || consumer.process(found) && p.isCheckDeep();
+ }
+ };
+
+ return ClassInheritorsSearch.search(parentClass, scope, true).forEach(inheritorsProcessor);
+ }
+
+ @Nullable
+ private static PsiMethod findOverridingMethod(PsiClass inheritor, @NotNull PsiClass parentClass, PsiMethod method) {
+ PsiSubstitutor substitutor = inheritor.isInheritor(parentClass, true) ?
+ TypeConversionUtil.getSuperClassSubstitutor(parentClass, inheritor, PsiSubstitutor.EMPTY) :
+ PsiSubstitutor.EMPTY;
+ MethodSignature signature = method.getSignature(substitutor);
+ PsiMethod found = MethodSignatureUtil.findMethodBySuperSignature(inheritor, signature, false);
+ if (found != null && isAcceptable(found, method)) {
+ return found;
+ }
+
+ if (parentClass.isInterface() && !inheritor.isInterface()) { //check for sibling implementation
+ final PsiClass superClass = inheritor.getSuperClass();
+ if (superClass != null && !superClass.isInheritor(parentClass, true)) {
+ PsiMethod derived = MethodSignatureUtil.findMethodInSuperClassBySignatureInDerived(inheritor, superClass, signature, true);
+ if (derived != null && isAcceptable(derived, method)) {
+ return derived;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static boolean isAcceptable(final PsiMethod found, final PsiMethod method) {
+ return !found.hasModifierProperty(PsiModifier.STATIC) &&
+ (!method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) ||
+ JavaPsiFacade.getInstance(found.getProject())
+ .arePackagesTheSame(method.getContainingClass(), found.getContainingClass()));
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java
new file mode 100644
index 0000000..086a20e
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaSourceFilterScope.java
@@ -0,0 +1,51 @@
+/*
+ * 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.impl.search;
+
+import com.intellij.ide.highlighter.JavaClassFileType;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.search.DelegatingGlobalSearchScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+
+public class JavaSourceFilterScope extends DelegatingGlobalSearchScope {
+ private final ProjectFileIndex myIndex;
+
+ public JavaSourceFilterScope(@NotNull final GlobalSearchScope delegate) {
+ super(delegate);
+ myIndex = ProjectRootManager.getInstance(getProject()).getFileIndex();
+ }
+
+ @Override
+ public boolean contains(final VirtualFile file) {
+ if (!super.contains(file)) {
+ return false;
+ }
+
+ if (JavaClassFileType.INSTANCE == file.getFileType()) {
+ return myIndex.isInLibraryClasses(file);
+ }
+
+ return myIndex.isInSourceContent(file);
+ }
+
+}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodDeepestSuperSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodDeepestSuperSearcher.java
new file mode 100644
index 0000000..2c9117b
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodDeepestSuperSearcher.java
@@ -0,0 +1,41 @@
+package com.intellij.psi.impl.search;
+
+import com.intellij.psi.PsiMethod;
+import com.intellij.util.Processor;
+import com.intellij.util.QueryExecutor;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+/**
+ * @author peter
+ */
+public class MethodDeepestSuperSearcher implements QueryExecutor<PsiMethod, PsiMethod> {
+ @Override
+ public boolean execute(@NotNull PsiMethod method, @NotNull Processor<PsiMethod> consumer) {
+ final Set<PsiMethod> methods = new THashSet<PsiMethod>();
+ methods.add(method);
+ return findDeepestSuperOrSelfSignature(method, methods, null, consumer);
+ }
+
+ private static boolean findDeepestSuperOrSelfSignature(PsiMethod method,
+ Set<PsiMethod> set,
+ Set<PsiMethod> guard,
+ Processor<PsiMethod> processor) {
+ if (guard != null && !guard.add(method)) return true;
+ PsiMethod[] supers = method.findSuperMethods();
+
+ if (supers.length == 0 && set.add(method) && !processor.process(method)) {
+ return false;
+ }
+ for (PsiMethod superMethod : supers) {
+ if (guard == null) {
+ guard = new THashSet<PsiMethod>();
+ guard.add(method);
+ }
+ if (!findDeepestSuperOrSelfSignature(superMethod, set, guard, processor)) return false;
+ }
+ return true;
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java
new file mode 100644
index 0000000..d65e80e
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java
@@ -0,0 +1,71 @@
+package com.intellij.psi.impl.search;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.*;
+import com.intellij.psi.search.searches.SuperMethodsSearch;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
+import com.intellij.psi.util.MethodSignatureUtil;
+import com.intellij.util.Processor;
+import com.intellij.util.QueryExecutor;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author ven
+ */
+public class MethodSuperSearcher implements QueryExecutor<MethodSignatureBackedByPsiMethod, SuperMethodsSearch.SearchParameters> {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.search.MethodSuperSearcher");
+
+ @Override
+ public boolean execute(@NotNull final SuperMethodsSearch.SearchParameters queryParameters, @NotNull final Processor<MethodSignatureBackedByPsiMethod> consumer) {
+ final PsiClass parentClass = queryParameters.getPsiClass();
+ final PsiMethod method = queryParameters.getMethod();
+ HierarchicalMethodSignature signature = method.getHierarchicalMethodSignature();
+
+ final boolean checkBases = queryParameters.isCheckBases();
+ final boolean allowStaticMethod = queryParameters.isAllowStaticMethod();
+ final List<HierarchicalMethodSignature> supers = signature.getSuperSignatures();
+ for (HierarchicalMethodSignature superSignature : supers) {
+ if (MethodSignatureUtil.isSubsignature(superSignature, signature)) {
+ if (!addSuperMethods(superSignature, method, parentClass, allowStaticMethod, checkBases, consumer)) return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static boolean addSuperMethods(final HierarchicalMethodSignature signature,
+ final PsiMethod method,
+ final PsiClass parentClass,
+ final boolean allowStaticMethod,
+ final boolean checkBases,
+ final Processor<MethodSignatureBackedByPsiMethod> consumer) {
+ PsiMethod signatureMethod = signature.getMethod();
+ PsiClass hisClass = signatureMethod.getContainingClass();
+ if (parentClass == null || InheritanceUtil.isInheritorOrSelf(parentClass, hisClass, true)) {
+ if (isAcceptable(signatureMethod, method, allowStaticMethod)) {
+ if (parentClass != null && !parentClass.equals(hisClass) && !checkBases) {
+ return true;
+ }
+ LOG.assertTrue(signatureMethod != method, method); // method != method.getsuper()
+ return consumer.process(signature); //no need to check super classes
+ }
+ }
+ for (HierarchicalMethodSignature superSignature : signature.getSuperSignatures()) {
+ if (MethodSignatureUtil.isSubsignature(superSignature, signature)) {
+ addSuperMethods(superSignature, method, parentClass, allowStaticMethod, checkBases, consumer);
+ }
+ }
+
+ return true;
+ }
+
+ private static boolean isAcceptable(final PsiMethod superMethod, final PsiMethod method, final boolean allowStaticMethod) {
+ boolean hisStatic = superMethod.hasModifierProperty(PsiModifier.STATIC);
+ return hisStatic == method.hasModifierProperty(PsiModifier.STATIC) &&
+ (allowStaticMethod || !hisStatic) &&
+ JavaPsiFacade.getInstance(method.getProject()).getResolveHelper().isAccessible(superMethod, method, null);
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodTextOccurrenceProcessor.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodTextOccurrenceProcessor.java
new file mode 100644
index 0000000..5e6a35a
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodTextOccurrenceProcessor.java
@@ -0,0 +1,98 @@
+/*
+ * 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.impl.search;
+
+import com.intellij.psi.*;
+import com.intellij.psi.search.RequestResultProcessor;
+import com.intellij.psi.util.MethodSignature;
+import com.intellij.psi.util.MethodSignatureUtil;
+import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.util.Processor;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+
+/**
+ * @author peter
+ */
+public final class MethodTextOccurrenceProcessor extends RequestResultProcessor {
+ private static final PsiReferenceService ourReferenceService = PsiReferenceService.getService();
+ private final PsiMethod[] myMethods;
+ private final PsiClass myContainingClass;
+ private final boolean myStrictSignatureSearch;
+
+ public MethodTextOccurrenceProcessor(@NotNull final PsiClass aClass, final boolean strictSignatureSearch, final PsiMethod... methods) {
+ super(strictSignatureSearch, Arrays.asList(methods));
+ myMethods = methods;
+ myContainingClass = aClass;
+ myStrictSignatureSearch = strictSignatureSearch;
+ }
+
+ @Override
+ public boolean processTextOccurrence(@NotNull PsiElement element, int offsetInElement, @NotNull final Processor<PsiReference> consumer) {
+ for (PsiReference ref : ourReferenceService.getReferences(element, new PsiReferenceService.Hints(myMethods[0], offsetInElement))) {
+ if (ReferenceRange.containsOffsetInElement(ref, offsetInElement) && !processReference(consumer, ref)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ private boolean processReference(Processor<PsiReference> consumer, PsiReference ref) {
+ for (PsiMethod method : myMethods) {
+ if (!method.isValid()) {
+ continue;
+ }
+
+ if (ref instanceof ResolvingHint && !((ResolvingHint)ref).canResolveTo(PsiMethod.class)) {
+ return true;
+ }
+ if (ref.isReferenceTo(method)) {
+ return consumer.process(ref);
+ }
+ PsiElement refElement = ref.resolve();
+
+ if (refElement instanceof PsiMethod) {
+ PsiMethod refMethod = (PsiMethod)refElement;
+ PsiClass refMethodClass = refMethod.getContainingClass();
+ if (refMethodClass == null) continue;
+
+ if (!refMethod.hasModifierProperty(PsiModifier.STATIC)) {
+ PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(myContainingClass, refMethodClass, PsiSubstitutor.EMPTY);
+ if (substitutor != null) {
+ MethodSignature superSignature = method.getSignature(substitutor);
+ MethodSignature refSignature = refMethod.getSignature(PsiSubstitutor.EMPTY);
+
+ if (MethodSignatureUtil.isSubsignature(superSignature, refSignature)) {
+ if (!consumer.process(ref)) return false;
+ }
+ }
+ }
+
+ if (!myStrictSignatureSearch) {
+ PsiManager manager = method.getManager();
+ if (manager.areElementsEquivalent(refMethodClass, myContainingClass)) {
+ if (!consumer.process(ref)) return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java
new file mode 100644
index 0000000..49bd3f3
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodUsagesSearcher.java
@@ -0,0 +1,82 @@
+package com.intellij.psi.impl.search;
+
+import com.intellij.openapi.application.QueryExecutorBase;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.search.SearchRequestCollector;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.UsageSearchContext;
+import com.intellij.psi.search.searches.MethodReferencesSearch;
+import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.Processor;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author max
+ */
+public class MethodUsagesSearcher extends QueryExecutorBase<PsiReference, MethodReferencesSearch.SearchParameters> {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.search.MethodUsagesSearcher");
+ public MethodUsagesSearcher() {
+ super(true);
+ }
+
+ @Override
+ public void processQuery(@NotNull MethodReferencesSearch.SearchParameters p, @NotNull final Processor<PsiReference> consumer) {
+ final PsiMethod method = p.getMethod();
+ final SearchRequestCollector collector = p.getOptimizer();
+
+ final SearchScope searchScope = p.getScope();
+
+ final PsiManager psiManager = method.getManager();
+
+ final PsiClass aClass = method.getContainingClass();
+ if (aClass == null) return;
+
+ final boolean strictSignatureSearch = p.isStrictSignatureSearch();
+
+ if (method.isConstructor()) {
+ new ConstructorReferencesSearchHelper(psiManager).
+ processConstructorReferences(consumer, method, searchScope, !strictSignatureSearch, strictSignatureSearch, collector);
+ }
+
+ if (PsiUtil.isAnnotationMethod(method) &&
+ PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(method.getName()) &&
+ method.getParameterList().getParametersCount() == 0) {
+ ReferencesSearch.search(aClass, p.getScope()).forEach(PsiAnnotationMethodReferencesSearcher.createImplicitDefaultAnnotationMethodConsumer( consumer));
+ }
+
+ boolean needStrictSignatureSearch = strictSignatureSearch && (aClass instanceof PsiAnonymousClass
+ || aClass.hasModifierProperty(PsiModifier.FINAL)
+ || method.hasModifierProperty(PsiModifier.STATIC)
+ || method.hasModifierProperty(PsiModifier.FINAL)
+ || method.hasModifierProperty(PsiModifier.PRIVATE));
+ if (needStrictSignatureSearch) {
+ ReferencesSearch.searchOptimized(method, searchScope, false, collector, consumer);
+ return;
+ }
+
+ final String textToSearch = method.getName();
+ if (StringUtil.isEmpty(textToSearch)) {
+ return;
+ }
+ final PsiMethod[] methods = strictSignatureSearch ? new PsiMethod[]{method} : aClass.findMethodsByName(textToSearch, false);
+
+ SearchScope accessScope = methods[0].getUseScope();
+ for (int i = 1; i < methods.length; i++) {
+ PsiMethod method1 = methods[i];
+ accessScope = accessScope.union(method1.getUseScope());
+ }
+
+ final SearchScope restrictedByAccess = searchScope.intersectWith(accessScope);
+
+ short searchContext = UsageSearchContext.IN_CODE | UsageSearchContext.IN_COMMENTS | UsageSearchContext.IN_FOREIGN_LANGUAGES;
+ collector.searchWord(textToSearch, restrictedByAccess, searchContext, true,
+ new MethodTextOccurrenceProcessor(aClass, strictSignatureSearch, methods));
+
+ SimpleAccessorReferenceSearcher.addPropertyAccessUsages(method, restrictedByAccess, collector);
+
+ }
+
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/PsiAnnotationMethodReferencesSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/PsiAnnotationMethodReferencesSearcher.java
new file mode 100644
index 0000000..50f10ca
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/PsiAnnotationMethodReferencesSearcher.java
@@ -0,0 +1,48 @@
+package com.intellij.psi.impl.search;
+
+import com.intellij.psi.*;
+import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.Processor;
+import com.intellij.util.Query;
+import com.intellij.util.QueryExecutor;
+import com.intellij.openapi.application.ReadActionProcessor;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author max
+ */
+public class PsiAnnotationMethodReferencesSearcher implements QueryExecutor<PsiReference, ReferencesSearch.SearchParameters> {
+ @Override
+ public boolean execute(@NotNull final ReferencesSearch.SearchParameters p, @NotNull final Processor<PsiReference> consumer) {
+ final PsiElement refElement = p.getElementToSearch();
+ if (PsiUtil.isAnnotationMethod(refElement)) {
+ PsiMethod method = (PsiMethod)refElement;
+ if (PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(method.getName()) && method.getParameterList().getParametersCount() == 0) {
+ final Query<PsiReference> query = ReferencesSearch.search(method.getContainingClass(), p.getScope(), p.isIgnoreAccessScope());
+ return query.forEach(createImplicitDefaultAnnotationMethodConsumer(consumer));
+ }
+ }
+
+ return true;
+ }
+
+ public static ReadActionProcessor<PsiReference> createImplicitDefaultAnnotationMethodConsumer(final Processor<PsiReference> consumer) {
+ return new ReadActionProcessor<PsiReference>() {
+ @Override
+ public boolean processInReadAction(final PsiReference reference) {
+ if (reference instanceof PsiJavaCodeReferenceElement) {
+ PsiJavaCodeReferenceElement javaReference = (PsiJavaCodeReferenceElement)reference;
+ if (javaReference.getParent() instanceof PsiAnnotation) {
+ PsiNameValuePair[] members = ((PsiAnnotation)javaReference.getParent()).getParameterList().getAttributes();
+ if (members.length == 1 && members[0].getNameIdentifier() == null) {
+ PsiReference t = members[0].getReference();
+ if (t != null && !consumer.process(t)) return false;
+ }
+ }
+ }
+ return true;
+ }
+ };
+ }
+}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/SimpleAccessorReferenceSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/SimpleAccessorReferenceSearcher.java
new file mode 100644
index 0000000..1687068
--- /dev/null
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/SimpleAccessorReferenceSearcher.java
@@ -0,0 +1,62 @@
+/*
+ * 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.impl.search;
+
+import com.intellij.openapi.application.QueryExecutorBase;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.SearchRequestCollector;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.UsageSearchContext;
+import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.psi.util.PropertyUtil;
+import com.intellij.util.Processor;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ven
+ */
+public class SimpleAccessorReferenceSearcher extends QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters> {
+
+ public SimpleAccessorReferenceSearcher() {
+ super(true);
+ }
+
+ @Override
+ public void processQuery(@NotNull ReferencesSearch.SearchParameters queryParameters, @NotNull Processor<PsiReference> consumer) {
+ PsiElement refElement = queryParameters.getElementToSearch();
+ if (!(refElement instanceof PsiMethod)) return;
+
+ addPropertyAccessUsages((PsiMethod)refElement, queryParameters.getEffectiveSearchScope(), queryParameters.getOptimizer());
+ }
+
+ static void addPropertyAccessUsages(PsiMethod method, SearchScope scope, SearchRequestCollector collector) {
+ final String propertyName = PropertyUtil.getPropertyName(method);
+ if (StringUtil.isNotEmpty(propertyName)) {
+ SearchScope additional = GlobalSearchScope.EMPTY_SCOPE;
+ for (CustomPropertyScopeProvider provider : Extensions.getExtensions(CustomPropertyScopeProvider.EP_NAME)) {
+ additional = additional.union(provider.getScope(method.getProject()));
+ }
+ assert propertyName != null;
+ final SearchScope propScope = scope.intersectWith(method.getUseScope()).intersectWith(additional);
+ collector.searchWord(propertyName, propScope, UsageSearchContext.IN_FOREIGN_LANGUAGES, true, method);
+ }
+ }
+}