Skip to content

Commit a17e9bf

Browse files
committed
some merge
1 parent 2450b29 commit a17e9bf

38 files changed

Lines changed: 5028 additions & 3333 deletions

java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java

Lines changed: 184 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.ArrayList;
2222
import java.util.Arrays;
2323
import java.util.Collection;
24+
import java.util.LinkedHashSet;
2425
import java.util.List;
2526
import java.util.Map;
2627
import java.util.Set;
@@ -46,6 +47,7 @@
4647
import com.intellij.pom.java.LanguageLevel;
4748
import com.intellij.psi.*;
4849
import com.intellij.psi.impl.PsiClassImplUtil;
50+
import com.intellij.psi.impl.PsiSuperMethodImplUtil;
4951
import com.intellij.psi.search.GlobalSearchScope;
5052
import com.intellij.psi.search.PsiShortNamesCache;
5153
import com.intellij.psi.search.searches.ReferencesSearch;
@@ -86,7 +88,13 @@ static HighlightInfo checkInferredTypeArguments(PsiTypeParameterListOwner listOw
8688
@Nullable
8789
static HighlightInfo checkInferredTypeArguments(PsiTypeParameter[] typeParameters, PsiElement call, PsiSubstitutor substitutor)
8890
{
89-
final Pair<PsiTypeParameter, PsiType> inferredTypeArgument = GenericsUtil.findTypeParameterWithBoundError(typeParameters, substitutor, call, false);
91+
return checkInferredTypeArguments(typeParameters, call, substitutor, false);
92+
}
93+
94+
@Nullable
95+
static HighlightInfo checkInferredTypeArguments(PsiTypeParameter[] typeParameters, PsiElement call, PsiSubstitutor substitutor, boolean allowUncheckedConversion)
96+
{
97+
final Pair<PsiTypeParameter, PsiType> inferredTypeArgument = GenericsUtil.findTypeParameterWithBoundError(typeParameters, substitutor, call, allowUncheckedConversion);
9098
if(inferredTypeArgument != null)
9199
{
92100
final PsiType extendsType = inferredTypeArgument.second;
@@ -421,15 +429,9 @@ private static HighlightInfo checkInterfaceMultipleInheritance(PsiClass aClass,
421429
Set<PsiClass> visited,
422430
TextRange textRange)
423431
{
424-
final PsiClassType[] superTypes = aClass.getSuperTypes();
425-
for(PsiClassType superType : superTypes)
432+
final List<PsiClassType.ClassResolveResult> superTypes = PsiClassImplUtil.getScopeCorrectedSuperTypes(aClass, place.getResolveScope());
433+
for(PsiClassType.ClassResolveResult result : superTypes)
426434
{
427-
superType = PsiClassImplUtil.correctType(superType, place.getResolveScope());
428-
if(superType == null)
429-
{
430-
continue;
431-
}
432-
final PsiClassType.ClassResolveResult result = superType.resolveGenerics();
433435
final PsiClass superClass = result.getElement();
434436
if(superClass == null || visited.contains(superClass))
435437
{
@@ -521,55 +523,185 @@ static HighlightInfo checkDefaultMethodOverrideEquivalentToObjectNonPrivate(@Not
521523

522524
static HighlightInfo checkUnrelatedDefaultMethods(@NotNull PsiClass aClass, @NotNull Collection<HierarchicalMethodSignature> signaturesWithSupers, @NotNull PsiIdentifier classIdentifier)
523525
{
524-
for(HierarchicalMethodSignature methodSignature : signaturesWithSupers)
526+
final Map<MethodSignature, Set<PsiMethod>> overrideEquivalent = new THashMap<MethodSignature, Set<PsiMethod>>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY);
527+
PsiClass[] supers = aClass.getSupers();
528+
for(int i = 0; i < supers.length; i++)
525529
{
526-
final PsiMethod method = methodSignature.getMethod();
527-
final boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT);
528-
if(method.hasModifierProperty(PsiModifier.DEFAULT) || isAbstract)
530+
PsiClass superClass = supers[i];
531+
boolean subType = false;
532+
for(int j = 0; j < supers.length; j++)
533+
{
534+
if(j == i)
535+
{
536+
continue;
537+
}
538+
subType |= supers[j].isInheritor(supers[i], true);
539+
}
540+
if(subType)
529541
{
542+
continue;
543+
}
544+
for(HierarchicalMethodSignature hms : superClass.getVisibleSignatures())
545+
{
546+
final PsiMethod method = hms.getMethod();
547+
if(aClass.findMethodsBySignature(method, false).length > 0)
548+
{
549+
continue;
550+
}
530551
final PsiClass containingClass = method.getContainingClass();
531-
List<HierarchicalMethodSignature> superSignatures = methodSignature.getSuperSignatures();
532-
if(!superSignatures.isEmpty())
552+
if(containingClass == null)
553+
{
554+
continue;
555+
}
556+
final PsiSubstitutor containingClassSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, aClass, PsiSubstitutor.EMPTY);
557+
if(containingClassSubstitutor == null)
558+
{
559+
continue;
560+
}
561+
final PsiSubstitutor finalSubstitutor = PsiSuperMethodImplUtil.obtainFinalSubstitutor(containingClass, containingClassSubstitutor, hms.getSubstitutor(), false);
562+
final MethodSignatureBackedByPsiMethod signature = MethodSignatureBackedByPsiMethod.create(method, finalSubstitutor, false);
563+
Set<PsiMethod> methods = overrideEquivalent.get(signature);
564+
if(methods == null)
565+
{
566+
methods = new LinkedHashSet<PsiMethod>();
567+
overrideEquivalent.put(signature, methods);
568+
}
569+
methods.add(method);
570+
}
571+
}
572+
573+
final boolean isInterface = aClass.isInterface();
574+
for(Set<PsiMethod> overrideEquivalentMethods : overrideEquivalent.values())
575+
{
576+
if(overrideEquivalentMethods.size() <= 1)
577+
{
578+
continue;
579+
}
580+
List<PsiMethod> defaults = null;
581+
List<PsiMethod> astracts = null;
582+
boolean hasConcrete = false;
583+
for(PsiMethod method : overrideEquivalentMethods)
584+
{
585+
final boolean isDefault = method.hasModifierProperty(PsiModifier.DEFAULT);
586+
final boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT);
587+
if(isDefault)
533588
{
534-
for(HierarchicalMethodSignature signature : superSignatures)
589+
if(defaults == null)
535590
{
536-
final PsiMethod superMethod = signature.getMethod();
537-
final PsiClass superContainingClass = superMethod.getContainingClass();
538-
if(containingClass != null && superContainingClass != null && !InheritanceUtil.isInheritorOrSelf(containingClass, superContainingClass, true))
539-
{
540-
final boolean isDefault = superMethod.hasModifierProperty(PsiModifier.DEFAULT);
541-
if(!aClass.hasModifierProperty(PsiModifier.ABSTRACT) && !isDefault && !isAbstract)
542-
{
543-
final String message = JavaErrorMessages.message(aClass instanceof PsiEnumConstantInitializer ? "enum.constant.should.implement.method" : "class.must.be.abstract",
544-
HighlightUtil.formatClass(superContainingClass), JavaHighlightUtil.formatMethod(superMethod), HighlightUtil.formatClass(superContainingClass, false));
545-
final HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(classIdentifier).descriptionAndTooltip(message).create();
546-
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createImplementMethodsFix(aClass));
547-
return info;
548-
}
591+
defaults = new ArrayList<PsiMethod>(2);
592+
}
593+
defaults.add(method);
594+
}
595+
if(isAbstract)
596+
{
597+
if(astracts == null)
598+
{
599+
astracts = new ArrayList<PsiMethod>(2);
600+
}
601+
astracts.add(method);
602+
}
603+
hasConcrete |= !isDefault && !isAbstract;
604+
}
549605

550-
if(isDefault || !isAbstract && superMethod.hasModifierProperty(PsiModifier.ABSTRACT))
551-
{
552-
final String message = isDefault && !isAbstract ? " inherits unrelated defaults for " : " inherits abstract and default for ";
553-
final String inheritUnrelatedDefaultsMessage = HighlightUtil.formatClass(aClass) +
554-
message +
555-
JavaHighlightUtil.formatMethod(method) +
556-
" from types " +
557-
HighlightUtil.formatClass(containingClass) +
558-
" and " +
559-
HighlightUtil.formatClass(superContainingClass);
560-
final HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(classIdentifier).descriptionAndTooltip(inheritUnrelatedDefaultsMessage)
561-
.create();
562-
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createImplementMethodsFix(aClass));
563-
return info;
564-
}
565-
}
606+
if(!hasConcrete && defaults != null)
607+
{
608+
final PsiMethod defaultMethod = defaults.get(0);
609+
final PsiClass defaultMethodContainingClass = defaultMethod.getContainingClass();
610+
if(defaultMethodContainingClass == null)
611+
{
612+
continue;
613+
}
614+
final PsiMethod unrelatedMethod = astracts != null ? astracts.get(0) : defaults.get(1);
615+
final PsiClass unrelatedMethodContainingClass = unrelatedMethod.getContainingClass();
616+
if(unrelatedMethodContainingClass == null)
617+
{
618+
continue;
619+
}
620+
if(!aClass.hasModifierProperty(PsiModifier.ABSTRACT) && astracts != null && unrelatedMethodContainingClass.isInterface())
621+
{
622+
if(defaultMethodContainingClass.isInheritor(unrelatedMethodContainingClass, true) && MethodSignatureUtil.isSubsignature(unrelatedMethod.getSignature(PsiSubstitutor.EMPTY),
623+
defaultMethod.getSignature(PsiSubstitutor.EMPTY)))
624+
{
625+
continue;
566626
}
627+
final String key = aClass instanceof PsiEnumConstantInitializer ? "enum.constant.should.implement.method" : "class.must.be.abstract";
628+
final String message = JavaErrorMessages.message(key, HighlightUtil.formatClass(aClass, false), JavaHighlightUtil.formatMethod(astracts.get(0)),
629+
HighlightUtil.formatClass(unrelatedMethodContainingClass, false));
630+
final HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(classIdentifier).descriptionAndTooltip(message).create();
631+
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createImplementMethodsFix(aClass));
632+
return info;
633+
}
634+
if(isInterface || astracts == null || unrelatedMethodContainingClass.isInterface())
635+
{
636+
if(defaultMethodContainingClass.isInheritor(unrelatedMethodContainingClass, true) || unrelatedMethodContainingClass.isInheritor(defaultMethodContainingClass, true))
637+
{
638+
continue;
639+
}
640+
final String message = astracts != null ? " inherits abstract and default for " : " inherits unrelated defaults for ";
641+
final HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(classIdentifier).descriptionAndTooltip(HighlightUtil.formatClass(aClass) +
642+
message +
643+
JavaHighlightUtil.formatMethod(defaultMethod) +
644+
" from types " +
645+
HighlightUtil.formatClass(defaultMethodContainingClass) +
646+
" and " +
647+
HighlightUtil.formatClass(unrelatedMethodContainingClass)).create();
648+
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createImplementMethodsFix(aClass));
649+
return info;
567650
}
568651
}
569652
}
570653
return null;
571654
}
572655

656+
static HighlightInfo checkUnrelatedConcrete(@NotNull PsiClass psiClass, @NotNull PsiIdentifier classIdentifier)
657+
{
658+
final PsiClass superClass = psiClass.getSuperClass();
659+
if(superClass != null && superClass.hasTypeParameters())
660+
{
661+
final Collection<HierarchicalMethodSignature> visibleSignatures = superClass.getVisibleSignatures();
662+
final Map<MethodSignature, PsiMethod> overrideEquivalent = new THashMap<MethodSignature, PsiMethod>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY);
663+
for(HierarchicalMethodSignature hms : visibleSignatures)
664+
{
665+
final PsiMethod method = hms.getMethod();
666+
if(method.hasModifierProperty(PsiModifier.ABSTRACT) || method.hasModifierProperty(PsiModifier.DEFAULT))
667+
{
668+
continue;
669+
}
670+
if(psiClass.findMethodsBySignature(method, false).length > 0)
671+
{
672+
continue;
673+
}
674+
final PsiClass containingClass = method.getContainingClass();
675+
if(containingClass == null)
676+
{
677+
continue;
678+
}
679+
final PsiSubstitutor containingClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(containingClass, psiClass, PsiSubstitutor.EMPTY);
680+
final PsiSubstitutor finalSubstitutor = PsiSuperMethodImplUtil.obtainFinalSubstitutor(containingClass, containingClassSubstitutor, hms.getSubstitutor(), false);
681+
final MethodSignatureBackedByPsiMethod signature = MethodSignatureBackedByPsiMethod.create(method, finalSubstitutor, false);
682+
final PsiMethod foundMethod = overrideEquivalent.get(signature);
683+
PsiClass foundMethodContainingClass;
684+
if(foundMethod != null &&
685+
!foundMethod.hasModifierProperty(PsiModifier.ABSTRACT) &&
686+
!foundMethod.hasModifierProperty(PsiModifier.DEFAULT) &&
687+
(foundMethodContainingClass = foundMethod.getContainingClass()) != null)
688+
{
689+
final String description = "Methods " +
690+
JavaHighlightUtil.formatMethod(foundMethod) + " from " + HighlightUtil.formatClass(foundMethodContainingClass) +
691+
" and " +
692+
JavaHighlightUtil.formatMethod(method) + " from " + HighlightUtil.formatClass(containingClass) +
693+
" are inherited with the same signature";
694+
695+
final HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(classIdentifier).descriptionAndTooltip(description).create();
696+
//todo override fix
697+
return info;
698+
}
699+
overrideEquivalent.put(signature, method);
700+
}
701+
}
702+
return null;
703+
}
704+
573705
@Nullable
574706
private static HighlightInfo checkSameErasureNotSubSignatureInner(@NotNull HierarchicalMethodSignature signature,
575707
@NotNull PsiManager manager,
@@ -1660,29 +1792,15 @@ static HighlightInfo checkInferredIntersections(PsiSubstitutor substitutor, Text
16601792
{
16611793
for(Map.Entry<PsiTypeParameter, PsiType> typeEntry : substitutor.getSubstitutionMap().entrySet())
16621794
{
1795+
final String parameterName = typeEntry.getKey().getName();
16631796
final PsiType type = typeEntry.getValue();
16641797
if(type instanceof PsiIntersectionType)
16651798
{
1666-
final PsiType[] conjuncts = ((PsiIntersectionType) type).getConjuncts();
1667-
for(int i = 0; i < conjuncts.length; i++)
1799+
final String conflictingConjunctsMessage = ((PsiIntersectionType) type).getConflictingConjunctsMessage();
1800+
if(conflictingConjunctsMessage != null)
16681801
{
1669-
PsiClass conjunct = PsiUtil.resolveClassInClassTypeOnly(conjuncts[i]);
1670-
if(conjunct != null && !conjunct.isInterface())
1671-
{
1672-
for(int i1 = i + 1; i1 < conjuncts.length; i1++)
1673-
{
1674-
PsiClass oppositeConjunct = PsiUtil.resolveClassInClassTypeOnly(conjuncts[i1]);
1675-
if(oppositeConjunct != null && !oppositeConjunct.isInterface())
1676-
{
1677-
if(!conjunct.isInheritor(oppositeConjunct, true) && !oppositeConjunct.isInheritor(conjunct, true))
1678-
{
1679-
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip("Type parameter " + typeEntry.getKey().getName() + " has incompatible upper " +
1680-
"bounds: " +
1681-
conjunct.getName() + " and " + oppositeConjunct.getName()).range(ref).create();
1682-
}
1683-
}
1684-
}
1685-
}
1802+
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip("Type parameter " + parameterName + " has incompatible upper bounds: " +
1803+
conflictingConjunctsMessage).range(ref).create();
16861804
}
16871805
}
16881806
}
@@ -1766,4 +1884,5 @@ public static HighlightInfo checkTypeParameterOverrideEquivalentMethods(PsiClass
17661884
}
17671885
return null;
17681886
}
1769-
}
1887+
}
1888+

0 commit comments

Comments
 (0)