Groovy PSI doesn't depends on LookupElements anymore

This commit is contained in:
Max Medvedev
2014-04-25 23:59:56 +04:00
parent 92da487a5e
commit 0fff99976a
10 changed files with 483 additions and 381 deletions
@@ -65,7 +65,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatem
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.CompleteReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.CompleteReferencesWithSameQualifier;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.refactoring.DefaultGroovyVariableNameValidator;
@@ -432,8 +432,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
final PsiType qualifierType = qualifier instanceof GrExpression ? ((GrExpression)qualifier).getType() : null;
if (reference instanceof GrReferenceExpression && (qualifier instanceof GrExpression || qualifier == null)) {
for (String string : CompleteReferenceExpression.getVariantsWithSameQualifier(matcher, (GrExpression)qualifier,
(GrReferenceExpression)reference)) {
for (String string : CompleteReferencesWithSameQualifier.getVariantsWithSameQualifier((GrReferenceExpression)reference, matcher, (GrExpression)qualifier)) {
consumer.consume(LookupElementBuilder.create(string).withItemTextUnderlined(true));
}
if (parameters.getInvocationCount() < 2 && qualifier != null && qualifierType == null &&
@@ -446,7 +445,8 @@ public class GroovyCompletionContributor extends CompletionContributor {
}
final List<LookupElement> zeroPriority = newArrayList();
reference.processVariants(matcher, parameters, new Consumer<LookupElement>() {
GroovyCompletionUtil.processVariants(reference, matcher, parameters, new Consumer<LookupElement>() {
@Override
public void consume(LookupElement lookupElement) {
Object object = lookupElement.getObject();
@@ -18,10 +18,7 @@ package org.jetbrains.plugins.groovy.lang.completion;
import com.intellij.codeInsight.CodeInsightUtilCore;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.completion.AllClassesGetter;
import com.intellij.codeInsight.completion.JavaClassNameCompletionContributor;
import com.intellij.codeInsight.completion.JavaCompletionUtil;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.completion.originInfo.OriginInfoProvider;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
@@ -42,6 +39,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.*;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
@@ -77,6 +75,10 @@ import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.modifiers.GrAnnotationCollector;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.CompleteReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceExpressionImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.CompleteCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrCodeReferenceElementImpl;
import org.jetbrains.plugins.groovy.lang.psi.util.GdkMethodUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
@@ -289,11 +291,11 @@ public class GroovyCompletionUtil {
for (GroovyResolveResult r : importReference.multiResolve(false)) {
final PsiElement resolved = r.getElement();
if (context.getManager().areElementsEquivalent(resolved, element) && (alias || !(element instanceof PsiClass))) {
return generateLookupForImportedElement(candidate, importedName, alias);
return generateLookupForImportedElement(candidate, importedName);
}
else {
if (resolved instanceof PsiField && element instanceof PsiMethod && isAccessorFor((PsiMethod)element, (PsiField)resolved)) {
return generateLookupForImportedElement(candidate, getAccessorPrefix((PsiMethod)element) + capitalize(importedName), alias);
return generateLookupForImportedElement(candidate, getAccessorPrefix((PsiMethod)element) + capitalize(importedName));
}
}
}
@@ -330,9 +332,7 @@ public class GroovyCompletionUtil {
return AllClassesGetter.createLookupItem(psiClass, new GroovyClassNameInsertHandler());
}
private static List<? extends LookupElement> generateLookupForImportedElement(GroovyResolveResult resolveResult,
String importedName,
boolean alias) {
private static List<? extends LookupElement> generateLookupForImportedElement(GroovyResolveResult resolveResult, String importedName) {
final PsiElement element = resolveResult.getElement();
assert element != null;
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
@@ -672,4 +672,13 @@ public class GroovyCompletionUtil {
pparent instanceof GrVariableDeclaration &&
((GrVariableDeclaration)pparent).isTuple();
}
public static void processVariants(GrReferenceElement referenceElement, PrefixMatcher matcher, CompletionParameters parameters, Consumer<LookupElement> consumer) {
if (referenceElement instanceof GrCodeReferenceElementImpl) {
CompleteCodeReferenceElement.processVariants((GrCodeReferenceElementImpl)referenceElement, consumer, matcher);
}
else if (referenceElement instanceof GrReferenceExpressionImpl) {
CompleteReferenceExpression.processVariants(matcher, consumer, (GrReferenceExpressionImpl)referenceElement, parameters);
}
}
}
@@ -107,33 +107,34 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
final PsiElement reference = position.getParent();
if (reference == null) return;
if (reference instanceof GrReferenceElement) {
((GrReferenceElement)reference).processVariants(result.getPrefixMatcher(), params, new Consumer<LookupElement>() {
public void consume(LookupElement variant) {
PsiType type = null;
GroovyCompletionUtil.processVariants((GrReferenceElement)reference, result.getPrefixMatcher(), params,
new Consumer<LookupElement>() {
public void consume(LookupElement variant) {
PsiType type = null;
Object o = variant.getObject();
if (o instanceof GroovyResolveResult) {
if (!((GroovyResolveResult)o).isAccessible()) return;
o = ((GroovyResolveResult)o).getElement();
}
Object o = variant.getObject();
if (o instanceof GroovyResolveResult) {
if (!((GroovyResolveResult)o).isAccessible()) return;
o = ((GroovyResolveResult)o).getElement();
}
if (o instanceof PsiElement) {
type = getTypeByElement((PsiElement)o, position);
}
else if (o instanceof String) {
if ("true".equals(o) || "false".equals(o)) {
type = PsiType.BOOLEAN;
}
}
if (type == null) return;
for (TypeConstraint info : infos) {
if (info.satisfied(type, position)) {
result.addElement(variant);
break;
}
}
}
});
if (o instanceof PsiElement) {
type = getTypeByElement((PsiElement)o, position);
}
else if (o instanceof String) {
if ("true".equals(o) || "false".equals(o)) {
type = PsiType.BOOLEAN;
}
}
if (type == null) return;
for (TypeConstraint info : infos) {
if (info.satisfied(type, position)) {
result.addElement(variant);
break;
}
}
}
});
}
addExpectedClassMembers(params, result);
@@ -225,7 +226,7 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
result.addElement(element);
}
}
});
}, params);
}
});
@@ -15,13 +15,9 @@
*/
package org.jetbrains.plugins.groovy.lang.psi;
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.PsiType;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -48,8 +44,6 @@ public interface GrReferenceElement<Q extends PsiElement> extends GroovyPsiEleme
@Nullable
GrTypeArgumentList getTypeArgumentList();
void processVariants(PrefixMatcher matcher, CompletionParameters parameters, Consumer<LookupElement> consumer);
@Nullable
String getClassNameText();
@@ -15,7 +15,6 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions;
import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.JavaClassNameCompletionContributor;
import com.intellij.codeInsight.completion.PrefixMatcher;
@@ -38,7 +37,6 @@ import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState;
@@ -51,7 +49,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssign
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrReflectedMethod;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
@@ -73,59 +70,76 @@ import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils.*;
* @author ven
*/
public class CompleteReferenceExpression {
private CompleteReferenceExpression() {
private static final Logger LOG = Logger.getInstance(CompleteReferenceExpression.class);
private final PrefixMatcher myMatcher;
private final Consumer<LookupElement> myConsumer;
private final GrReferenceExpressionImpl myRefExpr;
private final CompletionParameters myParameters;
private final CompleteReferenceProcessor myProcessor;
private CompleteReferenceExpression(@NotNull PrefixMatcher matcher,
@NotNull Consumer<LookupElement> consumer,
@NotNull GrReferenceExpressionImpl refExpr,
@NotNull CompletionParameters parameters) {
myMatcher = matcher;
myConsumer = consumer;
myParameters = parameters;
myRefExpr = refExpr;
myProcessor = new CompleteReferenceProcessor();
}
public static void processVariants(@NotNull PrefixMatcher matcher,
@NotNull final Consumer<LookupElement> consumer,
@NotNull Consumer<LookupElement> consumer,
@NotNull GrReferenceExpressionImpl refExpr,
@NotNull CompletionParameters parameters) {
processRefInAnnotation(refExpr, matcher, consumer);
new CompleteReferenceExpression(matcher, consumer, refExpr, parameters).processVariantsImpl();
}
final int[] count = new int[]{0};
final CompleteReferenceProcessor processor = new CompleteReferenceProcessor(refExpr, new Consumer<LookupElement>() {
@Override
public void consume(LookupElement element) {
count[0]++;
consumer.consume(element);
}
}, matcher, parameters);
private void processVariantsImpl() {
processRefInAnnotationImpl();
getVariantsImpl(refExpr, processor);
final GroovyResolveResult[] candidates = processor.getCandidates();
getVariantsImpl();
final GroovyResolveResult[] candidates = myProcessor.getCandidates();
List<LookupElement> results =
GroovyCompletionUtil.getCompletionVariants(candidates,
JavaClassNameCompletionContributor.AFTER_NEW.accepts(refExpr), matcher, refExpr);
JavaClassNameCompletionContributor.AFTER_NEW.accepts(myRefExpr), myMatcher, myRefExpr);
if (count[0] == 0 && results.size() == 0) {
results = GroovyCompletionUtil.getCompletionVariants(processor.getInapplicableResults(),
JavaClassNameCompletionContributor.AFTER_NEW.accepts(refExpr), matcher, refExpr);
if (myProcessor.isEmpty() && results.size() == 0) {
results = GroovyCompletionUtil.getCompletionVariants(myProcessor.getInapplicableResults(),
JavaClassNameCompletionContributor.AFTER_NEW.accepts(myRefExpr), myMatcher,
myRefExpr);
}
for (LookupElement o : results) {
consumer.consume(o);
myConsumer.consume(o);
}
}
public static void processRefInAnnotation(@NotNull GrReferenceExpression refExpr,
@NotNull PrefixMatcher matcher,
@NotNull Consumer<LookupElement> consumer) {
if (refExpr.getParent() instanceof GrAnnotationNameValuePair &&
((GrAnnotationNameValuePair)refExpr.getParent()).getNameIdentifierGroovy() == null) {
PsiElement parent = refExpr.getParent().getParent();
@NotNull Consumer<LookupElement> consumer,
@NotNull CompletionParameters parameters) {
new CompleteReferenceExpression(matcher, consumer, (GrReferenceExpressionImpl)refExpr, parameters).processRefInAnnotationImpl();
}
private void processRefInAnnotationImpl() {
if (myRefExpr.getParent() instanceof GrAnnotationNameValuePair &&
((GrAnnotationNameValuePair)myRefExpr.getParent()).getNameIdentifierGroovy() == null) {
PsiElement parent = myRefExpr.getParent().getParent();
if (!(parent instanceof GrAnnotation)) {
parent = parent.getParent();
}
if (parent instanceof GrAnnotation) {
for (LookupElement result : GroovyCompletionUtil.getAnnotationCompletionResults((GrAnnotation)parent, matcher)) {
consumer.consume(result);
for (LookupElement result : GroovyCompletionUtil.getAnnotationCompletionResults((GrAnnotation)parent, myMatcher)) {
myConsumer.consume(result);
}
}
}
}
private static void processIfJavaLangClass(@NotNull GrReferenceExpression refExpr,
@NotNull ResolverProcessor consumer,
@Nullable PsiType type) {
private void processIfJavaLangClass(@Nullable PsiType type) {
if (!(type instanceof PsiClassType)) return;
final PsiClass psiClass = ((PsiClassType)type).resolve();
@@ -134,53 +148,51 @@ public class CompleteReferenceExpression {
final PsiType[] params = ((PsiClassType)type).getParameters();
if (params.length != 1) return;
getVariantsFromQualifierType(refExpr, consumer, params[0], refExpr.getProject());
getVariantsFromQualifierType(params[0], myRefExpr.getProject());
}
private static void getVariantsImpl(@NotNull GrReferenceExpression refExpr,
@NotNull CompleteReferenceProcessor processor) {
GrExpression qualifier = refExpr.getQualifierExpression();
private void getVariantsImpl() {
GrExpression qualifier = myRefExpr.getQualifierExpression();
if (qualifier == null) {
ResolveUtil.treeWalkUp(refExpr, processor, true);
ResolveUtil.treeWalkUp(myRefExpr, myProcessor, true);
for (PsiElement e = refExpr.getParent(); e != null; e = e.getParent()) {
for (PsiElement e = myRefExpr.getParent(); e != null; e = e.getParent()) {
if (e instanceof GrClosableBlock) {
ResolveState state = ResolveState.initial().put(ResolverProcessor.RESOLVE_CONTEXT, e);
for (ClosureMissingMethodContributor contributor : ClosureMissingMethodContributor.EP_NAME.getExtensions()) {
contributor.processMembers((GrClosableBlock)e, processor, refExpr, state);
contributor.processMembers((GrClosableBlock)e, myProcessor, myRefExpr, state);
}
}
}
GrExpression runtimeQualifier = PsiImplUtil.getRuntimeQualifier(refExpr);
GrExpression runtimeQualifier = PsiImplUtil.getRuntimeQualifier(myRefExpr);
if (runtimeQualifier != null) {
getVariantsFromQualifier(refExpr, processor, runtimeQualifier);
getVariantsFromQualifier(runtimeQualifier);
}
getBindings(refExpr, processor);
getBindings();
}
else {
if (refExpr.getDotTokenType() != GroovyTokenTypes.mSPREAD_DOT) {
getVariantsFromQualifier(refExpr, processor, qualifier);
if (myRefExpr.getDotTokenType() != GroovyTokenTypes.mSPREAD_DOT) {
getVariantsFromQualifier(qualifier);
if (qualifier instanceof GrReferenceExpression &&
("class".equals(((GrReferenceExpression)qualifier).getReferenceName()) || PsiUtil.isThisReference(qualifier) && !PsiUtil.isInstanceThisRef(qualifier))) {
processIfJavaLangClass(refExpr, processor, qualifier.getType());
processIfJavaLangClass(qualifier.getType());
}
}
else {
getVariantsFromQualifierForSpreadOperator(refExpr, processor, qualifier);
getVariantsFromQualifierForSpreadOperator(qualifier);
}
}
ResolveUtil.processCategoryMembers(refExpr, processor, ResolveState.initial());
ResolveUtil.processCategoryMembers(myRefExpr, myProcessor, ResolveState.initial());
}
private static void getBindings(@NotNull final GrReferenceExpression refExpr,
@NotNull final CompleteReferenceProcessor processor) {
final PsiClass containingClass = PsiTreeUtil.getParentOfType(refExpr, PsiClass.class);
private void getBindings() {
final PsiClass containingClass = PsiTreeUtil.getParentOfType(myRefExpr, PsiClass.class);
if (containingClass != null) return;
final PsiFile file = FileContextUtil.getContextFile(refExpr);
final PsiFile file = FileContextUtil.getContextFile(myRefExpr);
if (file instanceof GroovyFile) {
((GroovyFile)file).accept(new GroovyRecursiveElementVisitor() {
@Override
@@ -191,10 +203,10 @@ public class CompleteReferenceExpression {
if (value instanceof GrReferenceExpression && !((GrReferenceExpression)value).isQualified()) {
final PsiElement resolved = ((GrReferenceExpression)value).resolve();
if (resolved instanceof GrBindingVariable) {
processor.execute(resolved, ResolveState.initial());
myProcessor.execute(resolved, ResolveState.initial());
}
else if (resolved == null) {
processor.execute(new GrBindingVariable((GroovyFile)file, ((GrReferenceExpression)value).getReferenceName(), true),
myProcessor.execute(new GrBindingVariable((GroovyFile)file, ((GrReferenceExpression)value).getReferenceName(), true),
ResolveState.initial());
}
}
@@ -208,12 +220,10 @@ public class CompleteReferenceExpression {
}
}
private static void getVariantsFromQualifierForSpreadOperator(@NotNull GrReferenceExpression refExpr,
@NotNull ResolverProcessor processor,
@NotNull GrExpression qualifier) {
final PsiType spreadType = ClosureParameterEnhancer.findTypeForIteration(qualifier, refExpr);
private void getVariantsFromQualifierForSpreadOperator(@NotNull GrExpression qualifier) {
final PsiType spreadType = ClosureParameterEnhancer.findTypeForIteration(qualifier, myRefExpr);
if (spreadType != null) {
getVariantsFromQualifierType(refExpr, processor, spreadType, refExpr.getProject());
getVariantsFromQualifierType(spreadType, myRefExpr.getProject());
}
}
@@ -285,9 +295,7 @@ public class CompleteReferenceExpression {
}
}
private static void getVariantsFromQualifier(@NotNull GrReferenceExpression refExpr,
@NotNull ResolverProcessor processor,
@NotNull GrExpression qualifier) {
private void getVariantsFromQualifier(@NotNull GrExpression qualifier) {
Project project = qualifier.getProject();
PsiType qualifierType = qualifier.getType();
final ResolveState state = ResolveState.initial();
@@ -295,24 +303,23 @@ public class CompleteReferenceExpression {
if (qualifier instanceof GrReferenceExpression) {
PsiElement resolved = ((GrReferenceExpression)qualifier).resolve();
if (resolved instanceof PsiPackage || resolved instanceof PsiVariable) {
resolved.processDeclarations(processor, state, null, refExpr);
resolved.processDeclarations(myProcessor, state, null, myRefExpr);
return;
}
}
getVariantsFromQualifierType(refExpr, processor,
PsiType.getJavaLangObject(refExpr.getManager(), qualifier.getResolveScope()), project);
getVariantsFromQualifierType(PsiType.getJavaLangObject(myRefExpr.getManager(), qualifier.getResolveScope()), project);
}
else if (qualifierType instanceof PsiIntersectionType) {
for (PsiType conjunct : ((PsiIntersectionType)qualifierType).getConjuncts()) {
getVariantsFromQualifierType(refExpr, processor, conjunct, project);
getVariantsFromQualifierType(conjunct, project);
}
}
else {
getVariantsFromQualifierType(refExpr, processor, qualifierType, project);
getVariantsFromQualifierType(qualifierType, project);
if (qualifier instanceof GrReferenceExpression && !PsiUtil.isSuperReference(qualifier) && !PsiUtil.isInstanceThisRef(qualifier)) {
PsiElement resolved = ((GrReferenceExpression)qualifier).resolve();
if (resolved instanceof PsiClass) { ////omitted .class
GlobalSearchScope scope = refExpr.getResolveScope();
GlobalSearchScope scope = myRefExpr.getResolveScope();
PsiClass javaLangClass = PsiUtil.getJavaLangClass(resolved, scope);
if (javaLangClass != null) {
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
@@ -320,93 +327,49 @@ public class CompleteReferenceExpression {
if (typeParameters.length == 1) {
substitutor = substitutor.put(typeParameters[0], qualifierType);
}
PsiType javaLangClassType = JavaPsiFacade.getElementFactory(refExpr.getProject()).createType(javaLangClass, substitutor);
ResolveUtil.processAllDeclarations(javaLangClassType, processor, state, refExpr);
PsiType javaLangClassType = JavaPsiFacade.getElementFactory(myRefExpr.getProject()).createType(javaLangClass, substitutor);
ResolveUtil.processAllDeclarations(javaLangClassType, myProcessor, state, myRefExpr);
}
}
}
}
}
@NotNull
public static Set<String> getVariantsWithSameQualifier(@NotNull PrefixMatcher matcher,
@Nullable GrExpression qualifier,
@NotNull GrReferenceExpression refExpr) {
if (qualifier != null && qualifier.getType() != null) return Collections.emptySet();
final PsiElement scope = PsiTreeUtil.getParentOfType(refExpr, GrMember.class, PsiFile.class);
Set<String> result = new LinkedHashSet<String>();
if (scope != null) {
addVariantsWithSameQualifier(matcher, scope, refExpr, qualifier, result);
}
return result;
}
private static void addVariantsWithSameQualifier(@NotNull PrefixMatcher matcher,
@NotNull PsiElement element,
@NotNull GrReferenceExpression patternExpression,
@Nullable GrExpression patternQualifier,
@NotNull Set<String> result) {
if (element instanceof GrReferenceExpression && element != patternExpression && !PsiUtil.isLValue((GroovyPsiElement)element)) {
final GrReferenceExpression refExpr = (GrReferenceExpression)element;
final String refName = refExpr.getReferenceName();
if (refName != null && !result.contains(refName) && matcher.prefixMatches(refName)) {
final GrExpression hisQualifier = refExpr.getQualifierExpression();
if (hisQualifier != null && patternQualifier != null) {
if (PsiEquivalenceUtil.areElementsEquivalent(hisQualifier, patternQualifier)) {
if (refExpr.resolve() == null) {
result.add(refName);
}
}
}
else if (hisQualifier == null && patternQualifier == null) {
if (refExpr.resolve() == null) {
result.add(refName);
}
}
}
}
for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
addVariantsWithSameQualifier(matcher, child, patternExpression, patternQualifier, result);
}
}
private static void getVariantsFromQualifierType(@NotNull GrReferenceExpression refExpr,
@NotNull ResolverProcessor processor,
@NotNull PsiType qualifierType,
@NotNull Project project) {
private void getVariantsFromQualifierType(@NotNull PsiType qualifierType,
@NotNull Project project) {
final ResolveState state = ResolveState.initial();
if (qualifierType instanceof PsiClassType) {
PsiClassType.ClassResolveResult result = ((PsiClassType)qualifierType).resolveGenerics();
PsiClass qualifierClass = result.getElement();
if (qualifierClass != null) {
qualifierClass.processDeclarations(processor, state.put(PsiSubstitutor.KEY, result.getSubstitutor()), null, refExpr);
qualifierClass.processDeclarations(myProcessor, state.put(PsiSubstitutor.KEY, result.getSubstitutor()), null, myRefExpr);
}
}
else if (qualifierType instanceof PsiArrayType) {
final GrTypeDefinition arrayClass = GroovyPsiManager.getInstance(project).getArrayClass(((PsiArrayType)qualifierType).getComponentType());
final GrTypeDefinition arrayClass =
GroovyPsiManager.getInstance(project).getArrayClass(((PsiArrayType)qualifierType).getComponentType());
if (arrayClass != null) {
if (!arrayClass.processDeclarations(processor, state, null, refExpr)) return;
if (!arrayClass.processDeclarations(myProcessor, state, null, myRefExpr)) return;
}
}
else if (qualifierType instanceof PsiIntersectionType) {
for (PsiType conjunct : ((PsiIntersectionType)qualifierType).getConjuncts()) {
getVariantsFromQualifierType(refExpr, processor, conjunct, project);
getVariantsFromQualifierType(conjunct, project);
}
return;
}
ResolveUtil.processNonCodeMembers(qualifierType, processor, refExpr, state);
ResolveUtil.processNonCodeMembers(qualifierType, myProcessor, myRefExpr, state);
}
@NotNull
private static Set<String> addAllRestrictedProperties(@NotNull GrReferenceExpression place) {
if (place.getQualifier() != null) {
private Set<String> addAllRestrictedProperties() {
if (myRefExpr.getQualifier() != null) {
return Collections.emptySet();
}
Set<String> propertyNames = new HashSet<String>();
for (GrTypeDefinition containingClass = PsiTreeUtil.getParentOfType(place, GrTypeDefinition.class);
for (GrTypeDefinition containingClass = PsiTreeUtil.getParentOfType(myRefExpr, GrTypeDefinition.class);
containingClass != null;
containingClass = PsiTreeUtil.getParentOfType(containingClass, GrTypeDefinition.class)) {
for (PsiField field : containingClass.getFields()) {
@@ -416,17 +379,14 @@ public class CompleteReferenceExpression {
return propertyNames;
}
private static boolean isMap(@NotNull GrReferenceExpression place) {
final PsiType qType = GrReferenceResolveUtil.getQualifierType(place);
private boolean isMap() {
final PsiType qType = GrReferenceResolveUtil.getQualifierType(myRefExpr);
return InheritanceUtil.isInheritor(qType, CommonClassNames.JAVA_UTIL_MAP);
}
private static class CompleteReferenceProcessor extends ResolverProcessor implements Consumer<Object> {
private static final Logger LOG = Logger.getInstance(CompleteReferenceProcessor.class);
private class CompleteReferenceProcessor extends ResolverProcessor implements Consumer<Object> {
private final Consumer<LookupElement> myConsumer;
private final PrefixMatcher myMatcher;
private final CompletionParameters myParameters;
private final boolean mySkipPackages;
private final PsiClass myEventListener;
@@ -443,32 +403,39 @@ public class CompleteReferenceExpression {
private List<GroovyResolveResult> myInapplicable;
protected CompleteReferenceProcessor(@NotNull GrReferenceExpression place,
@NotNull Consumer<LookupElement> consumer,
@NotNull PrefixMatcher matcher,
@NotNull CompletionParameters parameters) {
super(null, EnumSet.allOf(ResolveKind.class), place, PsiType.EMPTY_ARRAY);
myConsumer = consumer;
myMatcher = matcher;
myParameters = parameters;
myPreferredFieldNames = addAllRestrictedProperties(place);
mySkipPackages = shouldSkipPackages(place);
myEventListener = JavaPsiFacade.getInstance(place.getProject()).findClass("java.util.EventListener", place.getResolveScope());
private boolean myIsEmpty = true;
protected CompleteReferenceProcessor() {
super(null, EnumSet.allOf(ResolveKind.class), myRefExpr, PsiType.EMPTY_ARRAY);
myConsumer = new Consumer<LookupElement>() {
@Override
public void consume(LookupElement element) {
myIsEmpty = false;
CompleteReferenceExpression.this.myConsumer.consume(element);
}
};
myPreferredFieldNames = addAllRestrictedProperties();
mySkipPackages = shouldSkipPackages();
myEventListener = JavaPsiFacade.getInstance(myRefExpr.getProject()).findClass("java.util.EventListener", myRefExpr.getResolveScope());
myPropertyNames.addAll(myPreferredFieldNames);
myFieldPointerOperator = place.hasAt();
myMethodPointerOperator = place.getDotTokenType() == GroovyTokenTypes.mMEMBER_POINTER;
myIsMap = isMap(place);
final PsiType thisType = GrReferenceResolveUtil.getQualifierType(place);
mySubstitutorComputer = new SubstitutorComputer(thisType, PsiType.EMPTY_ARRAY, PsiType.EMPTY_ARRAY, place, place.getParent());
myFieldPointerOperator = myRefExpr.hasAt();
myMethodPointerOperator = myRefExpr.getDotTokenType() == GroovyTokenTypes.mMEMBER_POINTER;
myIsMap = isMap();
final PsiType thisType = GrReferenceResolveUtil.getQualifierType(myRefExpr);
mySubstitutorComputer = new SubstitutorComputer(thisType, PsiType.EMPTY_ARRAY, PsiType.EMPTY_ARRAY, myRefExpr, myRefExpr.getParent());
}
private static boolean shouldSkipPackages(@NotNull GrReferenceExpression place) {
if (PsiImplUtil.getRuntimeQualifier(place) != null) {
public boolean isEmpty() {
return myIsEmpty;
}
private boolean shouldSkipPackages() {
if (PsiImplUtil.getRuntimeQualifier(myRefExpr) != null) {
return false;
}
PsiElement parent = place.getParent();
PsiElement parent = myRefExpr.getParent();
return parent == null || parent.getLanguage().isKindOf(GroovyFileType.GROOVY_LANGUAGE); //don't skip in Play!
}
@@ -0,0 +1,94 @@
/*
* Copyright 2000-2014 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 org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions;
import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import java.util.Collections;
import java.util.Set;
/**
* Created by Max Medvedev on 25/04/14
*/
public class CompleteReferencesWithSameQualifier {
private final GrReferenceExpression myRefExpr;
private final PrefixMatcher myMatcher;
private final GrExpression myQualifier;
private CompleteReferencesWithSameQualifier(@NotNull GrReferenceExpression refExpr,
@NotNull PrefixMatcher matcher,
@Nullable GrExpression qualifier) {
myRefExpr = refExpr;
myMatcher = matcher;
myQualifier = qualifier;
}
@NotNull
public static Set<String> getVariantsWithSameQualifier(@NotNull GrReferenceExpression refExpr,
@NotNull PrefixMatcher matcher,
@Nullable GrExpression qualifier) {
return new CompleteReferencesWithSameQualifier(refExpr, matcher, qualifier).getVariantsWithSameQualifierImpl();
}
private Set<String> getVariantsWithSameQualifierImpl() {
if (myQualifier != null && myQualifier.getType() != null) return Collections.emptySet();
final PsiElement scope = PsiTreeUtil.getParentOfType(myRefExpr, GrMember.class, PsiFile.class);
Set<String> result = ContainerUtil.newLinkedHashSet();
if (scope != null) {
addVariantsWithSameQualifier(scope, result);
}
return result;
}
private void addVariantsWithSameQualifier(@NotNull PsiElement element, @NotNull Set<String> result) {
if (element instanceof GrReferenceExpression && element != myRefExpr && !PsiUtil.isLValue((GroovyPsiElement)element)) {
final GrReferenceExpression refExpr = (GrReferenceExpression)element;
final String refName = refExpr.getReferenceName();
if (refName != null && !result.contains(refName) && myMatcher.prefixMatches(refName)) {
final GrExpression hisQualifier = refExpr.getQualifierExpression();
if (hisQualifier != null && myQualifier != null) {
if (PsiEquivalenceUtil.areElementsEquivalent(hisQualifier, myQualifier)) {
if (refExpr.resolve() == null) {
result.add(refName);
}
}
}
else if (hisQualifier == null && myQualifier == null) {
if (refExpr.resolve() == null) {
result.add(refName);
}
}
}
}
for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
addVariantsWithSameQualifier(child, result);
}
}
}
@@ -16,9 +16,6 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions;
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Computable;
@@ -34,7 +31,6 @@ import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
@@ -903,11 +899,6 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
return results.length == 0 ? GroovyResolveResult.EMPTY_ARRAY : (GroovyResolveResult[])results;
}
@Override
public void processVariants(PrefixMatcher matcher, CompletionParameters parameters, Consumer<LookupElement> consumer) {
CompleteReferenceExpression.processVariants(matcher, consumer, this, parameters);
}
@NotNull
public GroovyResolveResult[] getSameNameVariants() {
return doPolyResolve(true, true);
@@ -15,16 +15,12 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.impl.synthetic;
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiType;
import com.intellij.psi.impl.light.LightElement;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -95,10 +91,6 @@ public class GrLightClassReferenceElement extends LightElement implements GrCode
return null;
}
@Override
public void processVariants(PrefixMatcher matcher, CompletionParameters parameters, Consumer<LookupElement> consumer) {
}
@Override
public String getClassNameText() {
return myClassName;
@@ -0,0 +1,223 @@
/*
* Copyright 2000-2014 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 org.jetbrains.plugins.groovy.lang.psi.impl.types;
import com.intellij.codeInsight.completion.JavaClassNameCompletionContributor;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody;
import org.jetbrains.plugins.groovy.lang.psi.api.types.*;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.processors.CompletionProcessor;
import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor;
import java.util.List;
import static org.jetbrains.plugins.groovy.lang.psi.impl.types.GrCodeReferenceElementImpl.ReferenceKind.*;
/**
* Created by Max Medvedev on 25/04/14
*/
public class CompleteCodeReferenceElement {
private static final Logger LOG = Logger.getInstance(CompleteCodeReferenceElement.class);
private final GrCodeReferenceElementImpl myRef;
private final Consumer<LookupElement> myConsumer;
private final PrefixMatcher myMatcher;
private CompleteCodeReferenceElement(@NotNull GrCodeReferenceElementImpl ref,
@NotNull Consumer<LookupElement> consumer,
@NotNull PrefixMatcher matcher) {
myRef = ref;
myConsumer = consumer;
myMatcher = matcher;
}
public static void processVariants(@NotNull GrCodeReferenceElementImpl ref,
@NotNull Consumer<LookupElement> consumer,
@NotNull PrefixMatcher matcher) {
new CompleteCodeReferenceElement(ref, consumer, matcher).processVariantsImpl();
}
private void feedLookupElements(@NotNull PsiNamedElement psi, boolean afterNew) {
GroovyResolveResultImpl candidate = new GroovyResolveResultImpl(psi, true);
List<? extends LookupElement> elements = GroovyCompletionUtil.createLookupElements(candidate, afterNew, myMatcher, null);
for (LookupElement element : elements) {
myConsumer.consume(element);
}
}
public void processVariantsImpl() {
boolean afterNew = JavaClassNameCompletionContributor.AFTER_NEW.accepts(myRef);
switch (myRef.getKind(true)) {
case STATIC_MEMBER_FQ: {
final GrCodeReferenceElement qualifier = myRef.getQualifier();
if (qualifier != null) {
final PsiElement resolve = qualifier.resolve();
if (resolve instanceof PsiClass) {
final PsiClass clazz = (PsiClass)resolve;
for (PsiField field : clazz.getFields()) {
if (field.hasModifierProperty(PsiModifier.STATIC)) {
feedLookupElements(field, afterNew);
}
}
for (PsiMethod method : clazz.getMethods()) {
if (method.hasModifierProperty(PsiModifier.STATIC)) {
feedLookupElements(method, afterNew);
}
}
for (PsiClass inner : clazz.getInnerClasses()) {
if (inner.hasModifierProperty(PsiModifier.STATIC)) {
feedLookupElements(inner, afterNew);
}
}
return;
}
}
}
// fall through
case PACKAGE_FQ:
case CLASS_FQ:
case CLASS_OR_PACKAGE_FQ: {
final String refText = PsiUtil.getQualifiedReferenceText(myRef);
LOG.assertTrue(refText != null, myRef.getText());
String parentPackageFQName = StringUtil.getPackageName(refText);
final PsiPackage parentPackage = JavaPsiFacade.getInstance(myRef.getProject()).findPackage(parentPackageFQName);
if (parentPackage != null) {
final GlobalSearchScope scope = myRef.getResolveScope();
if (myRef.getKind(true) == PACKAGE_FQ) {
for (PsiPackage aPackage : parentPackage.getSubPackages(scope)) {
feedLookupElements(aPackage, afterNew);
}
return;
}
if (myRef.getKind(true) == CLASS_FQ) {
for (PsiClass aClass : parentPackage.getClasses(scope)) {
feedLookupElements(aClass, afterNew);
}
return;
}
for (PsiPackage aPackage : parentPackage.getSubPackages(scope)) {
feedLookupElements(aPackage, afterNew);
}
for (PsiClass aClass : parentPackage.getClasses(scope)) {
feedLookupElements(aClass, afterNew);
}
return;
}
}
case CLASS_OR_PACKAGE:
case CLASS_IN_QUALIFIED_NEW:
case CLASS: {
GrCodeReferenceElement qualifier = myRef.getQualifier();
if (qualifier != null) {
PsiElement qualifierResolved = qualifier.resolve();
if (qualifierResolved instanceof PsiPackage) {
PsiPackage aPackage = (PsiPackage)qualifierResolved;
for (PsiClass aClass : aPackage.getClasses(myRef.getResolveScope())) {
feedLookupElements(aClass, afterNew);
}
if (myRef.getKind(true) == CLASS) return;
for (PsiPackage subpackage : aPackage.getSubPackages(myRef.getResolveScope())) {
feedLookupElements(subpackage, afterNew);
}
}
else if (qualifierResolved instanceof PsiClass) {
for (PsiClass aClass : ((PsiClass)qualifierResolved).getInnerClasses()) {
feedLookupElements(aClass, afterNew);
}
}
}
else {
ResolverProcessor classProcessor = CompletionProcessor.createClassCompletionProcessor(myRef);
processTypeParametersFromUnfinishedMethodOrField(classProcessor);
ResolveUtil.treeWalkUp(myRef, classProcessor, false);
for (LookupElement o : GroovyCompletionUtil.getCompletionVariants(classProcessor.getCandidates(), afterNew, myMatcher, myRef)) {
myConsumer.consume(o);
}
}
}
}
}
private void processTypeParametersFromUnfinishedMethodOrField(@NotNull ResolverProcessor processor) {
final PsiElement candidate = findTypeParameterListCandidate();
if (candidate instanceof GrTypeParameterList) {
for (GrTypeParameter p : ((GrTypeParameterList)candidate).getTypeParameters()) {
ResolveUtil.processElement(processor, p, ResolveState.initial());
}
}
}
@Nullable
private PsiElement findTypeParameterListCandidate() {
final GrTypeElement typeElement = getRootTypeElement();
if (typeElement == null) return null;
if (typeElement.getParent() instanceof GrTypeDefinitionBody) {
return PsiUtil.skipWhitespacesAndComments(typeElement.getPrevSibling(), false);
}
if (typeElement.getParent() instanceof GrVariableDeclaration) {
final PsiElement errorElement = PsiUtil.skipWhitespacesAndComments(typeElement.getPrevSibling(), false);
if (errorElement instanceof PsiErrorElement) {
return errorElement.getFirstChild();
}
}
return null;
}
@Nullable
private GrTypeElement getRootTypeElement() {
PsiElement parent = myRef.getParent();
while (isTypeElementChild(parent)) {
if (parent instanceof GrTypeElement && !isTypeElementChild(parent.getParent())) return (GrTypeElement)parent;
parent = parent.getParent();
}
return null;
}
private static boolean isTypeElementChild(@Nullable PsiElement element) {
return element instanceof GrCodeReferenceElement || element instanceof GrTypeArgumentList || element instanceof GrTypeElement;
}
}
@@ -16,23 +16,16 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.types;
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.JavaClassNameCompletionContributor;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.ResolveCache;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocReferenceElement;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
@@ -41,14 +34,13 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.types.*;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrReferenceElementImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
@@ -58,7 +50,6 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint;
import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassResolverProcessor;
import org.jetbrains.plugins.groovy.lang.resolve.processors.CompletionProcessor;
import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor;
import java.util.ArrayList;
@@ -132,7 +123,7 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl<GrCodeRef
return results.length == 1 ? results[0].getElement() : null;
}
private ReferenceKind getKind(boolean forCompletion) {
public ReferenceKind getKind(boolean forCompletion) {
if (isClassReferenceForNew()) {
return CLASS_OR_PACKAGE;
}
@@ -273,161 +264,6 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl<GrCodeRef
return parent instanceof GrNewExpression;
}
private static void feedLookupElements(PsiNamedElement psi, boolean afterNew, Consumer<LookupElement> consumer, PrefixMatcher matcher) {
for (LookupElement element : GroovyCompletionUtil
.createLookupElements(new GroovyResolveResultImpl(psi, true), afterNew, matcher, null)) {
consumer.consume(element);
}
}
private void processVariantsImpl(ReferenceKind kind, Consumer<LookupElement> consumer, PrefixMatcher matcher) {
boolean afterNew = JavaClassNameCompletionContributor.AFTER_NEW.accepts(this);
switch (kind) {
case STATIC_MEMBER_FQ: {
final GrCodeReferenceElement qualifier = getQualifier();
if (qualifier != null) {
final PsiElement resolve = qualifier.resolve();
if (resolve instanceof PsiClass) {
final PsiClass clazz = (PsiClass)resolve;
for (PsiField field : clazz.getFields()) {
if (field.hasModifierProperty(PsiModifier.STATIC)) {
feedLookupElements(field, afterNew, consumer, matcher);
}
}
for (PsiMethod method : clazz.getMethods()) {
if (method.hasModifierProperty(PsiModifier.STATIC)) {
feedLookupElements(method, afterNew, consumer, matcher);
}
}
for (PsiClass inner : clazz.getInnerClasses()) {
if (inner.hasModifierProperty(PsiModifier.STATIC)) {
feedLookupElements(inner, afterNew, consumer, matcher);
}
}
return;
}
}
}
// fall through
case PACKAGE_FQ:
case CLASS_FQ:
case CLASS_OR_PACKAGE_FQ: {
final String refText = PsiUtil.getQualifiedReferenceText(this);
LOG.assertTrue(refText != null, this.getText());
String parentPackageFQName = StringUtil.getPackageName(refText);
final PsiPackage parentPackage = JavaPsiFacade.getInstance(getProject()).findPackage(parentPackageFQName);
if (parentPackage != null) {
final GlobalSearchScope scope = getResolveScope();
if (kind == PACKAGE_FQ) {
for (PsiPackage aPackage : parentPackage.getSubPackages(scope)) {
feedLookupElements(aPackage, afterNew, consumer, matcher);
}
return;
}
if (kind == CLASS_FQ) {
for (PsiClass aClass : parentPackage.getClasses(scope)) {
feedLookupElements(aClass, afterNew, consumer, matcher);
}
return;
}
for (PsiPackage aPackage : parentPackage.getSubPackages(scope)) {
feedLookupElements(aPackage, afterNew, consumer, matcher);
}
for (PsiClass aClass : parentPackage.getClasses(scope)) {
feedLookupElements(aClass, afterNew, consumer, matcher);
}
return;
}
}
case CLASS_OR_PACKAGE:
case CLASS_IN_QUALIFIED_NEW:
case CLASS: {
GrCodeReferenceElement qualifier = getQualifier();
if (qualifier != null) {
PsiElement qualifierResolved = qualifier.resolve();
if (qualifierResolved instanceof PsiPackage) {
PsiPackage aPackage = (PsiPackage)qualifierResolved;
for (PsiClass aClass : aPackage.getClasses(getResolveScope())) {
feedLookupElements(aClass, afterNew, consumer, matcher);
}
if (kind == CLASS) return;
for (PsiPackage subpackage : aPackage.getSubPackages(getResolveScope())) {
feedLookupElements(subpackage, afterNew, consumer, matcher);
}
}
else if (qualifierResolved instanceof PsiClass) {
for (PsiClass aClass : ((PsiClass)qualifierResolved).getInnerClasses()) {
feedLookupElements(aClass, afterNew, consumer, matcher);
}
}
}
else {
ResolverProcessor classProcessor = CompletionProcessor.createClassCompletionProcessor(this);
processTypeParametersFromUnfinishedMethodOrField(classProcessor);
ResolveUtil.treeWalkUp(this, classProcessor, false);
for (LookupElement o : GroovyCompletionUtil.getCompletionVariants(classProcessor.getCandidates(), afterNew, matcher, this)) {
consumer.consume(o);
}
}
}
}
}
private void processTypeParametersFromUnfinishedMethodOrField(@NotNull ResolverProcessor processor) {
final PsiElement candidate = findTypeParameterListCandidate();
if (candidate instanceof GrTypeParameterList) {
for (GrTypeParameter p : ((GrTypeParameterList)candidate).getTypeParameters()) {
ResolveUtil.processElement(processor, p, ResolveState.initial());
}
}
}
@Nullable
private PsiElement findTypeParameterListCandidate() {
final GrTypeElement typeElement = getRootTypeElement();
if (typeElement == null) return null;
if (typeElement.getParent() instanceof GrTypeDefinitionBody) {
return PsiUtil.skipWhitespacesAndComments(typeElement.getPrevSibling(), false);
}
if (typeElement.getParent() instanceof GrVariableDeclaration) {
final PsiElement errorElement = PsiUtil.skipWhitespacesAndComments(typeElement.getPrevSibling(), false);
if (errorElement instanceof PsiErrorElement) {
return errorElement.getFirstChild();
}
}
return null;
}
@Nullable
private GrTypeElement getRootTypeElement() {
PsiElement parent = getParent();
while (isTypeElementChild(parent)) {
if (parent instanceof GrTypeElement && !isTypeElementChild(parent.getParent())) return (GrTypeElement)parent;
parent = parent.getParent();
}
return null;
}
private static boolean isTypeElementChild(PsiElement element) {
return element instanceof GrCodeReferenceElement || element instanceof GrTypeArgumentList || element instanceof GrTypeElement;
}
public boolean isSoft() {
return false;
}
@@ -681,11 +517,6 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl<GrCodeRef
return (GroovyResolveResult[])results;
}
@Override
public void processVariants(PrefixMatcher matcher, CompletionParameters parameters, Consumer<LookupElement> consumer) {
processVariantsImpl(getKind(true), consumer, matcher);
}
@NotNull
@Override
public PsiType[] getTypeArguments() {