Show static members after instance qualifier on second completion

This commit is contained in:
peter
2011-11-02 19:04:46 +01:00
parent 32632b2072
commit 557b9e6fcd
20 changed files with 64 additions and 35 deletions
@@ -274,7 +274,7 @@ public class JavaCompletionContributor extends CompletionContributor {
for (LookupElement element : JavaCompletionUtil.processJavaReference(position,
(PsiJavaReference)reference,
new ElementExtractorFilter(filter),
checkAccess,
checkAccess, checkAccess,
result.getPrefixMatcher(), parameters)) {
if (inheritors.alreadyProcessed(element)) {
continue;
@@ -414,7 +414,7 @@ public class JavaCompletionContributor extends CompletionContributor {
if (showClasses && insertedElement.getParent() instanceof PsiReferenceExpression) {
final Set<LookupElement> set = JavaCompletionUtil.processJavaReference(
insertedElement, (PsiJavaReference)insertedElement.getParent(), TrueFilter.INSTANCE, true, result.getPrefixMatcher(), parameters);
insertedElement, (PsiJavaReference)insertedElement.getParent(), TrueFilter.INSTANCE, true, false, result.getPrefixMatcher(), parameters);
for (final LookupElement element : set) {
result.addElement(element);
}
@@ -411,7 +411,7 @@ public class JavaCompletionUtil {
}
public static Set<LookupElement> processJavaReference(PsiElement element, PsiJavaReference javaReference, ElementFilter elementFilter,
final boolean checkAccess, @Nullable final PrefixMatcher matcher, CompletionParameters parameters) {
final boolean checkAccess, boolean filterStaticAfterInstance, @Nullable final PrefixMatcher matcher, CompletionParameters parameters) {
final THashSet<LookupElement> set = new THashSet<LookupElement>();
final Condition<String> nameCondition = matcher == null ? null : new Condition<String>() {
public boolean value(String s) {
@@ -422,7 +422,7 @@ public class JavaCompletionUtil {
PsiMethodCallExpression call = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class);
boolean checkInitialized = parameters.getInvocationCount() <= 1 && call != null && PsiKeyword.SUPER.equals(call.getMethodExpression().getText());
final JavaCompletionProcessor processor = new JavaCompletionProcessor(element, elementFilter, checkAccess, checkInitialized, nameCondition);
final JavaCompletionProcessor processor = new JavaCompletionProcessor(element, elementFilter, checkAccess, checkInitialized, filterStaticAfterInstance, nameCondition);
javaReference.processVariants(processor);
final Collection<CompletionElement> plainResults = processor.getResults();
@@ -77,7 +77,7 @@ public class JavaDocCompletionContributor extends CompletionContributor {
if (ref instanceof PsiJavaReference) {
result.stopHere();
final JavaCompletionProcessor processor = new JavaCompletionProcessor(position, TrueFilter.INSTANCE, false, false, null);
final JavaCompletionProcessor processor = new JavaCompletionProcessor(position, TrueFilter.INSTANCE, false, false, false, null);
((PsiJavaReference) ref).processVariants(processor);
for (final CompletionElement _item : processor.getResults()) {
@@ -449,7 +449,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
if (reference instanceof PsiJavaReference) {
final PsiJavaReference javaReference = (PsiJavaReference)reference;
return JavaCompletionUtil.processJavaReference(element, javaReference, new ElementFilter() {
return JavaCompletionUtil.processJavaReference(element, javaReference, new ElementFilter() {
public boolean isAcceptable(Object element, PsiElement context) {
return filter.isAcceptable(element, context);
}
@@ -463,7 +463,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
ReflectionCache.isAssignable(PsiMethod.class, hintClass) ||
ReflectionCache.isAssignable(CandidateInfo.class, hintClass);
}
}, true, null, parameters);
}, true, parameters.getInvocationCount() <= 1, null, parameters);
}
return Collections.emptySet();
@@ -63,7 +63,7 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
private final Set<PsiField> myNonInitializedFields = new HashSet<PsiField>();
private boolean myAllowStaticWithInstanceQualifier;
public JavaCompletionProcessor(PsiElement element, ElementFilter filter, final boolean checkAccess, boolean checkInitialized, @Nullable Condition<String> nameCondition) {
public JavaCompletionProcessor(PsiElement element, ElementFilter filter, final boolean checkAccess, boolean checkInitialized, boolean filterStaticAfterInstance, @Nullable Condition<String> nameCondition) {
myCheckAccess = checkAccess;
myResults = new ArrayList<CompletionElement>();
myElement = element;
@@ -110,7 +110,7 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
myNonInitializedFields.addAll(getNonInitializedFields(element));
}
myAllowStaticWithInstanceQualifier = CodeInsightSettings.getInstance().SHOW_STATIC_AFTER_INSTANCE ||
myAllowStaticWithInstanceQualifier = !filterStaticAfterInstance || CodeInsightSettings.getInstance().SHOW_STATIC_AFTER_INSTANCE ||
SuppressManager.getInstance()
.isSuppressedFor(element, AccessStaticViaInstance.ACCESS_STATIC_VIA_INSTANCE);
@@ -0,0 +1,6 @@
public class KeyVO {
{
this.fo<caret>
}
static void foo() {}
}
@@ -0,0 +1,6 @@
public class KeyVO {
{
this.foo();<caret>
}
static void foo() {}
}
@@ -463,9 +463,9 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase {
public void testBreakInIfCondition() throws Throwable { doTest(); }
public void testAccessStaticViaInstance() throws Throwable { doTest(); }
public void _testAccessStaticViaInstanceSecond() throws Throwable {
doAntiTest()
complete()
public void testAccessStaticViaInstanceSecond() throws Throwable {
configure()
myFixture.complete(CompletionType.BASIC, 2)
checkResult()
}
@@ -403,7 +403,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
final ElementFilter classFilter = getClassFilter(position);
reference.processVariants(result.getPrefixMatcher(), new Consumer<Object>() {
reference.processVariants(result.getPrefixMatcher(), parameters, new Consumer<Object>() {
public void consume(Object element) {
if (element instanceof PsiClass && inheritorsHolder.alreadyProcessed((PsiClass)element)) {
return;
@@ -96,7 +96,7 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
final PsiElement reference = position.getParent();
if (reference == null) return;
if (reference instanceof GrReferenceElement) {
((GrReferenceElement)reference).processVariants(result.getPrefixMatcher(), new Consumer<Object>() {
((GrReferenceElement)reference).processVariants(result.getPrefixMatcher(), params, new Consumer<Object>() {
public void consume(Object variant) {
PsiType type = null;
@@ -15,6 +15,7 @@
*/
package org.jetbrains.plugins.groovy.lang.psi;
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyVariantReference;
@@ -45,7 +46,7 @@ public interface GrReferenceElement<Q extends PsiElement> extends GroovyPsiEleme
@Nullable
GrTypeArgumentList getTypeArgumentList();
void processVariants(PrefixMatcher matcher, Consumer<Object> consumer);
void processVariants(PrefixMatcher matcher, CompletionParameters parameters, Consumer<Object> consumer);
@Nullable
String getClassNameText();
@@ -16,6 +16,7 @@
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.PrefixMatcher;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.project.Project;
@@ -62,8 +63,8 @@ public class CompleteReferenceExpression {
private CompleteReferenceExpression() {
}
public static void processVariants(PrefixMatcher matcher, Consumer<Object> consumer, GrReferenceExpressionImpl refExpr) {
final CompleteReferenceProcessor processor = new CompleteReferenceProcessor(refExpr, consumer, matcher);
public static void processVariants(PrefixMatcher matcher, Consumer<Object> consumer, GrReferenceExpressionImpl refExpr, CompletionParameters parameters) {
final CompleteReferenceProcessor processor = new CompleteReferenceProcessor(refExpr, consumer, matcher, parameters);
getVariantsImpl(matcher, refExpr, processor);
final GroovyResolveResult[] candidates = processor.getCandidates();
for (Object o : GroovyCompletionUtil.getCompletionVariants(candidates)) {
@@ -335,16 +336,18 @@ public class CompleteReferenceExpression {
private static class CompleteReferenceProcessor extends ResolverProcessor implements Consumer<Object> {
private final Consumer<Object> myConsumer;
private final PrefixMatcher myMatcher;
private final CompletionParameters myParameters;
private Collection<String> myPreferredFieldNames;
private final boolean mySkipPackages;
private final PsiClass myEventListener;
private final Set<String> myPropertyNames = new HashSet<String>();
private final Set<String> myLocalVars = new HashSet<String>();
protected CompleteReferenceProcessor(GrReferenceExpression place, Consumer<Object> consumer, @NotNull PrefixMatcher matcher) {
protected CompleteReferenceProcessor(GrReferenceExpression place, Consumer<Object> consumer, @NotNull PrefixMatcher matcher, CompletionParameters parameters) {
super(null, EnumSet.allOf(ResolveKind.class), place, PsiType.EMPTY_ARRAY);
myConsumer = consumer;
myMatcher = matcher;
myParameters = parameters;
myPreferredFieldNames = addAllRestrictedProperties(place);
mySkipPackages = PsiImplUtil.getRuntimeQualifier(place) == null;
myEventListener = JavaPsiFacade.getInstance(place.getProject()).findClass("java.util.EventListener", place.getResolveScope());
@@ -359,7 +362,7 @@ public class CompleteReferenceExpression {
boolean isAccessible = isAccessible(namedElement);
final GroovyPsiElement resolveContext = state.get(RESOLVE_CONTEXT);
boolean isStaticsOK = isStaticsOK(namedElement, resolveContext);
boolean isStaticsOK = isStaticsOK(namedElement, resolveContext, myParameters.getInvocationCount() <= 1);
PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
@@ -16,6 +16,7 @@
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.lang.ASTNode;
import com.intellij.openapi.util.Pair;
@@ -758,8 +759,8 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
}
@Override
public void processVariants(PrefixMatcher matcher, Consumer<Object> consumer) {
CompleteReferenceExpression.processVariants(matcher, consumer, this);
public void processVariants(PrefixMatcher matcher, CompletionParameters parameters, Consumer<Object> consumer) {
CompleteReferenceExpression.processVariants(matcher, consumer, this, parameters);
}
@NotNull
@@ -15,6 +15,7 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.impl.synthetic;
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiClass;
@@ -94,7 +95,7 @@ public class GrLightClassReferenceElement extends LightElement implements GrCode
}
@Override
public void processVariants(PrefixMatcher matcher, Consumer<Object> consumer) {
public void processVariants(PrefixMatcher matcher, CompletionParameters parameters, Consumer<Object> consumer) {
}
@Override
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.types;
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
@@ -551,7 +552,7 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl<GrCodeRef
}
@Override
public void processVariants(PrefixMatcher matcher, Consumer<Object> consumer) {
public void processVariants(PrefixMatcher matcher, CompletionParameters parameters, Consumer<Object> consumer) {
processVariantsImpl(getKind(true), consumer);
}
@@ -299,11 +299,7 @@ public class PsiUtil {
return TokenSets.REFERENCE_NAMES_WITHOUT_NUMBERS.contains(lexer.getTokenType()) && lexer.getTokenEnd() == text.length();
}
public static boolean isStaticsOK(PsiModifierListOwner owner, PsiElement place) {
return isStaticsOK(owner, place, null);
}
public static boolean isStaticsOK(PsiModifierListOwner member, PsiElement place, @Nullable PsiElement resolveContext) {
public static boolean isStaticsOK(PsiModifierListOwner member, PsiElement place, @Nullable PsiElement resolveContext, boolean filterStaticAfterInstanceQualifier) {
if (!(member instanceof PsiMember)) return true;
if (!(place instanceof GrReferenceExpression)) return true;
@@ -367,7 +363,7 @@ public class PsiUtil {
//static members may be invoked from this.<...>
final boolean isInStatic = isInStaticContext((GrThisReferenceExpression)qualifier);
if (containingClass != null && CommonClassNames.JAVA_LANG_CLASS.equals(containingClass.getQualifiedName())) {
return !(member.hasModifierProperty(PsiModifier.STATIC) && !CodeInsightSettings.getInstance().SHOW_STATIC_AFTER_INSTANCE);
return !filterStaticAfterInstanceQualifier || !member.hasModifierProperty(PsiModifier.STATIC) || CodeInsightSettings.getInstance().SHOW_STATIC_AFTER_INSTANCE;
}
else if (isInStatic) return member.hasModifierProperty(PsiModifier.STATIC);
}
@@ -376,7 +372,7 @@ public class PsiUtil {
if (member instanceof PsiClass) {
return false;
}
return !(isStatic && !CodeInsightSettings.getInstance().SHOW_STATIC_AFTER_INSTANCE);
return !isStatic || !filterStaticAfterInstanceQualifier || CodeInsightSettings.getInstance().SHOW_STATIC_AFTER_INSTANCE;
}
else {
if (containingClass == null) return true;
@@ -72,7 +72,7 @@ public class AccessorResolverProcessor extends ResolverProcessor {
}
boolean isAccessible = isAccessible(method);
final GroovyPsiElement resolveContext = state.get(RESOLVE_CONTEXT);
boolean isStaticsOK = isStaticsOK(method, resolveContext);
boolean isStaticsOK = isStaticsOK(method, resolveContext, true);
addCandidate(new GroovyResolveResultImpl(method, resolveContext, substitutor, isAccessible, isStaticsOK, true));
return !isAccessible || !isStaticsOK;
}
@@ -99,7 +99,7 @@ public class MethodResolverProcessor extends ResolverProcessor {
}
boolean isAccessible = isAccessible(method);
GroovyPsiElement resolveContext = state.get(RESOLVE_CONTEXT);
boolean isStaticsOK = isStaticsOK(method, resolveContext);
boolean isStaticsOK = isStaticsOK(method, resolveContext, true);
if (!myAllVariants && isStaticsOK &&
PsiUtil.isApplicable(myArgumentTypes, method, substitutor, (GroovyPsiElement)myPlace, myByShape)) {
addCandidate(new GroovyResolveResultImpl(method, resolveContext, substitutor, isAccessible, isStaticsOK));
@@ -96,7 +96,7 @@ public class ResolverProcessor implements PsiScopeProcessor, NameHint, ClassHint
boolean isAccessible = isAccessible(namedElement);
final GroovyPsiElement resolveContext = state.get(RESOLVE_CONTEXT);
boolean isStaticsOK = isStaticsOK(namedElement, resolveContext);
boolean isStaticsOK = isStaticsOK(namedElement, resolveContext, true);
addCandidate(new GroovyResolveResultImpl(namedElement, resolveContext, substitutor, isAccessible, isStaticsOK));
return !isAccessible || !isStaticsOK;
}
@@ -139,11 +139,11 @@ public class ResolverProcessor implements PsiScopeProcessor, NameHint, ClassHint
PsiUtil.isAccessible(myPlace, ((PsiMember)namedElement));
}
protected boolean isStaticsOK(PsiNamedElement element, GroovyPsiElement resolveContext) {
protected boolean isStaticsOK(PsiNamedElement element, GroovyPsiElement resolveContext, boolean filterStaticAfterInstanceQualifier) {
if (resolveContext instanceof GrImportStatement) return true;
if (element instanceof PsiModifierListOwner) {
return PsiUtil.isStaticsOK((PsiModifierListOwner) element, myPlace, resolveContext);
return PsiUtil.isStaticsOK((PsiModifierListOwner) element, myPlace, resolveContext, filterStaticAfterInstanceQualifier);
}
return true;
}
@@ -24,6 +24,7 @@ import org.jetbrains.plugins.groovy.GroovyFileType
import org.jetbrains.plugins.groovy.util.TestUtils
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import org.jetbrains.plugins.groovy.formatter.GroovyCodeStyleSettings
import com.intellij.codeInsight.completion.CompletionType
/**
* @author Maxim.Medvedev
@@ -1073,6 +1074,19 @@ class X {
assert myFixture.lookupElementStrings == ["foo"]
}
public void testAccessStaticViaInstanceSecond() throws Exception {
myFixture.configureByText("a.groovy", """
public class KeyVO {
{ this.fo<caret>x }
static void foo() {}
}
""");
myFixture.complete(CompletionType.BASIC, 1)
assert !myFixture.lookupElementStrings
myFixture.complete(CompletionType.BASIC, 2)
assert myFixture.lookupElementStrings == ["foo"]
}
public void testNoRepeatingModifiers() {
myFixture.configureByText 'a.groovy', 'class A { public static <caret> }'
myFixture.completeBasic()