mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Groovy PSI doesn't depends on LookupElements anymore
This commit is contained in:
+4
-4
@@ -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
-9
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-26
@@ -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();
|
||||
|
||||
|
||||
+114
-147
@@ -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!
|
||||
}
|
||||
|
||||
|
||||
+94
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
-9
@@ -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);
|
||||
|
||||
-8
@@ -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;
|
||||
|
||||
+223
@@ -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;
|
||||
}
|
||||
}
|
||||
+3
-172
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user