IDEA-173437 Completion suggestion is bad for ObjectUtils.tryCast

This commit is contained in:
peter
2017-05-26 14:42:42 +02:00
parent d50409dbbe
commit d30a552fcb
5 changed files with 39 additions and 4 deletions
@@ -39,6 +39,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -329,6 +330,8 @@ public class JavaCompletionSorting {
}
}
if (returnsUnboundType(item)) return MyResult.normal;
PsiType itemType = JavaCompletionUtil.getLookupElementType(item);
if (isExactlyExpected(item, itemType)) {
return AbstractExpectedTypeSkipper.skips(item, myLocation) ? MyResult.expectedNoSelect : MyResult.exactlyExpected;
@@ -361,16 +364,25 @@ public class JavaCompletionSorting {
if (JavaCompletionUtil.SUPER_METHOD_PARAMETERS.get(item) != null) {
return true;
}
if (itemType == null || itemType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) || hasUnboundTypeArguments(item)) {
if (itemType == null || itemType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
return false;
}
return ContainerUtil.exists(myExpectedTypes, info -> box(info.getType().getDeepComponentType()).equals(box(itemType)));
}
private static boolean hasUnboundTypeArguments(@NotNull LookupElement item) {
private boolean returnsUnboundType(@NotNull LookupElement item) {
JavaMethodCallElement call = item.as(JavaMethodCallElement.CLASS_CONDITION_KEY);
return call != null && !call.getInferenceSubstitutor().equals(PsiSubstitutor.EMPTY);
if (call != null && !call.getInferenceSubstitutor().equals(PsiSubstitutor.EMPTY)) {
PsiType callType = TypeConversionUtil.erasure(call.getSubstitutor().substitute(call.getObject().getReturnType()));
return callType == null || Arrays.stream(myExpectedTypes).noneMatch(i -> canBeExpected(callType, i));
}
return false;
}
private static boolean canBeExpected(PsiType callType, ExpectedTypeInfo info) {
PsiType expectedType = TypeConversionUtil.erasure(info.getType());
return expectedType != null && TypeConversionUtil.isAssignable(expectedType, callType);
}
private PsiType box(PsiType expectedType) {
@@ -0,0 +1,11 @@
public class Foo {
void foo(Object o) {
String s = Util.tryCast(o, <caret>);
}
}
class Util {
static <T> T tryCast(Object obj, Class<T> clazz) {}
}
@@ -211,7 +211,7 @@ public class SecondSmartTypeCompletionTest extends LightFixtureCompletionTestCas
public void testGlobalFactoryMethods() {
configure();
assertStringItems("Constants.SUBSTRING", "createExpected", "createSubGeneric", "createSubRaw", "createSubString");
assertStringItems("createExpected", "Constants.SUBSTRING", "createSubGeneric", "createSubRaw", "createSubString");
}
public void testEmptyMapPresentation() {
@@ -249,4 +249,10 @@ public void testConvertToObjectStream() {
configureByTestName();
myFixture.assertPreferredCompletionItems(0, "TimeUnit.DAYS");
}
public void testFreeGenericsAfterClassLiteral() {
configureByTestName();
myFixture.assertPreferredCompletionItems(0, "String.class", "tryCast");
}
}
@@ -1268,4 +1268,10 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
myFixture.type('\t');
checkResultByTestName();
}
public void testFreeGenericsAfterClassLiteral() {
configureByTestName();
myFixture.assertPreferredCompletionItems(0, "String.class", "tryCast");
}
}