prefer T if Class<? extends T> is expected (IDEA-121339)

This commit is contained in:
peter
2014-04-18 22:37:29 +02:00
parent c9609013a4
commit c47713fe17
4 changed files with 42 additions and 7 deletions
@@ -34,6 +34,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.Function;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
@@ -425,20 +426,35 @@ public class JavaCompletionSorting {
}
private static class PreferExpected extends LookupElementWeigher {
private final boolean myAcceptClasses;
private final boolean myConstructorPossible;
private final ExpectedTypeInfo[] myExpectedTypes;
private final List<PsiType> myExpectedClasses = new SmartList<PsiType>();
public PreferExpected(boolean acceptClasses, ExpectedTypeInfo[] expectedTypes) {
public PreferExpected(boolean constructorPossible, ExpectedTypeInfo[] expectedTypes) {
super("expectedType");
myAcceptClasses = acceptClasses;
myConstructorPossible = constructorPossible;
myExpectedTypes = expectedTypes;
for (ExpectedTypeInfo info : expectedTypes) {
ContainerUtil.addIfNotNull(myExpectedClasses, PsiUtil.substituteTypeParameter(info.getDefaultType(), CommonClassNames.JAVA_LANG_CLASS, 0, false));
}
}
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement item) {
return item.getObject() instanceof PsiClass && !myAcceptClasses
? ExpectedTypeMatching.normal : getExpectedTypeMatching(item, myExpectedTypes);
public ExpectedTypeMatching weigh(@NotNull LookupElement item) {
if (item.getObject() instanceof PsiClass && !myConstructorPossible) {
PsiType itemType = JavaCompletionUtil.getLookupElementType(item);
if (itemType != null) {
for (PsiType expectedClass : myExpectedClasses) {
if (expectedClass.isAssignableFrom(itemType)) {
return ExpectedTypeMatching.expected;
}
}
}
return ExpectedTypeMatching.normal;
}
return getExpectedTypeMatching(item, myExpectedTypes);
}
}
@@ -330,7 +330,9 @@ public class JavaCompletionUtil {
PsiScopesUtil.processTypeDeclarations(qualifierType, member, new MyProcessor());
PsiType rawType = member instanceof PsiField ? ((PsiField) member).getType() : ((PsiMethod) member).getReturnType();
PsiType rawType = member instanceof PsiField ? ((PsiField) member).getType() :
member instanceof PsiMethod ? ((PsiMethod) member).getReturnType() :
JavaPsiFacade.getElementFactory(member.getProject()).createType((PsiClass)member);
return subst.get().substitute(rawType);
}
@@ -0,0 +1,12 @@
import java.lang.Exception;
public class Foo {
{
foo(X<caret>)
}
void foo(Class<? extends Throwable> c) {}
}
interface XIntf {}
class XClass {}
@@ -620,6 +620,11 @@ interface TxANotAnno {}
checkPreferredItems 0, 'MyEnum.BAR', 'MyEnum', 'MyEnum.FOO'
}
public void testPreferClassesOfExpectedClassType() {
myFixture.addClass "class XException extends Exception {}"
checkPreferredItems 0, 'XException', 'XClass', 'XIntf'
}
public void testGlobalStaticMemberStats() {
configureNoCompletion(getTestName(false) + ".java")
myFixture.complete(CompletionType.BASIC, 2)