/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.plugin.ij.lang.psi.impl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
import com.intellij.psi.stubs.StubIndex;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import gw.plugin.ij.lang.psi.api.statements.typedef.IGosuAnonymousClassDefinition;
import gw.plugin.ij.lang.psi.api.statements.typedef.IGosuReferenceList;
import gw.plugin.ij.lang.psi.api.statements.typedef.IGosuTypeDefinition;
import gw.plugin.ij.lang.psi.stubs.index.GosuAnonymousClassIndex;
import gw.plugin.ij.lang.psi.stubs.index.GosuDirectInheritorsIndex;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author ven
*/
public class GosuDirectInheritorSearcher implements QueryExecutor<PsiClass, DirectClassInheritorsSearch.SearchParameters> {
public GosuDirectInheritorSearcher() {
}
@NotNull
private static PsiClass[] getDeriverCandidates(@NotNull PsiClass clazz, GlobalSearchScope scope) {
final String name = clazz.getName();
if (name == null) return new PsiClass[0];
final ArrayList<PsiClass> inheritors = new ArrayList<>();
Collection<IGosuReferenceList> gosuReferenceLists = StubIndex.getInstance().get(GosuDirectInheritorsIndex.KEY, name, clazz.getProject(), scope);
for (IGosuReferenceList list : gosuReferenceLists) {
final PsiElement parent = list.getParent();
if (parent instanceof IGosuTypeDefinition) {
inheritors.add((IGosuTypeDefinition) parent);
}
}
Collection<IGosuAnonymousClassDefinition> classes = StubIndex.getInstance().get(GosuAnonymousClassIndex.KEY, name, clazz.getProject(), scope);
for (IGosuAnonymousClassDefinition aClass : classes) {
inheritors.add(aClass);
}
return inheritors.toArray(new PsiClass[inheritors.size()]);
}
public boolean execute(@NotNull DirectClassInheritorsSearch.SearchParameters queryParameters, @NotNull final Processor<PsiClass> consumer) {
final PsiClass clazz = queryParameters.getClassToProcess();
final SearchScope scope = queryParameters.getScope();
if (scope instanceof GlobalSearchScope) {
final PsiClass[] candidates = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass[]>() {
@NotNull
public PsiClass[] compute() {
if (!clazz.isValid()) return PsiClass.EMPTY_ARRAY;
return getDeriverCandidates(clazz, (GlobalSearchScope) scope);
}
});
for (final PsiClass candidate : candidates) {
final boolean isInheritor = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
public Boolean compute() {
return candidate.isInheritor(clazz, false);
}
});
if (isInheritor) {
if (!consumer.process(candidate)) {
return false;
}
}
}
return true;
}
return true;
}
}