From 4b53ed7039df972178400b61c1252fc52ca7653d Mon Sep 17 00:00:00 2001 From: Peter Gromov Date: Thu, 17 Sep 2009 21:03:01 +0400 Subject: [PATCH] local variables and recursion checks are more important for relevance than expected types in basic completion --- ....java => AbstractExpectedTypeSkipper.java} | 10 +- .../completion/JavaCompletionUtil.java | 16 +--- .../completion/PreferDefaultTypeWeigher.java | 91 +++++++++++++++++++ .../completion/PreferExpectedTypeWeigher.java | 70 ++------------ .../completion/RecursionWeigher.java | 2 +- resources/src/META-INF/IdeaPlugin.xml | 10 +- 6 files changed, 115 insertions(+), 84 deletions(-) rename java/java-impl/src/com/intellij/codeInsight/completion/{SkipAbstractExpectedTypeWeigher.java => AbstractExpectedTypeSkipper.java} (89%) create mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/PreferDefaultTypeWeigher.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/SkipAbstractExpectedTypeWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/AbstractExpectedTypeSkipper.java similarity index 89% rename from java/java-impl/src/com/intellij/codeInsight/completion/SkipAbstractExpectedTypeWeigher.java rename to java/java-impl/src/com/intellij/codeInsight/completion/AbstractExpectedTypeSkipper.java index 7ddc29f94ff8..17e40e36f380 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/SkipAbstractExpectedTypeWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/AbstractExpectedTypeSkipper.java @@ -15,9 +15,9 @@ import com.intellij.psi.util.TypeConversionUtil; /** * @author peter */ -public class SkipAbstractExpectedTypeWeigher extends CompletionPreselectSkipper { +public class AbstractExpectedTypeSkipper extends CompletionPreselectSkipper { - enum Result { + private enum Result { NON_DEFAULT, STRING, ABSTRACT, @@ -26,10 +26,14 @@ public class SkipAbstractExpectedTypeWeigher extends CompletionPreselectSkipper @Override public boolean skipElement(LookupElement element, CompletionLocation location) { + return skips(element, location); + } + + public static boolean skips(LookupElement element, CompletionLocation location) { return getSkippingStatus(element, location) != Result.ACCEPT; } - public static Result getSkippingStatus(final LookupElement item, final CompletionLocation location) { + private static Result getSkippingStatus(final LookupElement item, final CompletionLocation location) { if (location.getCompletionType() != CompletionType.SMART) return Result.ACCEPT; final PsiExpression expression = PsiTreeUtil.getParentOfType(location.getCompletionParameters().getPosition(), PsiExpression.class); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index ecd455112f26..f3982162c27a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -680,7 +680,7 @@ public class JavaCompletionUtil { } @Nullable - public static PsiType getPsiType(final Object o) { + private static PsiType getPsiType(final Object o) { if (o instanceof PsiVariable) { return ((PsiVariable)o).getType(); } @@ -768,28 +768,18 @@ public class JavaCompletionUtil { @Nullable public static PsiType getLookupElementType(final LookupElement element) { - PsiType qualifierType = null; final TypedLookupItem typed = element.as(TypedLookupItem.class); if (typed != null) { return typed.getType(); } - final Object o = element.getObject(); - if (o instanceof PsiVariable) { - qualifierType = ((PsiVariable)o).getType(); - } - else if (o instanceof PsiMethod) { - qualifierType = ((PsiMethod)o).getReturnType(); - } - else if (o instanceof PsiExpression) { - qualifierType = ((PsiExpression) o).getType(); - } + final PsiType qualifierType = getPsiType(element.getObject()); final LookupItem lookupItem = element.as(LookupItem.class); if (lookupItem != null) { final PsiSubstitutor substitutor = (PsiSubstitutor)lookupItem.getAttribute(LookupItem.SUBSTITUTOR); if (substitutor != null) { - qualifierType = substitutor.substitute(qualifierType); + return substitutor.substitute(qualifierType); } } return qualifierType; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferDefaultTypeWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferDefaultTypeWeigher.java new file mode 100644 index 000000000000..86dc2de5a419 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferDefaultTypeWeigher.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved. + * Use is subject to license terms. + */ +package com.intellij.codeInsight.completion; + +import com.intellij.codeInsight.ExpectedTypeInfo; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.openapi.util.NullableLazyKey; +import com.intellij.openapi.util.Pair; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiType; +import com.intellij.psi.PsiTypeParameter; +import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.NullableFunction; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author peter +*/ +public class PreferDefaultTypeWeigher extends CompletionWeigher { + private static final NullableLazyKey TYPE_PARAMETER = NullableLazyKey.create("expectedTypes", new NullableFunction() { + @Nullable + public PsiTypeParameter fun(final CompletionLocation location) { + final Pair pair = + JavaSmartCompletionContributor.getTypeParameterInfo(location.getCompletionParameters().getPosition()); + if (pair == null) return null; + return pair.first.getTypeParameters()[pair.second.intValue()]; + } + }); + + + private enum MyResult { + normal, + exactlyExpected, + ofDefaultType, + exactlyDefault, + expectedNoSelect + } + + public MyResult weigh(@NotNull final LookupElement item, final CompletionLocation location) { + final Object object = item.getObject(); + if (location.getCompletionType() != CompletionType.SMART) return MyResult.normal; + + if (object instanceof PsiClass) { + final PsiTypeParameter parameter = TYPE_PARAMETER.getValue(location); + if (parameter != null && object.equals(PsiUtil.resolveClassInType(TypeConversionUtil.typeParameterErasure(parameter)))) { + return MyResult.exactlyExpected; + } + } + + ExpectedTypeInfo[] expectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location); + if (expectedInfos == null) return MyResult.normal; + + PsiType itemType = JavaCompletionUtil.getLookupElementType(item); + if (itemType == null || !itemType.isValid()) return MyResult.normal; + + if (object instanceof PsiClass) { + for (final ExpectedTypeInfo info : expectedInfos) { + if (TypeConversionUtil.erasure(info.getType().getDeepComponentType()).equals(TypeConversionUtil.erasure(itemType))) { + return AbstractExpectedTypeSkipper.skips(item, location) ? MyResult.expectedNoSelect : MyResult.exactlyExpected; + } + } + } + + for (final ExpectedTypeInfo expectedInfo : expectedInfos) { + final PsiType defaultType = expectedInfo.getDefaultType(); + final PsiType expectedType = expectedInfo.getType(); + if (!expectedType.isValid()) { + return MyResult.normal; + } + + if (defaultType != expectedType) { + if (defaultType.equals(itemType)) { + return MyResult.exactlyDefault; + } + + if (defaultType.isAssignableFrom(itemType)) { + return MyResult.ofDefaultType; + } + } + if (PsiType.VOID.equals(itemType) && PsiType.VOID.equals(expectedType)) { + return MyResult.exactlyExpected; + } + } + + return MyResult.normal; + } +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferExpectedTypeWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferExpectedTypeWeigher.java index bfb30046cf19..947a8630db22 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferExpectedTypeWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferExpectedTypeWeigher.java @@ -6,75 +6,31 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupItem; -import com.intellij.openapi.util.NullableLazyKey; -import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiType; -import com.intellij.psi.PsiTypeParameter; -import com.intellij.psi.PsiSubstitutor; -import com.intellij.psi.util.PsiUtil; -import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.util.NullableFunction; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; /** * @author peter */ public class PreferExpectedTypeWeigher extends CompletionWeigher { - private static final NullableLazyKey TYPE_PARAMETER = NullableLazyKey.create("expectedTypes", new NullableFunction() { - @Nullable - public PsiTypeParameter fun(final CompletionLocation location) { - final Pair pair = - JavaSmartCompletionContributor.getTypeParameterInfo(location.getCompletionParameters().getPosition()); - if (pair == null) return null; - return pair.first.getTypeParameters()[pair.second.intValue()]; - } - }); private enum MyResult { normal, expected, - exactlyExpected, ofDefaultType, - exactlyDefault, - expectedNoSelect } public MyResult weigh(@NotNull final LookupElement item, final CompletionLocation location) { - final Object object = item.getObject(); - if (object instanceof PsiClass && location.getCompletionType() != CompletionType.SMART) return MyResult.normal; - - if (object instanceof PsiClass) { - final PsiTypeParameter parameter = TYPE_PARAMETER.getValue(location); - if (parameter != null && object.equals(PsiUtil.resolveClassInType(TypeConversionUtil.typeParameterErasure(parameter)))) { - return MyResult.expected; - } - } + if (location.getCompletionType() != CompletionType.BASIC) return MyResult.normal; + if (item.getObject() instanceof PsiClass) return MyResult.normal; ExpectedTypeInfo[] expectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location); if (expectedInfos == null) return MyResult.normal; - PsiType itemType = JavaCompletionUtil.getPsiType(object); + PsiType itemType = JavaCompletionUtil.getLookupElementType(item); if (itemType == null || !itemType.isValid()) return MyResult.normal; - final LookupItem lookupItem = item.as(LookupItem.class); - if (lookupItem != null) { - final PsiSubstitutor substitutor = (PsiSubstitutor)lookupItem.getAttribute(LookupItem.SUBSTITUTOR); - if (substitutor != null) { - itemType = substitutor.substitute(itemType); - } - } - - if (object instanceof PsiClass) { - for (final ExpectedTypeInfo info : expectedInfos) { - if (TypeConversionUtil.erasure(info.getType().getDeepComponentType()).equals(TypeConversionUtil.erasure(itemType))) { - return SkipAbstractExpectedTypeWeigher.getSkippingStatus(item, location) != SkipAbstractExpectedTypeWeigher.Result.ACCEPT ? MyResult.expectedNoSelect : MyResult.expected; - } - } - } - for (final ExpectedTypeInfo expectedInfo : expectedInfos) { final PsiType defaultType = expectedInfo.getDefaultType(); final PsiType expectedType = expectedInfo.getType(); @@ -82,23 +38,11 @@ public class PreferExpectedTypeWeigher extends CompletionWeigher { return MyResult.normal; } - if (defaultType != expectedType) { - if (defaultType.equals(itemType)) { - return MyResult.exactlyDefault; - } - - if (defaultType.isAssignableFrom(itemType)) { - return MyResult.ofDefaultType; - } + if (defaultType != expectedType && defaultType.isAssignableFrom(itemType)) { + return MyResult.ofDefaultType; } - if ((location.getCompletionType() == CompletionType.BASIC || PsiType.VOID.equals(expectedType))) { - if (expectedType.equals(itemType)) { - return MyResult.exactlyExpected; - } - - if (expectedType.isAssignableFrom(itemType)) { - return MyResult.expected; - } + if (expectedType.isAssignableFrom(itemType)) { + return MyResult.expected; } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java index 8f84154f3e2a..8de1f2dd04a8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java @@ -54,7 +54,7 @@ public class RecursionWeigher extends CompletionWeigher { if (expression != null) { final ExpectedTypeInfo[] expectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location); if (expectedInfos != null) { - final PsiType itemType = JavaCompletionUtil.getPsiType(object); + final PsiType itemType = JavaCompletionUtil.getLookupElementType(element); if (itemType != null) { for (final ExpectedTypeInfo expectedInfo : expectedInfos) { if (positionMethod.equals(expectedInfo.getCalledMethod()) && expectedInfo.getType().isAssignableFrom(itemType)) { diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index e5756d220de0..21509a878446 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -720,14 +720,16 @@ - + order="after defaultType, before nameEnd"/> + + order="after expectedType, before stats"/> @@ -747,7 +749,7 @@ - +