From 3ee8b6d1e86cf888f3379e332811adae1a47189c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 24 Jun 2016 15:31:03 +0300 Subject: [PATCH] unrelated defaults: correct type if super classes come from different jdks (both 1.8 but of different versions) --- .../intellij/psi/util/PsiSuperMethodUtil.java | 37 ++++++++++++++++++- .../com/intellij/psi/impl/TypeCorrector.java | 32 ++-------------- .../codeInsight/multipleJdks/java7/p/I.java | 4 ++ ...latedDefaultsFromDifferentJdkVersions.java | 3 ++ .../codeInsight/multipleJdks/java8/p/I.java | 4 ++ ...latedDefaultsFromDifferentJdkVersions.java | 8 ++++ .../MultipleJdksHighlightingTest.java | 12 +++++- 7 files changed, 67 insertions(+), 33 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/multipleJdks/java7/p/I.java create mode 100644 java/java-tests/testData/codeInsight/multipleJdks/java7/p/UnrelatedDefaultsFromDifferentJdkVersions.java create mode 100644 java/java-tests/testData/codeInsight/multipleJdks/java8/p/I.java create mode 100644 java/java-tests/testData/codeInsight/multipleJdks/java8/p/UnrelatedDefaultsFromDifferentJdkVersions.java diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java index 2148bd45b3cb..641cb6e7ee88 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java @@ -15,11 +15,15 @@ */ package com.intellij.psi.util; +import com.intellij.openapi.roots.FileIndexFacade; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.containers.HashSet; import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.LinkedHashSet; import java.util.List; @@ -111,6 +115,7 @@ public class PsiSuperMethodUtil { public static Map> collectOverrideEquivalents(@NotNull PsiClass aClass) { final Map> overrideEquivalent = new THashMap>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY); + final GlobalSearchScope resolveScope = aClass.getResolveScope(); PsiClass[] supers = aClass.getSupers(); for (int i = 0; i < supers.length; i++) { PsiClass superClass = supers[i]; @@ -122,10 +127,12 @@ public class PsiSuperMethodUtil { if (subType) continue; final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY); for (HierarchicalMethodSignature hms : superClass.getVisibleSignatures()) { - final PsiMethod method = hms.getMethod(); + PsiMethod method = hms.getMethod(); if (MethodSignatureUtil.findMethodBySignature(aClass, method.getSignature(superClassSubstitutor), false) != null) continue; - final PsiClass containingClass = method.getContainingClass(); + final PsiClass containingClass = mapClass(method.getContainingClass(), resolveScope); if (containingClass == null) continue; + method = containingClass.findMethodBySignature(method, false); + if (method == null) continue; final PsiSubstitutor containingClassSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, aClass, PsiSubstitutor.EMPTY); if (containingClassSubstitutor == null) continue; final PsiSubstitutor finalSubstitutor = @@ -141,4 +148,30 @@ public class PsiSuperMethodUtil { } return overrideEquivalent; } + + @Nullable + public static PsiClass mapClass(PsiClass psiClass, final GlobalSearchScope resolveScope) { + if (psiClass == null) return null; + String qualifiedName = psiClass.getQualifiedName(); + if (qualifiedName == null) { + return psiClass; + } + + PsiFile file = psiClass.getContainingFile(); + if (file == null || !file.getViewProvider().isPhysical()) { + return psiClass; + } + + final VirtualFile vFile = file.getVirtualFile(); + if (vFile == null) { + return psiClass; + } + + final FileIndexFacade index = FileIndexFacade.getInstance(file.getProject()); + if (!index.isInSource(vFile) && !index.isInLibrarySource(vFile) && !index.isInLibraryClasses(vFile)) { + return psiClass; + } + + return JavaPsiFacade.getInstance(psiClass.getProject()).findClass(qualifiedName, resolveScope); + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java b/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java index f6521658c6dc..d9fcf6bc3c50 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java @@ -15,11 +15,10 @@ */ package com.intellij.psi.impl; -import com.intellij.openapi.roots.FileIndexFacade; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiSuperMethodUtil; import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -56,7 +55,7 @@ class TypeCorrector extends PsiTypeMapper { final PsiClassType.ClassResolveResult classResolveResult = classType.resolveGenerics(); final PsiClass psiClass = classResolveResult.getElement(); if (psiClass != null && classResolveResult.getSubstitutor() == PsiSubstitutor.EMPTY) { - final PsiClass mappedClass = mapClass(psiClass); + final PsiClass mappedClass = PsiSuperMethodUtil.mapClass(psiClass, myResolveScope); if (mappedClass == null || mappedClass == psiClass) return (T) classType; } } @@ -79,7 +78,7 @@ class TypeCorrector extends PsiTypeMapper { PsiUtilCore.ensureValid(psiClass); - final PsiClass mappedClass = mapClass(psiClass); + final PsiClass mappedClass = PsiSuperMethodUtil.mapClass(psiClass, myResolveScope); if (mappedClass == null) return classType; PsiClassType mappedType = new PsiCorrectedClassType(classType.getLanguageLevel(), @@ -89,31 +88,6 @@ class TypeCorrector extends PsiTypeMapper { return mappedType; } - @Nullable - private PsiClass mapClass(@NotNull PsiClass psiClass) { - String qualifiedName = psiClass.getQualifiedName(); - if (qualifiedName == null) { - return psiClass; - } - - PsiFile file = psiClass.getContainingFile(); - if (file == null || !file.getViewProvider().isPhysical()) { - return psiClass; - } - - final VirtualFile vFile = file.getVirtualFile(); - if (vFile == null) { - return psiClass; - } - - final FileIndexFacade index = FileIndexFacade.getInstance(file.getProject()); - if (!index.isInSource(vFile) && !index.isInLibrarySource(vFile) && !index.isInLibraryClasses(vFile)) { - return psiClass; - } - - return JavaPsiFacade.getInstance(psiClass.getProject()).findClass(qualifiedName, myResolveScope); - } - @NotNull private PsiSubstitutor mapSubstitutor(PsiClass originalClass, PsiClass mappedClass, PsiSubstitutor substitutor) { PsiTypeParameter[] typeParameters = mappedClass.getTypeParameters(); diff --git a/java/java-tests/testData/codeInsight/multipleJdks/java7/p/I.java b/java/java-tests/testData/codeInsight/multipleJdks/java7/p/I.java new file mode 100644 index 000000000000..30e62b5249e6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/multipleJdks/java7/p/I.java @@ -0,0 +1,4 @@ +package p; +interface I { + default void foo(); +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/multipleJdks/java7/p/UnrelatedDefaultsFromDifferentJdkVersions.java b/java/java-tests/testData/codeInsight/multipleJdks/java7/p/UnrelatedDefaultsFromDifferentJdkVersions.java new file mode 100644 index 000000000000..52e05186d644 --- /dev/null +++ b/java/java-tests/testData/codeInsight/multipleJdks/java7/p/UnrelatedDefaultsFromDifferentJdkVersions.java @@ -0,0 +1,3 @@ +package p; + +public abstract class A implements I {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/multipleJdks/java8/p/I.java b/java/java-tests/testData/codeInsight/multipleJdks/java8/p/I.java new file mode 100644 index 000000000000..30e62b5249e6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/multipleJdks/java8/p/I.java @@ -0,0 +1,4 @@ +package p; +interface I { + default void foo(); +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/multipleJdks/java8/p/UnrelatedDefaultsFromDifferentJdkVersions.java b/java/java-tests/testData/codeInsight/multipleJdks/java8/p/UnrelatedDefaultsFromDifferentJdkVersions.java new file mode 100644 index 000000000000..ab93746c9c7d --- /dev/null +++ b/java/java-tests/testData/codeInsight/multipleJdks/java8/p/UnrelatedDefaultsFromDifferentJdkVersions.java @@ -0,0 +1,8 @@ +package p; + +class EmptyValueIterator extends A implements ValueIterator { + +} + +interface ValueIterator extends I {} + diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/MultipleJdksHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/MultipleJdksHighlightingTest.java index 874522ec38f7..4c6c21761f55 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/MultipleJdksHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/MultipleJdksHighlightingTest.java @@ -18,7 +18,6 @@ package com.intellij.codeInsight; import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.module.Module; -import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.pom.java.LanguageLevel; @@ -26,7 +25,6 @@ import com.intellij.testFramework.IdeaTestUtil; import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; import com.intellij.testFramework.fixtures.*; -import com.intellij.util.Consumer; public class MultipleJdksHighlightingTest extends UsefulTestCase { @@ -197,6 +195,16 @@ public class MultipleJdksHighlightingTest extends UsefulTestCase { myFixture.checkHighlighting(); } + public void testUnrelatedDefaultsFromDifferentJdkVersions() throws Exception { + ModuleRootModificationUtil.addDependency(myJava8Module, myJava7Module); + myFixture.copyFileToProject("java7/p/I.java"); + myFixture.copyFileToProject("java8/p/I.java"); + + final String testName = getTestName(false); + myFixture.configureByFiles("java8/p/" + testName + ".java", "java7/p/" + testName + ".java"); + myFixture.checkHighlighting(); + } + private void doTestWithoutLibrary() { final String name = getTestName(false); myFixture.configureByFiles("java7/p/" + name + ".java", "java8/p/" + name + ".java");