mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-91838 Complete instance members from static inner class
This commit is contained in:
+9
-3
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.TailType;
|
||||
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.ImportClassFix;
|
||||
import com.intellij.codeInsight.hint.ShowParameterInfoHandler;
|
||||
import com.intellij.codeInsight.lookup.*;
|
||||
@@ -276,7 +277,7 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
private static Set<String> addReferenceVariants(final CompletionParameters parameters, CompletionResultSet result, final InheritorsHolder inheritors) {
|
||||
final Set<String> usedWords = new HashSet<String>();
|
||||
final PsiElement position = parameters.getPosition();
|
||||
final boolean checkAccess = parameters.getInvocationCount() <= 1;
|
||||
final boolean first = parameters.getInvocationCount() <= 1;
|
||||
final boolean isSwitchLabel = SWITCH_LABEL.accepts(position);
|
||||
final boolean isAfterNew = JavaClassNameCompletionContributor.AFTER_NEW.accepts(position);
|
||||
final boolean pkgContext = JavaCompletionUtil.inSomePackage(position);
|
||||
@@ -286,10 +287,15 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
final ElementFilter filter = getReferenceFilter(position);
|
||||
if (filter != null) {
|
||||
final PsiFile originalFile = parameters.getOriginalFile();
|
||||
JavaCompletionProcessor.Options options =
|
||||
JavaCompletionProcessor.Options.DEFAULT_OPTIONS
|
||||
.withCheckAccess(first)
|
||||
.withFilterStaticAfterInstance(first)
|
||||
.withShowInstanceInStaticContext(!first);
|
||||
for (LookupElement element : JavaCompletionUtil.processJavaReference(position,
|
||||
(PsiJavaReference)reference,
|
||||
new ElementExtractorFilter(filter),
|
||||
checkAccess, checkAccess,
|
||||
options,
|
||||
result.getPrefixMatcher(), parameters)) {
|
||||
if (inheritors.alreadyProcessed(element)) {
|
||||
continue;
|
||||
@@ -429,7 +435,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, false, result.getPrefixMatcher(), parameters);
|
||||
insertedElement, (PsiJavaReference)insertedElement.getParent(), TrueFilter.INSTANCE, JavaCompletionProcessor.Options.DEFAULT_OPTIONS, result.getPrefixMatcher(), parameters);
|
||||
for (final LookupElement element : set) {
|
||||
result.addElement(element);
|
||||
}
|
||||
|
||||
@@ -324,7 +324,8 @@ public class JavaCompletionUtil {
|
||||
}
|
||||
|
||||
public static Set<LookupElement> processJavaReference(PsiElement element, PsiJavaReference javaReference, ElementFilter elementFilter,
|
||||
final boolean checkAccess, boolean filterStaticAfterInstance, final PrefixMatcher matcher, CompletionParameters parameters) {
|
||||
JavaCompletionProcessor.Options options,
|
||||
final PrefixMatcher matcher, CompletionParameters parameters) {
|
||||
final Set<LookupElement> set = new LinkedHashSet<LookupElement>();
|
||||
final Condition<String> nameCondition = new Condition<String>() {
|
||||
public boolean value(String s) {
|
||||
@@ -335,7 +336,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, filterStaticAfterInstance, nameCondition);
|
||||
final JavaCompletionProcessor processor = new JavaCompletionProcessor(element, elementFilter, options.withInitialized(checkInitialized), nameCondition);
|
||||
final PsiType plainQualifier = processor.getQualifierType();
|
||||
PsiType qualifierType = plainQualifier;
|
||||
|
||||
|
||||
+2
-1
@@ -28,6 +28,7 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorModificationUtil;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.patterns.PsiJavaPatterns;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.psi.*;
|
||||
@@ -75,7 +76,7 @@ public class JavaDocCompletionContributor extends CompletionContributor {
|
||||
if (ref instanceof PsiJavaReference) {
|
||||
result.stopHere();
|
||||
|
||||
final JavaCompletionProcessor processor = new JavaCompletionProcessor(position, TrueFilter.INSTANCE, false, false, false, null);
|
||||
final JavaCompletionProcessor processor = new JavaCompletionProcessor(position, TrueFilter.INSTANCE, JavaCompletionProcessor.Options.CHECK_NOTHING, Condition.TRUE);
|
||||
((PsiJavaReference) ref).processVariants(processor);
|
||||
|
||||
for (final CompletionElement _item : processor.getResults()) {
|
||||
|
||||
+6
-2
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.*;
|
||||
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
|
||||
import com.intellij.codeInsight.lookup.*;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
@@ -396,7 +397,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
|
||||
if (reference instanceof PsiJavaReference) {
|
||||
final PsiJavaReference javaReference = (PsiJavaReference)reference;
|
||||
|
||||
return JavaCompletionUtil.processJavaReference(element, javaReference, new ElementFilter() {
|
||||
ElementFilter checkClass = new ElementFilter() {
|
||||
public boolean isAcceptable(Object element, PsiElement context) {
|
||||
return filter.isAcceptable(element, context);
|
||||
}
|
||||
@@ -413,7 +414,10 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, true, parameters.getInvocationCount() <= 1, matcher, parameters);
|
||||
};
|
||||
JavaCompletionProcessor.Options options =
|
||||
JavaCompletionProcessor.Options.DEFAULT_OPTIONS.withFilterStaticAfterInstance(parameters.getInvocationCount() <= 1);
|
||||
return JavaCompletionUtil.processJavaReference(element, javaReference, checkClass, options, matcher, parameters);
|
||||
}
|
||||
|
||||
return Collections.emptySet();
|
||||
|
||||
+57
-20
@@ -51,7 +51,7 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
|
||||
private boolean myStatic = false;
|
||||
private PsiElement myDeclarationHolder = null;
|
||||
private final Set<Object> myResultNames = new THashSet<Object>();
|
||||
private final List<CompletionElement> myResults;
|
||||
private final List<CompletionElement> myResults = new ArrayList<CompletionElement>();
|
||||
private final PsiElement myElement;
|
||||
private final PsiElement myScope;
|
||||
private final ElementFilter myFilter;
|
||||
@@ -59,13 +59,12 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
|
||||
private PsiType myQualifierType = null;
|
||||
private PsiClass myQualifierClass = null;
|
||||
private final Condition<String> myMatcher;
|
||||
private final boolean myCheckAccess;
|
||||
private final Options myOptions;
|
||||
private final Set<PsiField> myNonInitializedFields = new HashSet<PsiField>();
|
||||
private boolean myAllowStaticWithInstanceQualifier;
|
||||
|
||||
public JavaCompletionProcessor(PsiElement element, ElementFilter filter, final boolean checkAccess, boolean checkInitialized, boolean filterStaticAfterInstance, @Nullable Condition<String> nameCondition) {
|
||||
myCheckAccess = checkAccess;
|
||||
myResults = new ArrayList<CompletionElement>();
|
||||
public JavaCompletionProcessor(@NotNull PsiElement element, ElementFilter filter, Options options, @NotNull Condition<String> nameCondition) {
|
||||
myOptions = options;
|
||||
myElement = element;
|
||||
myMatcher = nameCondition;
|
||||
myFilter = filter;
|
||||
@@ -106,11 +105,11 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
|
||||
}
|
||||
}
|
||||
|
||||
if (checkInitialized) {
|
||||
if (myOptions.checkInitialized) {
|
||||
myNonInitializedFields.addAll(getNonInitializedFields(element));
|
||||
}
|
||||
|
||||
myAllowStaticWithInstanceQualifier = !filterStaticAfterInstance || CodeInsightSettings.getInstance().SHOW_STATIC_AFTER_INSTANCE ||
|
||||
myAllowStaticWithInstanceQualifier = !options.filterStaticAfterInstance || CodeInsightSettings.getInstance().SHOW_STATIC_AFTER_INSTANCE ||
|
||||
SuppressManager.getInstance()
|
||||
.isSuppressedFor(element, AccessStaticViaInstance.ACCESS_STATIC_VIA_INSTANCE);
|
||||
|
||||
@@ -199,17 +198,16 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
|
||||
return true;
|
||||
}
|
||||
|
||||
final PsiElement elementParent = myElement.getParent();
|
||||
if (!(elementParent instanceof PsiMethodReferenceExpression) && checkStaticFlag(element)) return true;
|
||||
if (!(myElement.getParent() instanceof PsiMethodReferenceExpression) && !isStaticsOk(element)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (element instanceof PsiPackage && myScope instanceof PsiClass) {
|
||||
if (!(elementParent instanceof PsiQualifiedReference && ((PsiQualifiedReference)elementParent).getQualifier() != null)) {
|
||||
return true;
|
||||
}
|
||||
if (element instanceof PsiPackage && myScope instanceof PsiClass && !isQualifiedContext()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (satisfies(element, state) && isAccessible(element)) {
|
||||
CompletionElement element1 = new CompletionElement((PsiNamedElement)element, state.get(PsiSubstitutor.KEY));
|
||||
CompletionElement element1 = new CompletionElement(element, state.get(PsiSubstitutor.KEY));
|
||||
if (myResultNames.add(element1.getUniqueId())) {
|
||||
myResults.add(element1);
|
||||
}
|
||||
@@ -217,13 +215,21 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean checkStaticFlag(PsiElement element) {
|
||||
private boolean isQualifiedContext() {
|
||||
final PsiElement elementParent = myElement.getParent();
|
||||
return elementParent instanceof PsiQualifiedReference && ((PsiQualifiedReference)elementParent).getQualifier() != null;
|
||||
}
|
||||
|
||||
private boolean isStaticsOk(PsiElement element) {
|
||||
if (myOptions.showInstanceInStaticContext && !isQualifiedContext()) {
|
||||
return true;
|
||||
}
|
||||
if (!(element instanceof PsiClass) && element instanceof PsiModifierListOwner) {
|
||||
PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)element;
|
||||
if (myStatic) {
|
||||
if (!modifierListOwner.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
// we don't need non static method in static context.
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -231,16 +237,16 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
|
||||
&& modifierListOwner.hasModifierProperty(PsiModifier.STATIC)
|
||||
&& !myMembersFlag) {
|
||||
// according settings we don't need to process such fields/methods
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean satisfies(@NotNull PsiElement element, @NotNull ResolveState state) {
|
||||
final String name = PsiUtilCore.getName(element);
|
||||
if (StringUtil.isNotEmpty(name) && (myMatcher == null || myMatcher.value(name))) {
|
||||
if (name != null && StringUtil.isNotEmpty(name) && myMatcher.value(name)) {
|
||||
if (myFilter.isClassAcceptable(element.getClass()) && myFilter.isAcceptable(new CandidateInfo(element, state.get(PsiSubstitutor.KEY)), myElement)) {
|
||||
return true;
|
||||
}
|
||||
@@ -254,7 +260,7 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
|
||||
}
|
||||
|
||||
private boolean isAccessible(final PsiElement element) {
|
||||
if (!myCheckAccess) return true;
|
||||
if (!myOptions.checkAccess) return true;
|
||||
if (!(element instanceof PsiMember)) return true;
|
||||
|
||||
PsiMember member = (PsiMember)element;
|
||||
@@ -302,12 +308,43 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
|
||||
@Override
|
||||
public <T> T getHint(@NotNull Key<T> hintKey) {
|
||||
if (hintKey == ElementClassHint.KEY) {
|
||||
//noinspection unchecked
|
||||
return (T)this;
|
||||
}
|
||||
if (hintKey == JavaCompletionHints.NAME_FILTER) {
|
||||
//noinspection unchecked
|
||||
return (T)myMatcher;
|
||||
}
|
||||
|
||||
return super.getHint(hintKey);
|
||||
}
|
||||
|
||||
public static class Options {
|
||||
public static final Options DEFAULT_OPTIONS = new Options(true, false, true, false);
|
||||
public static final Options CHECK_NOTHING = new Options(false, false, false, false);
|
||||
final boolean checkAccess;
|
||||
final boolean checkInitialized;
|
||||
final boolean filterStaticAfterInstance;
|
||||
final boolean showInstanceInStaticContext;
|
||||
|
||||
private Options(boolean checkAccess, boolean checkInitialized, boolean filterStaticAfterInstance, boolean showInstanceInStaticContext) {
|
||||
this.checkAccess = checkAccess;
|
||||
this.checkInitialized = checkInitialized;
|
||||
this.filterStaticAfterInstance = filterStaticAfterInstance;
|
||||
this.showInstanceInStaticContext = showInstanceInStaticContext;
|
||||
}
|
||||
|
||||
public Options withInitialized(boolean checkInitialized) {
|
||||
return new Options(checkAccess, checkInitialized, filterStaticAfterInstance, showInstanceInStaticContext);
|
||||
}
|
||||
public Options withCheckAccess(boolean checkAccess) {
|
||||
return new Options(checkAccess, checkInitialized, filterStaticAfterInstance, showInstanceInStaticContext);
|
||||
}
|
||||
public Options withFilterStaticAfterInstance(boolean filterStaticAfterInstance) {
|
||||
return new Options(checkAccess, checkInitialized, filterStaticAfterInstance, showInstanceInStaticContext);
|
||||
}
|
||||
public Options withShowInstanceInStaticContext(boolean showInstanceInStaticContext) {
|
||||
return new Options(checkAccess, checkInitialized, filterStaticAfterInstance, showInstanceInStaticContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
public class Inspection {
|
||||
|
||||
public boolean ignoreEnums = false;
|
||||
|
||||
private static class Visitor {
|
||||
public void visitClass() {
|
||||
if (ignoen<caret>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
public class Inspection {
|
||||
|
||||
public boolean ignoreEnums = false;
|
||||
|
||||
private static class Visitor {
|
||||
public void visitClass() {
|
||||
if (ignoreEnums<caret>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -497,6 +497,12 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase {
|
||||
checkResult()
|
||||
}
|
||||
|
||||
public void testAccessInstanceFromStaticSecond() throws Throwable {
|
||||
configure()
|
||||
myFixture.complete(CompletionType.BASIC, 2)
|
||||
checkResult()
|
||||
}
|
||||
|
||||
public void testContinueLabel() throws Throwable { doTest(); }
|
||||
|
||||
public void testAnonymousProcess() {
|
||||
|
||||
Reference in New Issue
Block a user