From e32cc027256e16340c0c57a28002b47d77750ff6 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 5 Jan 2016 18:52:02 +0100 Subject: [PATCH] inherit unrelated concrete methods with same signature error (IDEA-67838) --- .../impl/analysis/GenericsHighlightUtil.java | 42 +++++++++++++++++++ .../impl/analysis/HighlightVisitorImpl.java | 4 ++ .../psi/impl/PsiSuperMethodImplUtil.java | 8 ++-- ...latedConcreteMethodsWithSameSignature.java | 18 ++++++++ .../daemon/LightAdvHighlightingJdk6Test.java | 1 + 5 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/InheritUnrelatedConcreteMethodsWithSameSignature.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 9ea3c44e6a6b..ac51328320b0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -33,6 +33,7 @@ import com.intellij.openapi.util.TextRange; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.impl.PsiClassImplUtil; +import com.intellij.psi.impl.PsiSuperMethodImplUtil; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.psi.search.searches.ReferencesSearch; @@ -490,6 +491,47 @@ public class GenericsHighlightUtil { return null; } + static HighlightInfo checkUnrelatedConcrete(@NotNull PsiClass psiClass, + @NotNull PsiIdentifier classIdentifier) { + final PsiClass superClass = psiClass.getSuperClass(); + if (superClass != null && superClass.hasTypeParameters()) { + final Collection visibleSignatures = superClass.getVisibleSignatures(); + final Map overrideEquivalent = new THashMap(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY); + for (HierarchicalMethodSignature hms : visibleSignatures) { + final PsiMethod method = hms.getMethod(); + if (method.hasModifierProperty(PsiModifier.ABSTRACT) || method.hasModifierProperty(PsiModifier.DEFAULT)) continue; + if (psiClass.findMethodsBySignature(method, false).length > 0) continue; + final PsiClass containingClass = method.getContainingClass(); + if (containingClass == null) continue; + final PsiSubstitutor containingClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(containingClass, psiClass, PsiSubstitutor.EMPTY); + final PsiSubstitutor finalSubstitutor = PsiSuperMethodImplUtil.obtainFinalSubstitutor(containingClass, containingClassSubstitutor, hms.getSubstitutor(), false); + final MethodSignatureBackedByPsiMethod signature = MethodSignatureBackedByPsiMethod.create(method, finalSubstitutor, false); + final PsiMethod foundMethod = overrideEquivalent.get(signature); + PsiClass foundMethodContainingClass; + if (foundMethod != null && + !foundMethod.hasModifierProperty(PsiModifier.ABSTRACT) && + !foundMethod.hasModifierProperty(PsiModifier.DEFAULT) && + (foundMethodContainingClass = foundMethod.getContainingClass()) != null) { + final String description = + "Methods " + + JavaHighlightUtil.formatMethod(foundMethod) + " from " + HighlightUtil.formatClass(foundMethodContainingClass) + + " and " + + JavaHighlightUtil.formatMethod(method) + " from " + HighlightUtil.formatClass(containingClass) + + " are inherited with the same signature"; + + final HighlightInfo info = HighlightInfo + .newHighlightInfo(HighlightInfoType.ERROR).range(classIdentifier).descriptionAndTooltip( + description) + .create(); + //todo override fix + return info; + } + overrideEquivalent.put(signature, method); + } + } + return null; + } + @Nullable private static HighlightInfo checkSameErasureNotSubSignatureInner(@NotNull HierarchicalMethodSignature signature, @NotNull PsiManager manager, diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 97c7a57ad88a..68710e22e50e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -633,6 +633,10 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults() && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) { myHolder.add(GenericsHighlightUtil.checkUnrelatedDefaultMethods(aClass, aClass.getVisibleSignatures(), identifier)); } + + if (!myHolder.hasErrorResults()) { + myHolder.add(GenericsHighlightUtil.checkUnrelatedConcrete(aClass, identifier)); + } } else if (parent instanceof PsiMethod) { PsiMethod method = (PsiMethod)parent; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java index 3f6fa62e7a32..66421a109e0a 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java @@ -374,10 +374,10 @@ public class PsiSuperMethodImplUtil { } @NotNull - private static PsiSubstitutor obtainFinalSubstitutor(@NotNull PsiClass superClass, - @NotNull PsiSubstitutor superSubstitutor, - @NotNull PsiSubstitutor derivedSubstitutor, - boolean inRawContext) { + public static PsiSubstitutor obtainFinalSubstitutor(@NotNull PsiClass superClass, + @NotNull PsiSubstitutor superSubstitutor, + @NotNull PsiSubstitutor derivedSubstitutor, + boolean inRawContext) { if (inRawContext) { Set typeParams = superSubstitutor.getSubstitutionMap().keySet(); PsiElementFactory factory = JavaPsiFacade.getElementFactory(superClass.getProject()); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/InheritUnrelatedConcreteMethodsWithSameSignature.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/InheritUnrelatedConcreteMethodsWithSameSignature.java new file mode 100644 index 000000000000..bc538b20e1dd --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/InheritUnrelatedConcreteMethodsWithSameSignature.java @@ -0,0 +1,18 @@ +class A { + public void foo(T t){} +} + +class B extends A { + public void foo(String s) {} +} +class C extends B {} + +class D { + public void foo(T t){} + public void foo(String s) {} +} + +class E extends D {} +class F extends D { + public void foo(String s) {} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java index 19992665ed5a..9eae0be5dfd4 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java @@ -60,4 +60,5 @@ public class LightAdvHighlightingJdk6Test extends LightDaemonAnalyzerTestCase { public void testInitializedBeforeUsed() { doTest(false, false); } public void testUnreachableAssignments() { doTest(false, false); } public void testCompileTypeConstantsAccessibleFromStaticFieldInitializers() { doTest(false, false);} + public void testInheritUnrelatedConcreteMethodsWithSameSignature() { doTest(false, false);} }