use JavaClassSupers to calculate super class substitutor and isInheritor

This commit is contained in:
peter
2015-05-20 22:16:29 +02:00
parent ec2186745e
commit 3880c5142f
2 changed files with 5 additions and 102 deletions
@@ -1090,28 +1090,7 @@ public class TypeConversionUtil {
@NotNull PsiClass derivedClass,
@NotNull PsiSubstitutor derivedSubstitutor,
@Nullable Set<PsiClass> visited) {
if (!superClass.hasTypeParameters() && superClass.getContainingClass() == null) {
return InheritanceUtil.isInheritorOrSelf(derivedClass, superClass, true) ? PsiSubstitutor.EMPTY : null; //optimization
}
final PsiManager manager = superClass.getManager();
if (PsiUtil.isRawSubstitutor(derivedClass, derivedSubstitutor)) {
return InheritanceUtil.isInheritorOrSelf(derivedClass, superClass, true) ? JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createRawSubstitutor(superClass) : null;
}
if (CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(superClass.getName()) &&
manager.areElementsEquivalent(superClass, JavaPsiFacade.getInstance(manager.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT, superClass.getResolveScope()))) {
return PsiSubstitutor.EMPTY;
}
if (derivedClass instanceof PsiAnonymousClass) {
final PsiClassType baseType = ((PsiAnonymousClass)derivedClass).getBaseClassType();
final JavaResolveResult result = baseType.resolveGenerics();
if (result.getElement() == null) return PsiSubstitutor.UNKNOWN;
derivedClass = (PsiClass)result.getElement();
derivedSubstitutor = derivedSubstitutor.putAll(result.getSubstitutor());
}
return getSuperClassSubstitutorInner(superClass, derivedClass, derivedSubstitutor, visited == null ? new THashSet<PsiClass>() : visited, manager);
return JavaClassSupers.getInstance().getSuperClassSubstitutor(superClass, derivedClass, derivedClass.getResolveScope(), derivedSubstitutor);
}
private static void reportHierarchyInconsistency(@NotNull PsiClass superClass, @NotNull PsiClass derivedClass, @NotNull Set<PsiClass> visited) {
@@ -1152,62 +1131,6 @@ public class TypeConversionUtil {
return getSuperClassSubstitutor(superClass, classResolveResult.getElement(), classResolveResult.getSubstitutor());
}
@Nullable
private static PsiSubstitutor getSuperClassSubstitutorInner(@NotNull PsiClass base,
@NotNull PsiClass candidate,
@NotNull PsiSubstitutor candidateSubstitutor,
@NotNull Set<PsiClass> visited,
@NotNull PsiManager manager) {
if (!visited.add(candidate)) return null;
assert candidateSubstitutor.isValid();
if (base == candidate) return candidateSubstitutor;
if (manager.areElementsEquivalent(base, candidate)) {
PsiTypeParameter[] baseParams = base.getTypeParameters();
PsiTypeParameter[] candidateParams = candidate.getTypeParameters();
PsiElementFactory factory = JavaPsiFacade.getInstance(base.getProject()).getElementFactory();
if (baseParams.length > 0 && candidateParams.length == 0) {
return factory.createRawSubstitutor(base);
}
else {
Map<PsiTypeParameter, PsiType> m = new HashMap<PsiTypeParameter, PsiType>();
for (int i = 0; i < candidateParams.length && i < baseParams.length; i++) {
m.put(baseParams[i], candidateSubstitutor.substitute(candidateParams[i]));
}
return factory.createSubstitutor(m);
}
}
PsiSubstitutor substitutor = checkReferenceList(candidate.getExtendsListTypes(), candidateSubstitutor, base, visited, manager);
if (substitutor == null) {
substitutor = checkReferenceList(candidate.getImplementsListTypes(), candidateSubstitutor, base, visited, manager);
}
return substitutor;
}
private static PsiSubstitutor checkReferenceList(@NotNull PsiClassType[] types,
@NotNull PsiSubstitutor candidateSubstitutor,
@NotNull PsiClass base,
@NotNull Set<PsiClass> set,
@NotNull PsiManager manager) {
for (final PsiClassType type : types) {
final PsiType substitutedType = candidateSubstitutor.substitute(type);
//if (!(substitutedType instanceof PsiClassType)) return null;
LOG.assertTrue(substitutedType instanceof PsiClassType);
final JavaResolveResult result = ((PsiClassType)substitutedType).resolveGenerics();
final PsiElement newCandidate = result.getElement();
if (newCandidate != null) {
final PsiSubstitutor substitutor = result.getSubstitutor();
final PsiSubstitutor newSubstitutor = getSuperClassSubstitutorInner(base, (PsiClass)newCandidate, substitutor, set, manager);
if (newSubstitutor != null) {
return type.isRaw() ? JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createRawSubstitutor(base) : newSubstitutor;
}
}
}
return null;
}
/**
* see JLS 5.6.2
*/
@@ -20,45 +20,25 @@ import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.psi.util.JavaClassSupers;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Set;
public class InheritanceImplUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.InheritanceImplUtil");
public static boolean isInheritor(@NotNull final PsiClass candidateClass, @NotNull PsiClass baseClass, final boolean checkDeep) {
if (baseClass instanceof PsiAnonymousClass) return false;
if (baseClass instanceof PsiAnonymousClass || baseClass.getManager().areElementsEquivalent(baseClass, candidateClass)) return false;
if (!checkDeep) {
return isInheritor(candidateClass.getManager(), candidateClass, baseClass, false, null);
}
if (hasObjectQualifiedName(candidateClass)) return false;
if (hasObjectQualifiedName(baseClass)) return true;
Map<PsiClass, Boolean> map = CachedValuesManager.
getCachedValue(candidateClass, new CachedValueProvider<Map<PsiClass, Boolean>>() {
@Nullable
@Override
public Result<Map<PsiClass, Boolean>> compute() {
final Map<PsiClass, Boolean> map = ContainerUtil.createConcurrentWeakMap();
return Result.create(map, candidateClass, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
});
Boolean computed = map.get(baseClass);
if (computed == null) {
computed = isInheritor(candidateClass.getManager(), candidateClass, baseClass, true, null);
map.put(baseClass, computed);
}
return computed;
GlobalSearchScope scope = candidateClass.getResolveScope();
return JavaClassSupers.getInstance().getSuperClassSubstitutor(baseClass, candidateClass, scope, PsiSubstitutor.EMPTY) != null;
}
public static boolean hasObjectQualifiedName(@NotNull PsiClass candidateClass) {