java-specific parts of MembersGetter go to JavaMembersGetter

This commit is contained in:
peter
2011-04-07 19:50:10 +02:00
parent 4d998743c4
commit c65ff63395
6 changed files with 152 additions and 98 deletions
@@ -24,7 +24,7 @@ import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PsiJavaPatterns;
import com.intellij.psi.*;
import com.intellij.psi.filters.getters.ClassLiteralGetter;
import com.intellij.psi.filters.getters.MembersGetter;
import com.intellij.psi.filters.getters.JavaMembersGetter;
import com.intellij.psi.filters.getters.ThisGetter;
import com.intellij.psi.scope.BaseScopeProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
@@ -90,9 +90,9 @@ public class BasicExpressionCompletionContributor {
final PsiElement parent = position.getParent();
if (parent != null && !(parent.getParent() instanceof PsiSwitchLabelStatement)) {
MembersGetter.addMembers(parameters.getPosition(), expectedType, result);
new JavaMembersGetter(expectedType).addMembers(parameters.getPosition(), result);
if (!parameters.getDefaultType().equals(expectedType)) {
MembersGetter.addMembers(parameters.getPosition(), parameters.getDefaultType(), result);
new JavaMembersGetter(parameters.getDefaultType()).addMembers(parameters.getPosition(), result);
}
for (final PsiExpression expression : ThisGetter.getThisExpressionVariants(position)) {
@@ -31,7 +31,7 @@ import com.intellij.psi.filters.*;
import com.intellij.psi.filters.classes.EnumOrAnnotationTypeFilter;
import com.intellij.psi.filters.classes.InterfaceFilter;
import com.intellij.psi.filters.element.ReferenceOnFilter;
import com.intellij.psi.filters.getters.MembersGetter;
import com.intellij.psi.filters.getters.JavaMembersGetter;
import com.intellij.psi.filters.position.*;
import com.intellij.psi.filters.types.TypeCodeFragmentIsVoidEnabledFilter;
import com.intellij.psi.impl.source.jsp.jspJava.JspClassLevelDeclarationStatement;
@@ -616,7 +616,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{
!(position.getParent() instanceof PsiLiteralExpression) &&
!(position.getParent().getParent() instanceof PsiSwitchLabelStatement)) {
for (final ExpectedTypeInfo info : JavaSmartCompletionContributor.getExpectedTypes(parameters)) {
MembersGetter.addMembers(position, info.getDefaultType(), new Consumer<LookupElement>() {
new JavaMembersGetter(info.getDefaultType()).addMembers(position, new Consumer<LookupElement>() {
@Override
public void consume(LookupElement element) {
result.addElement(element);
@@ -341,11 +341,9 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
}
public static SmartCompletionDecorator decorate(LookupElement lookupElement, Collection<ExpectedTypeInfo> infos) {
if (lookupElement instanceof LookupItem) {
final LookupItem lookupItem = (LookupItem)lookupElement;
if (lookupItem.getInsertHandler() == null) {
lookupItem.setInsertHandler(DefaultInsertHandler.NO_TAIL_HANDLER);
}
LookupItem item = lookupElement.as(LookupItem.CLASS_CONDITION_KEY);
if (item != null && item.getInsertHandler() == null) {
item.setInsertHandler(DefaultInsertHandler.NO_TAIL_HANDLER);
}
return new SmartCompletionDecorator(lookupElement, infos);
@@ -115,8 +115,9 @@ public class SmartCompletionDecorator extends TailTypeDecorator<LookupElement> {
@Override
public void handleInsert(InsertionContext context) {
myPosition = getPosition(context, this);
if (getDelegate() instanceof LookupItem) {
analyzeItem(context, (LookupItem)getDelegate(), getObject(), myPosition, myExpectedTypeInfos);
LookupItem item = getDelegate().as(LookupItem.CLASS_CONDITION_KEY);
if (item != null) {
analyzeItem(context, item, getObject(), myPosition, myExpectedTypeInfos);
}
super.handleInsert(context);
}
@@ -0,0 +1,124 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.filters.getters;
import com.intellij.codeInsight.completion.JavaCompletionUtil;
import com.intellij.codeInsight.completion.JavaMethodCallElement;
import com.intellij.codeInsight.completion.SmartCompletionDecorator;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.VariableLookupItem;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
*/
public class JavaMembersGetter extends MembersGetter {
private final PsiType myExpectedType;
public JavaMembersGetter(@NotNull PsiType expectedType) {
myExpectedType = expectedType;
}
public void addMembers(PsiElement position, Consumer<LookupElement> results) {
final PsiClass psiClass = PsiUtil.resolveClassInType(myExpectedType);
processMembers(position, results, psiClass, PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) != null);
if (myExpectedType instanceof PsiPrimitiveType && PsiType.DOUBLE.isAssignableFrom(myExpectedType)) {
addConstantsFromTargetClass(position, results);
}
}
private void addConstantsFromTargetClass(PsiElement position, Consumer<LookupElement> results) {
PsiElement parent = position.getParent();
if (!(parent instanceof PsiReferenceExpression)) {
return;
}
PsiElement prev = parent;
parent = parent.getParent();
while (parent instanceof PsiBinaryExpression) {
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)parent;
final IElementType op = binaryExpression.getOperationSign().getTokenType();
if (JavaTokenType.EQEQ == op || JavaTokenType.NE == op) {
if (prev == binaryExpression.getROperand()) {
processMembers(position, results, getCalledClass(binaryExpression.getLOperand()), false);
}
return;
}
prev = parent;
parent = parent.getParent();
}
if (parent instanceof PsiExpressionList) {
processMembers(position, results, getCalledClass(parent.getParent()), false);
}
}
@Nullable
private static PsiClass getCalledClass(@Nullable PsiElement call) {
if (call instanceof PsiMethodCallExpression) {
for (final JavaResolveResult result : ((PsiMethodCallExpression)call).getMethodExpression().multiResolve(true)) {
final PsiElement element = result.getElement();
if (element instanceof PsiMethod) {
final PsiClass aClass = ((PsiMethod)element).getContainingClass();
if (aClass != null) {
return aClass;
}
}
}
}
if (call instanceof PsiNewExpression) {
final PsiJavaCodeReferenceElement reference = ((PsiNewExpression)call).getClassReference();
if (reference != null) {
for (final JavaResolveResult result : reference.multiResolve(true)) {
final PsiElement element = result.getElement();
if (element instanceof PsiClass) {
return (PsiClass)element;
}
}
}
}
return null;
}
@Nullable
protected LookupElement createFieldElement(PsiField field) {
if (!myExpectedType.isAssignableFrom(field.getType())) {
return null;
}
return JavaCompletionUtil.qualify(new VariableLookupItem(field));
}
@Nullable
protected LookupElement createMethodElement(PsiMethod method) {
PsiSubstitutor substitutor = SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor(method, myExpectedType);
PsiType type = substitutor.substitute(method.getReturnType());
if (type == null || !myExpectedType.isAssignableFrom(type)) {
return null;
}
JavaMethodCallElement item = new JavaMethodCallElement(method);
item.setInferenceSubstitutor(substitutor);
return JavaCompletionUtil.qualify(item);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,91 +16,24 @@
package com.intellij.psi.filters.getters;
import com.intellij.codeInsight.completion.JavaCompletionUtil;
import com.intellij.codeInsight.completion.JavaMethodCallElement;
import com.intellij.codeInsight.completion.SmartCompletionDecorator;
import com.intellij.codeInsight.lookup.*;
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.*;
import com.intellij.psi.filters.TrueFilter;
import com.intellij.psi.scope.processor.FilterScopeProcessor;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: ik
* Date: 15.04.2003
* Time: 17:07:09
* To change this template use Options | File Templates.
* @author ik
* @author peter
*/
public class MembersGetter {
public abstract class MembersGetter {
public static void addMembers(PsiElement position, PsiType expectedType, Consumer<LookupElement> results) {
final PsiClass psiClass = PsiUtil.resolveClassInType(expectedType);
processMembers(position, results, psiClass, PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) != null, expectedType);
if (expectedType instanceof PsiPrimitiveType && PsiType.DOUBLE.isAssignableFrom(expectedType)) {
addConstantsFromTargetClass(position, expectedType, results);
}
}
private static void addConstantsFromTargetClass(PsiElement position, PsiType expectedType, Consumer<LookupElement> results) {
PsiElement parent = position.getParent();
if (!(parent instanceof PsiReferenceExpression)) {
return;
}
PsiElement prev = parent;
parent = parent.getParent();
while (parent instanceof PsiBinaryExpression) {
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)parent;
final IElementType op = binaryExpression.getOperationSign().getTokenType();
if (JavaTokenType.EQEQ == op || JavaTokenType.NE == op) {
if (prev == binaryExpression.getROperand()) {
processMembers(position, results, getCalledClass(binaryExpression.getLOperand()), false, expectedType);
}
return;
}
prev = parent;
parent = parent.getParent();
}
if (parent instanceof PsiExpressionList) {
processMembers(position, results, getCalledClass(parent.getParent()), false, expectedType);
}
}
@Nullable
private static PsiClass getCalledClass(@Nullable PsiElement call) {
if (call instanceof PsiMethodCallExpression) {
for (final JavaResolveResult result : ((PsiMethodCallExpression)call).getMethodExpression().multiResolve(true)) {
final PsiElement element = result.getElement();
if (element instanceof PsiMethod) {
final PsiClass aClass = ((PsiMethod)element).getContainingClass();
if (aClass != null) {
return aClass;
}
}
}
}
if (call instanceof PsiNewExpression) {
final PsiJavaCodeReferenceElement reference = ((PsiNewExpression)call).getClassReference();
if (reference != null) {
for (final JavaResolveResult result : reference.multiResolve(true)) {
final PsiElement element = result.getElement();
if (element instanceof PsiClass) {
return (PsiClass)element;
}
}
}
}
return null;
}
private static void processMembers(final PsiElement context, final Consumer<LookupElement> results, @Nullable final PsiClass where,
final boolean acceptMethods, PsiType expectedType) {
public void processMembers(@NotNull final PsiElement context, final Consumer<LookupElement> results, @Nullable final PsiClass where, final boolean acceptMethods) {
if (where == null) return;
PsiClass current = PsiTreeUtil.getContextOfType(context, PsiClass.class);
@@ -122,20 +55,18 @@ public class MembersGetter {
if (member.hasModifierProperty(PsiModifier.STATIC) && resolveHelper.isAccessible(member, context, null)) {
if (result instanceof PsiField && !member.hasModifierProperty(PsiModifier.FINAL)) continue;
if (result instanceof PsiMethod && acceptMethods) continue;
final LookupItem item = result instanceof PsiMethod ? new JavaMethodCallElement((PsiMethod)result) : new VariableLookupItem((PsiVariable)result);
item.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
JavaCompletionUtil.qualify(item);
if (member instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)member;
final PsiSubstitutor substitutor = SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor(method, expectedType);
((JavaMethodCallElement) item).setInferenceSubstitutor(substitutor);
}
final PsiType itemType = ((TypedLookupItem)item).getType();
if (itemType != null && expectedType.isAssignableFrom(itemType)) {
results.consume(item);
final LookupElement item = result instanceof PsiMethod ? createMethodElement((PsiMethod)result) : createFieldElement((PsiField)result);
if (item != null) {
results.consume(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(item));
}
}
}
}
}
@Nullable
protected abstract LookupElement createFieldElement(PsiField field);
@Nullable
protected abstract LookupElement createMethodElement(PsiMethod method);
}