/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.plugin.ij.lang.psi.impl.search;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiSubstitutor;
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.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import gw.plugin.ij.lang.psi.api.auxilary.IGosuModifier;
import gw.plugin.ij.util.GosuProperties;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class GosuAllOverridingMethodsSearcher implements QueryExecutor<Pair<PsiMethod, PsiMethod>, AllOverridingMethodsSearch.SearchParameters> {
@Override
public boolean execute(@NotNull AllOverridingMethodsSearch.SearchParameters p, @NotNull final Processor<Pair<PsiMethod, PsiMethod>> consumer) {
// Parameters
final PsiClass psiClass = p.getPsiClass();
final SearchScope scope = p.getScope();
// Setters and getters that can be overriden
final List<PsiMethod> methods = new ArrayList<>();
for (PsiMethod method : psiClass.getMethods()) {
if (PsiUtil.canBeOverriden(method) && (GosuProperties.isSetter(method) || GosuProperties.isGetter(method))) {
methods.add(method);
}
}
// Search all inheritors
return ClassInheritorsSearch.search(psiClass, scope, true).forEach(new Processor<PsiClass>() {
public boolean process(@NotNull PsiClass inheritor) {
//could be null if not java inheritor, TODO only JavaClassInheritors are needed
final PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(psiClass, inheritor, PsiSubstitutor.EMPTY);
if (substitutor == null) {
return true;
}
for (PsiMethod method : methods) {
if ((method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) ||
method.hasModifierProperty( IGosuModifier.INTERNAL)) &&
!JavaPsiFacade.getInstance(inheritor.getProject()).arePackagesTheSame(psiClass, inheritor)) {
continue;
}
final String getterName = GosuProperties.getGetterName(method);
final String setterName = GosuProperties.getSetterName(method);
for (PsiMethod overriddenMethod : inheritor.getMethods()) {
if ((getterName != null && getterName.equals(GosuProperties.getGetterName(overriddenMethod))) ||
(setterName != null && setterName.equals(GosuProperties.getSetterName(overriddenMethod)))) {
if (!consumer.process(new Pair(method, overriddenMethod))) {
return false;
}
}
}
}
return true;
}
});
}
}