IDEA-174659 Autocomplete generic parameters according to type restriction

This commit is contained in:
peter
2018-01-10 15:11:03 +01:00
parent fb27ac6664
commit 80875741b8
3 changed files with 42 additions and 5 deletions
@@ -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<PsiClass> bounds = getTypeBounds((PsiTypeElement)refParent);
return psiClass -> preferClassIf(ContainerUtil.exists(bounds, bound -> InheritanceUtil.isInheritorOrSelf(psiClass, bound, true)));
}
}
return aClass -> MyResult.classNameOrGlobalStatic;
}
private static List<PsiClass> 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) ||
@@ -0,0 +1,8 @@
public class BlaExecutor implements BasicExecutor<Bla<caret>> {
}
interface BasicExecutor<T extends Exception> {
}
class BlaOperation extends Exception {
}
@@ -845,4 +845,8 @@ class Foo {
checkPreferredItems 0, 'IllegalArgumentException', 'IllegalAccessException', 'IllegalStateException'
}
void testPreferExpectedTypeArguments() {
checkPreferredItems 0, 'BlaOperation'
}
}