From e05ea7c933d701a44e76bac7cae4e4fa6ca2cc87 Mon Sep 17 00:00:00 2001 From: Peter Gromov Date: Wed, 16 Sep 2009 21:32:57 +0400 Subject: [PATCH] disprefer the variable item when completing inside its own initializer, unify recursiveCall and qualifierParameter weighers --- .../codeInsight/completion/JavaCompletionUtil.java | 23 +++++++++++ ...ParameterWeigher.java => RecursionWeigher.java} | 46 +++++++++++++++++----- .../ReferenceExpressionCompletionContributor.java | 17 ++------ resources/src/META-INF/IdeaPlugin.xml | 6 +-- 4 files changed, 64 insertions(+), 28 deletions(-) rename java/java-impl/src/com/intellij/codeInsight/completion/{RecursiveCallParameterWeigher.java => RecursionWeigher.java} (64%) 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 499e09eab9..ecd455112f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -17,9 +17,14 @@ import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import static com.intellij.patterns.PlatformPatterns.psiElement; import com.intellij.patterns.PsiElementPattern; +import com.intellij.patterns.PsiJavaPatterns; import com.intellij.psi.*; import com.intellij.psi.codeStyle.*; import com.intellij.psi.filters.ElementFilter; +import com.intellij.psi.filters.AndFilter; +import com.intellij.psi.filters.ClassFilter; +import com.intellij.psi.filters.element.ExcludeDeclaredFilter; +import com.intellij.psi.filters.element.ExcludeSillyAssignment; import com.intellij.psi.html.HtmlTag; import com.intellij.psi.impl.source.PsiImmediateClassType; import com.intellij.psi.infos.CandidateInfo; @@ -28,6 +33,7 @@ import com.intellij.psi.javadoc.PsiDocToken; import com.intellij.psi.scope.BaseScopeProcessor; import com.intellij.psi.scope.ElementClassHint; import com.intellij.psi.scope.NameHint; +import com.intellij.psi.scope.ElementClassFilter; import com.intellij.psi.statistics.JavaStatisticsManager; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.*; @@ -1031,4 +1037,21 @@ public class JavaCompletionUtil { if (qualifier instanceof PsiMethodCallExpression) return true; return containsMethodCalls(getQualifier(qualifier)); } + + @Nullable + static ElementFilter recursionFilter(PsiElement element) { + if (com.intellij.patterns.PsiJavaPatterns.psiElement().afterLeaf(PsiKeyword.RETURN).inside(PsiReturnStatement.class).accepts(element)) { + return new ExcludeDeclaredFilter(ElementClassFilter.METHOD); + } + + if (com.intellij.patterns.PsiJavaPatterns.psiElement().inside( + PsiJavaPatterns.or( + PsiJavaPatterns.psiElement(PsiAssignmentExpression.class), + PsiJavaPatterns.psiElement(PsiVariable.class))). + andNot(com.intellij.patterns.PsiJavaPatterns.psiElement().afterLeaf(".")).accepts(element)) { + return new AndFilter(new ExcludeSillyAssignment(), + new ExcludeDeclaredFilter(new ClassFilter(PsiVariable.class))); + } + return null; + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/RecursiveCallParameterWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java similarity index 64% rename from java/java-impl/src/com/intellij/codeInsight/completion/RecursiveCallParameterWeigher.java rename to java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java index 0dbe4474ca..8f84154f3e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/RecursiveCallParameterWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java @@ -8,6 +8,7 @@ import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; +import com.intellij.psi.filters.ElementFilter; import com.intellij.psi.search.searches.DeepestSuperMethodsSearch; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; @@ -15,24 +16,41 @@ import org.jetbrains.annotations.NotNull; /** * @author peter */ -public class RecursiveCallParameterWeigher extends CompletionWeigher { +public class RecursionWeigher extends CompletionWeigher { - public Integer weigh(@NotNull final LookupElement element, final CompletionLocation location) { - if (location.getCompletionType() != CompletionType.BASIC && location.getCompletionType() != CompletionType.SMART) return 0; + private enum Result { + recursive, + passingObjectToItself, + normal, + delegation, + } + + public Result weigh(@NotNull final LookupElement element, final CompletionLocation location) { + if (location.getCompletionType() != CompletionType.BASIC && location.getCompletionType() != CompletionType.SMART) return Result.normal; final Object object = element.getObject(); - if (!(object instanceof PsiModifierListOwner) && !(object instanceof PsiExpression)) return 0; + if (!(object instanceof PsiModifierListOwner) && !(object instanceof PsiExpression)) return Result.normal; final PsiMethod positionMethod = JavaCompletionUtil.POSITION_METHOD.getValue(location); - if (positionMethod == null) return 0; + if (positionMethod == null) return Result.normal; final PsiElement position = location.getCompletionParameters().getPosition(); + final ElementFilter filter = JavaCompletionUtil.recursionFilter(position); + if (filter != null && !filter.isAcceptable(object, position)) { + return Result.recursive; + } + final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class, true, PsiClass.class); final PsiReferenceExpression reference = expression != null ? expression.getMethodExpression() : PsiTreeUtil.getParentOfType(position, PsiReferenceExpression.class); - if (reference == null) return 0; + if (reference == null) return Result.normal; final PsiExpression qualifier = reference.getQualifierExpression(); boolean isDelegate = qualifier != null && !(qualifier instanceof PsiThisExpression); + + if (isPassingObjectToItself(object, qualifier, isDelegate)) { + return Result.passingObjectToItself; + } + if (expression != null) { final ExpectedTypeInfo[] expectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location); if (expectedInfos != null) { @@ -40,12 +58,12 @@ public class RecursiveCallParameterWeigher extends CompletionWeigher { if (itemType != null) { for (final ExpectedTypeInfo expectedInfo : expectedInfos) { if (positionMethod.equals(expectedInfo.getCalledMethod()) && expectedInfo.getType().isAssignableFrom(itemType)) { - return isDelegate ? 2 : -1; + return isDelegate ? Result.delegation : Result.recursive; } } } } - return 0; + return Result.normal; } if (object instanceof PsiMethod) { @@ -54,12 +72,20 @@ public class RecursiveCallParameterWeigher extends CompletionWeigher { Comparing.equal(method.getName(), positionMethod.getName()) && method.getParameterList().getParametersCount() == positionMethod.getParameterList().getParametersCount()) { if (findDeepestSuper(method).equals(findDeepestSuper(positionMethod))) { - return isDelegate ? 2 : -1; + return isDelegate ? Result.delegation : Result.recursive; } } } - return 0; + return Result.normal; + } + + private static boolean isPassingObjectToItself(Object object, PsiExpression qualifier, boolean delegate) { + if (object instanceof PsiThisExpression) { + return !delegate || qualifier instanceof PsiSuperExpression; + } + return qualifier instanceof PsiReferenceExpression && + object.equals(((PsiReferenceExpression)qualifier).advancedResolve(true).getElement()); } @NotNull diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java index 46c4f8b244..733bf55a89 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java @@ -23,11 +23,8 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.filters.*; -import com.intellij.psi.filters.element.ExcludeDeclaredFilter; -import com.intellij.psi.filters.element.ExcludeSillyAssignment; import com.intellij.psi.filters.element.ModifierFilter; import com.intellij.psi.impl.source.PostprocessReformattingAspect; -import com.intellij.psi.scope.ElementClassFilter; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; @@ -69,17 +66,9 @@ public class ReferenceExpressionCompletionContributor extends ExpressionSmartCom } if (!allowRecursion) { - if (psiElement().afterLeaf(PsiKeyword.RETURN).inside(PsiReturnStatement.class).accepts(element)) { - return new ElementExtractorFilter(new ExcludeDeclaredFilter(ElementClassFilter.METHOD)); - } - - if (psiElement().inside( - PsiJavaPatterns.or( - PsiJavaPatterns.psiElement(PsiAssignmentExpression.class), - PsiJavaPatterns.psiElement(PsiVariable.class))). - andNot(psiElement().afterLeaf(".")).accepts(element)) { - return new ElementExtractorFilter(new AndFilter(new ExcludeSillyAssignment(), - new ExcludeDeclaredFilter(new ClassFilter(PsiVariable.class)))); + final ElementFilter filter = JavaCompletionUtil.recursionFilter(element); + if (filter != null) { + return new ElementExtractorFilter(filter); } } diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index dbe3c19c38..e5756d220d 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -724,12 +724,10 @@ order="before stats, after statics"/> - - + order="after recursion, before stats"/> -- 2.11.4.GIT