From 504c2c3867ffd7d2cc78fbb16479917821c37e8e Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 30 Apr 2013 15:23:36 +0200 Subject: [PATCH] generics: do not prefer type with more bounds when additional bounds are just subtypes of the rest (IDEA-67668) --- .../JavaMethodsConflictResolver.java | 63 +++++++++++++------ .../AmbiguousMethodCallIDEA67668.java | 17 +++++ .../daemon/LightAdvHighlightingJdk7Test.java | 1 + 3 files changed, 61 insertions(+), 20 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/AmbiguousMethodCallIDEA67668.java diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java index 0eace78fea45..6f1b08d3e3ca 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java @@ -630,28 +630,31 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ PsiType type2, PsiTypeParameter p1, PsiTypeParameter p2) { - Specifics specifics = checkSubtyping(TypeConversionUtil.erasure(PsiSubstitutor.EMPTY.substitute(p1)), - TypeConversionUtil.erasure(PsiSubstitutor.EMPTY.substitute(p2)), method1, method2); - if (specifics == Specifics.NEITHER) { - final Set resolved1 = new HashSet(); - for (PsiJavaCodeReferenceElement referenceElement : p1.getExtendsList().getReferenceElements()) { - final PsiElement resolve = referenceElement.resolve(); - if (resolve != null) { - resolved1.add(resolve); - } + final Set resolved1 = new HashSet(); + for (PsiClassType referenceElement : p1.getExtendsList().getReferencedTypes()) { + final PsiClass resolve = referenceElement.resolve(); + if (resolve != null) { + resolved1.add(resolve); } - - final Set resolved2 = new HashSet(); - for (PsiJavaCodeReferenceElement referenceElement : p2.getExtendsList().getReferenceElements()) { - final PsiElement resolve = referenceElement.resolve(); - if (resolve != null) { - resolved2.add(resolve); - } - } - - if (resolved1.size() > resolved2.size() && resolved1.containsAll(resolved2)) return Specifics.FIRST; - if (resolved2.size() > resolved1.size() && resolved2.containsAll(resolved1)) return Specifics.SECOND; } + + final Set resolved2 = new HashSet(); + for (PsiClassType referenceElement : p2.getExtendsList().getReferencedTypes()) { + final PsiClass resolve = referenceElement.resolve(); + if (resolve != null) { + resolved2.add(resolve); + } + } + + Specifics specifics = null; + if (resolved1.size() > resolved2.size()){ + specifics = checkExtendsList(resolved1, resolved2, Specifics.FIRST); + } else if (resolved2.size() > resolved1.size()) { + specifics = checkExtendsList(resolved2, resolved1, Specifics.SECOND); + } + if (specifics != null) return specifics; + specifics = checkSubtyping(TypeConversionUtil.erasure(PsiSubstitutor.EMPTY.substitute(p1)), + TypeConversionUtil.erasure(PsiSubstitutor.EMPTY.substitute(p2)), method1, method2); if (specifics != null) { return specifics; } else { @@ -661,6 +664,26 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ } } + private static Specifics checkExtendsList(Set resolved1, + Set resolved2, + Specifics preferred) { + if (resolved1.containsAll(resolved2)){ + resolved1.removeAll(resolved2); + for (Iterator iterator = resolved1.iterator(); iterator.hasNext(); ) { + PsiClass psiClass = iterator.next(); + for (PsiClass aClass : resolved2) { + if (InheritanceUtil.isInheritorOrSelf(aClass, psiClass, true)) { + iterator.remove(); + break; + } + } + } + if (!resolved1.isEmpty()) return preferred; + return Specifics.NEITHER; + } + return null; + } + private PsiSubstitutor calculateMethodSubstitutor(final PsiTypeParameter[] typeParameters, final PsiType[] types1, final PsiType[] types2, diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/AmbiguousMethodCallIDEA67668.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/AmbiguousMethodCallIDEA67668.java new file mode 100644 index 000000000000..2de2b0e4f5d9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/AmbiguousMethodCallIDEA67668.java @@ -0,0 +1,17 @@ +import java.util.Collection; +import java.util.List; + +interface A +{ + & List> void foo(S x); + > void foo(S x); +} + + +class B +{ + public static void main(String[] args) { + A a = null; + a.foo(null); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java index 9571dea1aec0..c80cd989778c 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java @@ -170,6 +170,7 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase { public void testWrongArgsAndUnknownTypeParams() { doTest(false, false); } public void testAmbiguousMethodCallIDEA97983() { doTest(false, false); } public void testAmbiguousMethodCallIDEA100314() { doTest(false, false); } + public void testAmbiguousMethodCallIDEA67668() { doTest(false, false); } public void testInstanceMemberNotAccessibleInStaticContext() { doTest(false, false); } public void testRejectedTypeParamsForConstructor() { doTest(false, false); } public void testAnnotationArgs() throws Exception { doTest(false, false);}