diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java index 7bb994ddea86..4f228d0c875f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java @@ -35,6 +35,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Set; import java.util.function.Function; @@ -115,16 +116,40 @@ public class PreferByKindWeigher extends LookupElementWeigher { return psiClass -> preferClassIf(InheritanceUtil.isInheritor(psiClass, CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE)); } - if (psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiAnnotation.class).accepts(position)) { - final PsiAnnotation annotation = PsiTreeUtil.getParentOfType(position, PsiAnnotation.class); - assert annotation != null; - final PsiAnnotation.TargetType[] targets = AnnotationTargetUtil.getTargetsForLocation(annotation.getOwner()); - return psiClass -> preferClassIf(psiClass.isAnnotationType() && AnnotationTargetUtil.findAnnotationTarget(psiClass, targets) != null); + PsiElement parent = position.getParent(); + if (parent instanceof PsiJavaCodeReferenceElement) { + PsiElement refParent = parent.getParent(); + if (refParent instanceof PsiAnnotation) { + PsiAnnotation.TargetType[] targets = AnnotationTargetUtil.getTargetsForLocation(((PsiAnnotation)refParent).getOwner()); + return psiClass -> preferClassIf(psiClass.isAnnotationType() && AnnotationTargetUtil.findAnnotationTarget(psiClass, targets) != null); + } + if (refParent instanceof PsiTypeElement) { + List bounds = getTypeBounds((PsiTypeElement)refParent); + return psiClass -> preferClassIf(ContainerUtil.exists(bounds, bound -> InheritanceUtil.isInheritorOrSelf(psiClass, bound, true))); + } } return aClass -> MyResult.classNameOrGlobalStatic; } + private static List getTypeBounds(PsiTypeElement typeElement) { + PsiElement typeParent = typeElement.getParent(); + if (typeParent instanceof PsiReferenceParameterList) { + int index = Arrays.asList(((PsiReferenceParameterList)typeParent).getTypeParameterElements()).indexOf(typeElement); + PsiElement listParent = typeParent.getParent(); + if (index >= 0 && listParent instanceof PsiJavaCodeReferenceElement) { + PsiElement target = ((PsiJavaCodeReferenceElement)listParent).resolve(); + if (target instanceof PsiClass) { + PsiTypeParameter[] typeParameters = ((PsiClass)target).getTypeParameters(); + if (index < typeParameters.length) { + return ContainerUtil.mapNotNull(typeParameters[index].getExtendsListTypes(), PsiUtil::resolveClassInType); + } + } + } + } + return Collections.emptyList(); + } + static boolean isExceptionPosition(PsiElement position) { return IN_CATCH_TYPE.accepts(position) || IN_MULTI_CATCH_TYPE.accepts(position) || INSIDE_METHOD_THROWS_CLAUSE.accepts(position) || diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/PreferExpectedTypeArguments.java b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferExpectedTypeArguments.java new file mode 100644 index 000000000000..66f973fb6fe4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferExpectedTypeArguments.java @@ -0,0 +1,8 @@ +public class BlaExecutor implements BasicExecutor> { +} + +interface BasicExecutor { +} + +class BlaOperation extends Exception { +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionOrderingTest.groovy index c701a284ecf2..e435ff793d02 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionOrderingTest.groovy @@ -845,4 +845,8 @@ class Foo { checkPreferredItems 0, 'IllegalArgumentException', 'IllegalAccessException', 'IllegalStateException' } + void testPreferExpectedTypeArguments() { + checkPreferredItems 0, 'BlaOperation' + } + }