disprefer the variable item when completing inside its own initializer, unify recursiveCall and qualifierParameter weighers

This commit is contained in:
Peter Gromov
2009-09-16 21:32:57 +04:00
parent a15214209f
commit e05ea7c933
4 changed files with 64 additions and 28 deletions
@@ -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;
}
}
@@ -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
@@ -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);
}
}