From 02cabc4e849835259d9d837f86493c5e4ff7269c Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 26 Nov 2013 18:07:45 +0100 Subject: [PATCH] IDEA-117082 Anonymous class assigned to final field --- .../psi/scope/util/PsiScopesUtil.java | 21 ++++++++++++++++++- .../CovariantReturnTypeAnonymous.java | 20 ++++++++++++++++++ .../psi/resolve/ResolveMethod15Test.java | 11 +++++++++- 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/psi/resolve/method/generics/CovariantReturnTypeAnonymous.java diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java b/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java index 8556ee13e513..30f908426cd6 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java @@ -25,6 +25,7 @@ package com.intellij.psi.scope.util; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicatorProvider; +import com.intellij.openapi.util.Comparing; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.JavaResolveUtil; @@ -318,7 +319,13 @@ public class PsiScopesUtil { if (initializer instanceof PsiNewExpression) { final PsiAnonymousClass anonymousClass = ((PsiNewExpression)initializer).getAnonymousClass(); if (anonymousClass != null && type.equals(anonymousClass.getBaseClassType())) { - type = initializer.getType(); + final PsiMethod[] refMethods = anonymousClass.findMethodsByName(methodCall.getMethodExpression().getReferenceName(), false); + if (refMethods.length > 0) { + final PsiClass baseClass = PsiUtil.resolveClassInType(type); + if (baseClass != null && !hasCovariantOverriding(baseClass, refMethods)) { + type = initializer.getType(); + } + } } } } @@ -381,6 +388,18 @@ public class PsiScopesUtil { } } + private static boolean hasCovariantOverriding(PsiClass baseClass, PsiMethod[] refMethods) { + for (PsiMethod method : refMethods) { + final PsiType methodReturnType = method.getReturnType(); + for (PsiMethod superMethod : method.findSuperMethods(baseClass)) { + if (!Comparing.equal(methodReturnType, superMethod.getReturnType())) { + return true; + } + } + } + return false; + } + private static boolean processQualifierType(@NotNull final PsiType type, final MethodsProcessor processor, PsiManager manager, diff --git a/java/java-tests/testData/psi/resolve/method/generics/CovariantReturnTypeAnonymous.java b/java/java-tests/testData/psi/resolve/method/generics/CovariantReturnTypeAnonymous.java new file mode 100644 index 000000000000..b487a309af24 --- /dev/null +++ b/java/java-tests/testData/psi/resolve/method/generics/CovariantReturnTypeAnonymous.java @@ -0,0 +1,20 @@ +interface X { + A[] foo(); +} + +class A {} + +class B extends A {} + +class C { + final X x = new X() { + @Override + public B[] foo() { + return new B[0]; + } + }; + + B[] bar() { + return x.foo(); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethod15Test.java b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethod15Test.java index 36b1c4c9de63..788febf4da6e 100644 --- a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethod15Test.java +++ b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethod15Test.java @@ -7,7 +7,6 @@ import com.intellij.navigation.NavigationItem; import org.jetbrains.annotations.NonNls; import static org.junit.Assert.assertThat; import static org.hamcrest.core.IsInstanceOf.instanceOf; -import static org.junit.Assert.assertTrue; /** * @author dsl @@ -129,6 +128,16 @@ public class ResolveMethod15Test extends Resolve15TestCase { assertTrue(containingClass != null ? containingClass.getName() : null, containingClass instanceof PsiAnonymousClass); } + public void testCovariantReturnTypeAnonymous() throws Exception { + final PsiReference ref = configureByFile(); + assertThat(ref, instanceOf(PsiReferenceExpression.class)); + final PsiReferenceExpression refExpr = (PsiReferenceExpression)ref; + final PsiElement resolve = refExpr.resolve(); + assertTrue(resolve != null ? resolve.toString() : null, resolve instanceof PsiMethod); + final PsiClass containingClass = ((PsiMethod)resolve).getContainingClass(); + assertTrue(containingClass != null ? containingClass.getName() : null, !(containingClass instanceof PsiAnonymousClass)); + } + public void testFilterFixedVsVarargs1() throws Exception { final PsiReference ref = configureByFile(); assertThat(ref, instanceOf(PsiReferenceExpression.class));