use of com.intellij.psi.impl.source.HierarchicalMethodSignatureImpl in project intellij-community by JetBrains.
the class PsiSuperMethodImplUtil method buildMethodHierarchy.
@NotNull
private static Map<MethodSignature, HierarchicalMethodSignature> buildMethodHierarchy(@NotNull PsiClass aClass, @Nullable String nameHint, @NotNull PsiSubstitutor substitutor, final boolean includePrivates, @NotNull final Set<PsiClass> visited, boolean isInRawContext, GlobalSearchScope resolveScope) {
ProgressManager.checkCanceled();
Map<MethodSignature, HierarchicalMethodSignature> result = new LinkedHashMap<>(new EqualityPolicy<MethodSignature>() {
@Override
public int getHashCode(MethodSignature object) {
return object.hashCode();
}
@Override
public boolean isEqual(MethodSignature o1, MethodSignature o2) {
if (o1.equals(o2)) {
final PsiMethod method1 = ((MethodSignatureBackedByPsiMethod) o1).getMethod();
final PsiType returnType1 = method1.getReturnType();
final PsiMethod method2 = ((MethodSignatureBackedByPsiMethod) o2).getMethod();
final PsiType returnType2 = method2.getReturnType();
if (method1.hasModifierProperty(PsiModifier.STATIC) || method2.hasModifierProperty(PsiModifier.STATIC)) {
return true;
}
if (MethodSignatureUtil.isReturnTypeSubstitutable(o1, o2, returnType1, returnType2)) {
return true;
}
final PsiClass containingClass1 = method1.getContainingClass();
final PsiClass containingClass2 = method2.getContainingClass();
if (containingClass1 != null && containingClass2 != null) {
return containingClass1.isAnnotationType() || containingClass2.isAnnotationType();
}
}
return false;
}
});
final Map<MethodSignature, List<PsiMethod>> sameParameterErasureMethods = new THashMap<>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY);
Map<MethodSignature, HierarchicalMethodSignatureImpl> map = new THashMap<>(new TObjectHashingStrategy<MethodSignature>() {
@Override
public int computeHashCode(MethodSignature signature) {
return MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY.computeHashCode(signature);
}
@Override
public boolean equals(MethodSignature o1, MethodSignature o2) {
if (!MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY.equals(o1, o2))
return false;
List<PsiMethod> list = sameParameterErasureMethods.get(o1);
boolean toCheckReturnType = list != null && list.size() > 1;
if (!toCheckReturnType)
return true;
PsiType returnType1 = ((MethodSignatureBackedByPsiMethod) o1).getMethod().getReturnType();
PsiType returnType2 = ((MethodSignatureBackedByPsiMethod) o2).getMethod().getReturnType();
if (returnType1 == null && returnType2 == null)
return true;
if (returnType1 == null || returnType2 == null)
return false;
PsiType erasure1 = TypeConversionUtil.erasure(o1.getSubstitutor().substitute(returnType1));
PsiType erasure2 = TypeConversionUtil.erasure(o2.getSubstitutor().substitute(returnType2));
return erasure1.equals(erasure2);
}
});
PsiMethod[] methods = aClass.getMethods();
if ((nameHint == null || "values".equals(nameHint)) && aClass instanceof PsiClassImpl) {
final PsiMethod valuesMethod = ((PsiClassImpl) aClass).getValuesMethod();
if (valuesMethod != null) {
methods = ArrayUtil.append(methods, valuesMethod);
}
}
for (PsiMethod method : methods) {
if (!method.isValid()) {
throw new PsiInvalidElementAccessException(method, "class.valid=" + aClass.isValid() + "; name=" + method.getName());
}
if (nameHint != null && !nameHint.equals(method.getName()))
continue;
if (!includePrivates && method.hasModifierProperty(PsiModifier.PRIVATE))
continue;
final MethodSignatureBackedByPsiMethod signature = MethodSignatureBackedByPsiMethod.create(method, PsiSubstitutor.EMPTY, isInRawContext);
HierarchicalMethodSignatureImpl newH = new HierarchicalMethodSignatureImpl(MethodSignatureBackedByPsiMethod.create(method, substitutor, isInRawContext));
List<PsiMethod> list = sameParameterErasureMethods.get(signature);
if (list == null) {
list = new SmartList<>();
sameParameterErasureMethods.put(signature, list);
}
list.add(method);
LOG.assertTrue(newH.getMethod().isValid());
result.put(signature, newH);
map.put(signature, newH);
}
final List<PsiClassType.ClassResolveResult> superTypes = PsiClassImplUtil.getScopeCorrectedSuperTypes(aClass, resolveScope);
for (PsiClassType.ClassResolveResult superTypeResolveResult : superTypes) {
PsiClass superClass = superTypeResolveResult.getElement();
if (superClass == null)
continue;
// cyclic inheritance
if (!visited.add(superClass))
continue;
final PsiSubstitutor superSubstitutor = superTypeResolveResult.getSubstitutor();
PsiSubstitutor finalSubstitutor = PsiSuperMethodUtil.obtainFinalSubstitutor(superClass, superSubstitutor, substitutor, isInRawContext);
final boolean isInRawContextSuper = (isInRawContext || PsiUtil.isRawSubstitutor(superClass, superSubstitutor)) && superClass.getTypeParameters().length != 0;
Map<MethodSignature, HierarchicalMethodSignature> superResult = buildMethodHierarchy(superClass, nameHint, finalSubstitutor, false, visited, isInRawContextSuper, resolveScope);
visited.remove(superClass);
List<Pair<MethodSignature, HierarchicalMethodSignature>> flattened = new ArrayList<>();
for (Map.Entry<MethodSignature, HierarchicalMethodSignature> entry : superResult.entrySet()) {
HierarchicalMethodSignature hms = entry.getValue();
MethodSignature signature = MethodSignatureBackedByPsiMethod.create(hms.getMethod(), hms.getSubstitutor(), hms.isRaw());
PsiClass containingClass = hms.getMethod().getContainingClass();
List<HierarchicalMethodSignature> supers = new ArrayList<>(hms.getSuperSignatures());
for (HierarchicalMethodSignature aSuper : supers) {
PsiClass superContainingClass = aSuper.getMethod().getContainingClass();
if (containingClass != null && superContainingClass != null && !containingClass.isInheritor(superContainingClass, true)) {
// methods must be inherited from unrelated classes, so flatten hierarchy here
// class C implements SAM1, SAM2 { void methodimpl() {} }
//hms.getSuperSignatures().remove(aSuper);
flattened.add(Pair.create(signature, aSuper));
}
}
putInMap(aClass, result, map, hms, signature);
}
for (Pair<MethodSignature, HierarchicalMethodSignature> pair : flattened) {
putInMap(aClass, result, map, pair.second, pair.first);
}
}
for (Map.Entry<MethodSignature, HierarchicalMethodSignatureImpl> entry : map.entrySet()) {
HierarchicalMethodSignatureImpl hierarchicalMethodSignature = entry.getValue();
MethodSignature methodSignature = entry.getKey();
if (result.get(methodSignature) == null) {
LOG.assertTrue(hierarchicalMethodSignature.getMethod().isValid());
result.put(methodSignature, hierarchicalMethodSignature);
}
}
return result;
}
use of com.intellij.psi.impl.source.HierarchicalMethodSignatureImpl in project intellij-community by JetBrains.
the class PsiSuperMethodImplUtil method mergeSupers.
private static void mergeSupers(@NotNull HierarchicalMethodSignatureImpl existing, @NotNull HierarchicalMethodSignature superSignature) {
for (HierarchicalMethodSignature existingSuper : existing.getSuperSignatures()) {
if (existingSuper.getMethod() == superSignature.getMethod()) {
for (HierarchicalMethodSignature signature : superSignature.getSuperSignatures()) {
mergeSupers((HierarchicalMethodSignatureImpl) existingSuper, signature);
}
return;
}
}
if (existing.getMethod() == superSignature.getMethod()) {
List<HierarchicalMethodSignature> existingSupers = existing.getSuperSignatures();
for (HierarchicalMethodSignature supers : superSignature.getSuperSignatures()) {
if (!existingSupers.contains(supers))
existing.addSuperSignature(copy(supers));
}
} else {
HierarchicalMethodSignatureImpl copy = copy(superSignature);
existing.addSuperSignature(copy);
}
}
use of com.intellij.psi.impl.source.HierarchicalMethodSignatureImpl in project intellij-community by JetBrains.
the class PsiSuperMethodImplUtil method putInMap.
private static void putInMap(@NotNull PsiClass aClass, @NotNull Map<MethodSignature, HierarchicalMethodSignature> result, @NotNull Map<MethodSignature, HierarchicalMethodSignatureImpl> map, @NotNull HierarchicalMethodSignature hierarchicalMethodSignature, @NotNull MethodSignature signature) {
HierarchicalMethodSignatureImpl existing = map.get(signature);
if (existing == null) {
HierarchicalMethodSignatureImpl copy = copy(hierarchicalMethodSignature);
LOG.assertTrue(copy.getMethod().isValid());
map.put(signature, copy);
} else if (isReturnTypeIsMoreSpecificThan(hierarchicalMethodSignature, existing) && isSuperMethod(aClass, hierarchicalMethodSignature, existing)) {
HierarchicalMethodSignatureImpl newSuper = copy(hierarchicalMethodSignature);
mergeSupers(newSuper, existing);
LOG.assertTrue(newSuper.getMethod().isValid());
map.put(signature, newSuper);
} else if (isSuperMethod(aClass, existing, hierarchicalMethodSignature)) {
mergeSupers(existing, hierarchicalMethodSignature);
} else // just drop an invalid method declaration there - to highlight accordingly
if (!result.containsKey(signature)) {
LOG.assertTrue(hierarchicalMethodSignature.getMethod().isValid());
result.put(signature, hierarchicalMethodSignature);
}
}
Aggregations