mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-62053 Smart completion should suggest "public static final members" of any class
This commit is contained in:
+6
-4
@@ -68,10 +68,12 @@ public class BasicExpressionCompletionContributor {
|
||||
}
|
||||
|
||||
if (!AFTER_DOT.accepts(element)) {
|
||||
new CollectionsUtilityMethodsProvider(parameters.getPosition(),
|
||||
parameters.getExpectedType(),
|
||||
parameters.getDefaultType(), result)
|
||||
.addCompletions(parameters.getParameters().getInvocationCount() > 1 || StringUtil.isNotEmpty(matcher.getPrefix()));
|
||||
if (parameters.getParameters().getInvocationCount() <= 1) {
|
||||
new CollectionsUtilityMethodsProvider(parameters.getPosition(),
|
||||
parameters.getExpectedType(),
|
||||
parameters.getDefaultType(), result)
|
||||
.addCompletions(StringUtil.isNotEmpty(matcher.getPrefix()));
|
||||
}
|
||||
ClassLiteralGetter.addCompletions(parameters, result, matcher);
|
||||
|
||||
final PsiElement position = parameters.getPosition();
|
||||
|
||||
@@ -540,7 +540,7 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
|
||||
static void addExpectedTypeMembers(CompletionParameters parameters, final CompletionResultSet result, PsiElement position) {
|
||||
for (final ExpectedTypeInfo info : JavaSmartCompletionContributor.getExpectedTypes(parameters)) {
|
||||
new JavaMembersGetter(info.getDefaultType(), position).addMembers(parameters, parameters.getInvocationCount() > 1, new Consumer<LookupElement>() {
|
||||
new JavaMembersGetter(info.getDefaultType(), parameters).addMembers(parameters.getInvocationCount() > 1, new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
result.addElement(element);
|
||||
|
||||
+2
-2
@@ -311,9 +311,9 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
|
||||
PsiElement position = params.getPosition();
|
||||
if (!BasicExpressionCompletionContributor.AFTER_DOT.accepts(position)) {
|
||||
for (ExpectedTypeInfo info : mergedInfos) {
|
||||
new JavaMembersGetter(info.getType(), position).addMembers(params, !quick, consumer);
|
||||
new JavaMembersGetter(info.getType(), params).addMembers(!quick, consumer);
|
||||
if (!info.getDefaultType().equals(info.getType())) {
|
||||
new JavaMembersGetter(info.getDefaultType(), position).addMembers(params, !quick, consumer);
|
||||
new JavaMembersGetter(info.getDefaultType(), params).addMembers(!quick, consumer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,37 +37,34 @@ import java.util.Set;
|
||||
*/
|
||||
public class JavaMembersGetter extends MembersGetter {
|
||||
private final PsiType myExpectedType;
|
||||
private final PsiElement myPlace;
|
||||
|
||||
public JavaMembersGetter(@NotNull PsiType expectedType, PsiElement place) {
|
||||
myPlace = place;
|
||||
public JavaMembersGetter(@NotNull PsiType expectedType, CompletionParameters parameters) {
|
||||
super(new JavaStaticMemberProcessor(parameters), parameters.getPosition());
|
||||
myExpectedType = JavaCompletionUtil.originalize(expectedType);
|
||||
}
|
||||
|
||||
public void addMembers(CompletionParameters parameters, boolean searchInheritors, final Consumer<LookupElement> results) {
|
||||
final StaticMemberProcessor processor = new JavaStaticMemberProcessor(parameters);
|
||||
final PsiElement position = parameters.getPosition();
|
||||
public void addMembers(boolean searchInheritors, final Consumer<LookupElement> results) {
|
||||
if (myExpectedType instanceof PsiPrimitiveType && PsiType.DOUBLE.isAssignableFrom(myExpectedType)) {
|
||||
addConstantsFromTargetClass(position, results, searchInheritors, processor);
|
||||
addConstantsFromReferencedClassesInSwitch(position, results, processor);
|
||||
addConstantsFromTargetClass(results, searchInheritors);
|
||||
addConstantsFromReferencedClassesInSwitch(results);
|
||||
}
|
||||
|
||||
if (position.getParent().getParent() instanceof PsiSwitchLabelStatement) {
|
||||
if (myPlace.getParent().getParent() instanceof PsiSwitchLabelStatement) {
|
||||
return; //non-enum values are processed above, enum values will be suggested by reference completion
|
||||
}
|
||||
|
||||
final PsiClass psiClass = PsiUtil.resolveClassInType(myExpectedType);
|
||||
processMembers(position, results, psiClass, PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) != null, searchInheritors, processor);
|
||||
processMembers(results, psiClass, PsiTreeUtil.getParentOfType(myPlace, PsiAnnotation.class) == null, searchInheritors);
|
||||
}
|
||||
|
||||
private void addConstantsFromReferencedClassesInSwitch(PsiElement position, final Consumer<LookupElement> results, final StaticMemberProcessor processor) {
|
||||
final Set<PsiField> fields = ReferenceExpressionCompletionContributor.findConstantsUsedInSwitch(position);
|
||||
private void addConstantsFromReferencedClassesInSwitch(final Consumer<LookupElement> results) {
|
||||
final Set<PsiField> fields = ReferenceExpressionCompletionContributor.findConstantsUsedInSwitch(myPlace);
|
||||
final Set<PsiClass> classes = new HashSet<PsiClass>();
|
||||
for (PsiField field : fields) {
|
||||
ContainerUtil.addIfNotNull(classes, field.getContainingClass());
|
||||
}
|
||||
for (PsiClass aClass : classes) {
|
||||
processMembers(position, new Consumer<LookupElement>() {
|
||||
processMembers(new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
//noinspection SuspiciousMethodCalls
|
||||
@@ -75,14 +72,12 @@ public class JavaMembersGetter extends MembersGetter {
|
||||
results.consume(TailTypeDecorator.withTail(element, TailType.CASE_COLON));
|
||||
}
|
||||
}
|
||||
}, aClass, false, false, processor);
|
||||
}, aClass, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void addConstantsFromTargetClass(PsiElement position,
|
||||
Consumer<LookupElement> results,
|
||||
boolean searchInheritors, final StaticMemberProcessor processor) {
|
||||
PsiElement parent = position.getParent();
|
||||
private void addConstantsFromTargetClass(Consumer<LookupElement> results, boolean searchInheritors) {
|
||||
PsiElement parent = myPlace.getParent();
|
||||
if (!(parent instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
}
|
||||
@@ -94,8 +89,8 @@ public class JavaMembersGetter extends MembersGetter {
|
||||
final IElementType op = binaryExpression.getOperationTokenType();
|
||||
if (JavaTokenType.EQEQ == op || JavaTokenType.NE == op) {
|
||||
if (prev == binaryExpression.getROperand()) {
|
||||
processMembers(position, results, getCalledClass(binaryExpression.getLOperand()), false, searchInheritors,
|
||||
processor);
|
||||
processMembers(results, getCalledClass(binaryExpression.getLOperand()), true, searchInheritors
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -103,7 +98,7 @@ public class JavaMembersGetter extends MembersGetter {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent instanceof PsiExpressionList) {
|
||||
processMembers(position, results, getCalledClass(parent.getParent()), false, searchInheritors, processor);
|
||||
processMembers(results, getCalledClass(parent.getParent()), true, searchInheritors);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,11 +22,13 @@ import com.intellij.codeInsight.completion.PrefixMatcher;
|
||||
import com.intellij.codeInsight.completion.StaticMemberProcessor;
|
||||
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.filters.TrueFilter;
|
||||
import com.intellij.psi.impl.java.stubs.index.JavaStaticMemberTypeIndex;
|
||||
import com.intellij.psi.scope.processor.FilterScopeProcessor;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
@@ -35,10 +37,7 @@ import com.intellij.util.PairConsumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author ik
|
||||
@@ -46,89 +45,107 @@ import java.util.Set;
|
||||
*/
|
||||
public abstract class MembersGetter {
|
||||
public static final Key<Boolean> EXPECTED_TYPE_INHERITOR_MEMBER = Key.create("EXPECTED_TYPE_INHERITOR_MEMBER");
|
||||
private final Set<PsiMember> myImportedStatically = new HashSet<PsiMember>();
|
||||
private final List<PsiClass> myPlaceClasses = new ArrayList<PsiClass>();
|
||||
private final List<PsiMethod> myPlaceMethods = new ArrayList<PsiMethod>();
|
||||
protected final PsiElement myPlace;
|
||||
|
||||
public void processMembers(@NotNull final PsiElement context, final Consumer<LookupElement> results, @Nullable final PsiClass where,
|
||||
final boolean acceptMethods, boolean searchInheritors,
|
||||
StaticMemberProcessor processor) {
|
||||
if (where == null) return;
|
||||
|
||||
final List<PsiClass> placeClasses = new ArrayList<PsiClass>();
|
||||
|
||||
PsiClass current = PsiTreeUtil.getContextOfType(context, PsiClass.class);
|
||||
while (current != null) {
|
||||
current = CompletionUtil.getOriginalOrSelf(current);
|
||||
placeClasses.add(current);
|
||||
current = PsiTreeUtil.getContextOfType(current, PsiClass.class);
|
||||
}
|
||||
|
||||
final Set<PsiMember> importedStatically = new HashSet<PsiMember>();
|
||||
protected MembersGetter(StaticMemberProcessor processor, @NotNull final PsiElement place) {
|
||||
myPlace = place;
|
||||
processor.processMembersOfRegisteredClasses(PrefixMatcher.ALWAYS_TRUE, new PairConsumer<PsiMember, PsiClass>() {
|
||||
@Override
|
||||
public void consume(PsiMember member, PsiClass psiClass) {
|
||||
importedStatically.add(member);
|
||||
myImportedStatically.add(member);
|
||||
}
|
||||
});
|
||||
|
||||
final Condition<PsiClass> mayProcessMembers = new Condition<PsiClass>() {
|
||||
@Override
|
||||
public boolean value(PsiClass psiClass) {
|
||||
if (psiClass == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
psiClass = CompletionUtil.getOriginalOrSelf(psiClass);
|
||||
for (PsiClass placeClass : placeClasses) {
|
||||
if (InheritanceUtil.isInheritorOrSelf(placeClass, psiClass, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
PsiClass current = PsiTreeUtil.getContextOfType(place, PsiClass.class);
|
||||
while (current != null) {
|
||||
current = CompletionUtil.getOriginalOrSelf(current);
|
||||
myPlaceClasses.add(current);
|
||||
current = PsiTreeUtil.getContextOfType(current, PsiClass.class);
|
||||
}
|
||||
|
||||
PsiMethod eachMethod = PsiTreeUtil.getContextOfType(place, PsiMethod.class);
|
||||
while (eachMethod != null) {
|
||||
eachMethod = CompletionUtil.getOriginalOrSelf(eachMethod);
|
||||
myPlaceMethods.add(eachMethod);
|
||||
eachMethod = PsiTreeUtil.getContextOfType(eachMethod, PsiMethod.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean mayProcessMembers(@Nullable PsiClass psiClass) {
|
||||
if (psiClass == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (PsiClass placeClass : myPlaceClasses) {
|
||||
if (InheritanceUtil.isInheritorOrSelf(placeClass, psiClass, true)) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(context.getProject()).getResolveHelper();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
final PsiClassType baseType = JavaPsiFacade.getElementFactory(where.getProject()).createType(where);
|
||||
public void processMembers(final Consumer<LookupElement> results, @Nullable final PsiClass where,
|
||||
final boolean acceptMethods, final boolean searchInheritors) {
|
||||
if (where == null) return;
|
||||
|
||||
final boolean searchFactoryMethods = searchInheritors &&
|
||||
!CommonClassNames.JAVA_LANG_OBJECT.equals(where.getQualifiedName()) &&
|
||||
!CommonClassNames.JAVA_LANG_STRING.equals(where.getQualifiedName());
|
||||
|
||||
final Project project = myPlace.getProject();
|
||||
final GlobalSearchScope scope = myPlace.getResolveScope();
|
||||
|
||||
final PsiClassType baseType = JavaPsiFacade.getElementFactory(project).createType(where);
|
||||
Consumer<PsiType> consumer = new Consumer<PsiType>() {
|
||||
@Override
|
||||
public void consume(PsiType psiType) {
|
||||
PsiClass psiClass = PsiUtil.resolveClassInType(psiType);
|
||||
if (mayProcessMembers.value(psiClass)) {
|
||||
psiClass = CompletionUtil.getOriginalOrSelf(psiClass);
|
||||
for (PsiClass placeClass : placeClasses) {
|
||||
if (InheritanceUtil.isInheritorOrSelf(placeClass, psiClass, true)) {
|
||||
return;
|
||||
}
|
||||
if (psiClass == null) {
|
||||
return;
|
||||
}
|
||||
psiClass = CompletionUtil.getOriginalOrSelf(psiClass);
|
||||
if (mayProcessMembers(psiClass)) {
|
||||
final FilterScopeProcessor<PsiElement> declProcessor = new FilterScopeProcessor<PsiElement>(TrueFilter.INSTANCE);
|
||||
psiClass.processDeclarations(declProcessor, ResolveState.initial(), null, myPlace);
|
||||
doProcessMembers(acceptMethods, results, psiType != baseType, declProcessor.getResults());
|
||||
|
||||
String name = psiClass.getName();
|
||||
if (name != null && searchFactoryMethods) {
|
||||
Collection<PsiMember> factoryMethods = JavaStaticMemberTypeIndex.getInstance().getStaticMembers(name, project, scope);
|
||||
doProcessMembers(acceptMethods, results, psiType != baseType, factoryMethods);
|
||||
}
|
||||
processClassDeclaredMembers(psiClass, context, acceptMethods, results, resolveHelper, importedStatically, psiType != baseType);
|
||||
}
|
||||
}
|
||||
};
|
||||
consumer.consume(baseType);
|
||||
if (searchInheritors && !CommonClassNames.JAVA_LANG_OBJECT.equals(where.getQualifiedName())) {
|
||||
CodeInsightUtil.processSubTypes(baseType, context, true, PrefixMatcher.ALWAYS_TRUE, consumer);
|
||||
CodeInsightUtil.processSubTypes(baseType, myPlace, true, PrefixMatcher.ALWAYS_TRUE, consumer);
|
||||
}
|
||||
}
|
||||
|
||||
private void processClassDeclaredMembers(PsiClass where,
|
||||
PsiElement context,
|
||||
boolean acceptMethods,
|
||||
Consumer<LookupElement> results, final PsiResolveHelper resolveHelper, final Set<PsiMember> importedStatically, boolean isInheritor) {
|
||||
final FilterScopeProcessor<PsiElement> processor = new FilterScopeProcessor<PsiElement>(TrueFilter.INSTANCE);
|
||||
where.processDeclarations(processor, ResolveState.initial(), null, context);
|
||||
|
||||
for (final PsiElement result : processor.getResults()) {
|
||||
private void doProcessMembers(boolean acceptMethods,
|
||||
Consumer<LookupElement> results,
|
||||
boolean isInheritor, Collection<? extends PsiElement> declarations) {
|
||||
for (final PsiElement result : declarations) {
|
||||
if (result instanceof PsiMember && !(result instanceof PsiClass)) {
|
||||
final PsiMember member = (PsiMember)result;
|
||||
if (JavaCompletionUtil.isInExcludedPackage(member, false) || importedStatically.contains(member)) continue;
|
||||
if (member.hasModifierProperty(PsiModifier.STATIC) && resolveHelper.isAccessible(member, context, null)) {
|
||||
if (result instanceof PsiField && !member.hasModifierProperty(PsiModifier.FINAL)) continue;
|
||||
if (result instanceof PsiMethod && acceptMethods) continue;
|
||||
final LookupElement item = result instanceof PsiMethod ? createMethodElement((PsiMethod)result) : createFieldElement((PsiField)result);
|
||||
if (item != null) {
|
||||
item.putUserData(EXPECTED_TYPE_INHERITOR_MEMBER, isInheritor);
|
||||
results.consume(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(item));
|
||||
}
|
||||
if (!member.hasModifierProperty(PsiModifier.STATIC)) continue;
|
||||
if (result instanceof PsiField && !member.hasModifierProperty(PsiModifier.FINAL)) continue;
|
||||
if (result instanceof PsiMethod && (!acceptMethods || myPlaceMethods.contains(result))) continue;
|
||||
if (JavaCompletionUtil.isInExcludedPackage(member, false) || myImportedStatically.contains(member)) continue;
|
||||
|
||||
if (!JavaPsiFacade.getInstance(myPlace.getProject()).getResolveHelper().isAccessible(member, myPlace, null)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final LookupElement item = result instanceof PsiMethod ? createMethodElement((PsiMethod)result) : createFieldElement((PsiField)result);
|
||||
if (item != null) {
|
||||
item.putUserData(EXPECTED_TYPE_INHERITOR_MEMBER, isInheritor);
|
||||
results.consume(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ public class JavaStaticMemberTypeIndex extends StringStubIndexExtension<PsiMembe
|
||||
return JavaStubIndexKeys.JVM_STATIC_MEMBERS_TYPES;
|
||||
}
|
||||
|
||||
public Collection<PsiMember> getStaticMembers(final String shortTypeText, final Project project, @NotNull final GlobalSearchScope scope) {
|
||||
public Collection<PsiMember> getStaticMembers(@NotNull final String shortTypeText, final Project project, @NotNull final GlobalSearchScope scope) {
|
||||
return super.get(shortTypeText, project, new JavaSourceFilterScope(scope));
|
||||
}
|
||||
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import java.lang.Object;
|
||||
|
||||
class Super<T> {
|
||||
}
|
||||
|
||||
class SubString extends Super<String> {
|
||||
public static SubString createSubString() {}
|
||||
}
|
||||
class SubInt extends Super<Integer> { }
|
||||
class SubGeneric<T> extends Super<T> { }
|
||||
class SubRaw extends Super { }
|
||||
|
||||
class Factory {
|
||||
public static Object createObject() {}
|
||||
public static <T> Super<T> createExpected() {}
|
||||
public static Super<Integer> createSuperInt() {}
|
||||
public static SubInt createSubInt() {}
|
||||
public static <T> SubGeneric<T> createSubGeneric() {}
|
||||
public static SubRaw createSubRaw() {}
|
||||
}
|
||||
|
||||
class Intermediate {
|
||||
|
||||
Super<String> s = create<caret>x
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ public class Test {
|
||||
|
||||
static MyEnum getAvailabilityStatusCode() {
|
||||
|
||||
return get<caret>
|
||||
return getAS<caret>
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ class C{
|
||||
{
|
||||
Object o;
|
||||
if (o instanceof Foo) {
|
||||
new Object().do<caret>
|
||||
new Object().dofo<caret>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+26
-26
@@ -2,23 +2,25 @@ package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.lookup.*;
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl;
|
||||
import com.intellij.codeInsight.lookup.LookupElementDecorator;
|
||||
import com.intellij.codeInsight.lookup.LookupElementPresentation;
|
||||
import com.intellij.codeInsight.lookup.LookupItem;
|
||||
import com.intellij.codeInsight.lookup.LookupManager;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
@SuppressWarnings({"ALL"})
|
||||
public class SecondSmartTypeCompletionTest extends LightCompletionTestCase {
|
||||
private static final String BASE_PATH = "/codeInsight/completion/smartType/second";
|
||||
public class SecondSmartTypeCompletionTest extends LightFixtureCompletionTestCase {
|
||||
|
||||
public SecondSmartTypeCompletionTest() {
|
||||
setType(CompletionType.SMART);
|
||||
@Override
|
||||
protected void complete() {
|
||||
myItems = myFixture.complete(CompletionType.SMART, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath();
|
||||
protected String getBasePath() {
|
||||
return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/completion/smartType/second";
|
||||
}
|
||||
|
||||
public void testMethodAsQualifier() throws Throwable { doTest(); }
|
||||
@@ -69,7 +71,7 @@ public class SecondSmartTypeCompletionTest extends LightCompletionTestCase {
|
||||
public void testDontIgnoreToStringInsideIt() throws Throwable { doTest(); }
|
||||
public void testDontIgnoreToStringInStringBuilders() throws Throwable {
|
||||
configure();
|
||||
assertStringItems("bar.substring", "bar.substring", "bar.toString");
|
||||
myFixture.assertPreferredCompletionItems(0, "bar.substring", "bar.substring", "bar.toString");
|
||||
}
|
||||
|
||||
public void testNoObjectMethodsAsFirstPart() throws Throwable { doTest(); }
|
||||
@@ -81,7 +83,7 @@ public class SecondSmartTypeCompletionTest extends LightCompletionTestCase {
|
||||
public void testNewStaticProblem() throws Throwable { doTest(); }
|
||||
|
||||
public void testChainingPerformance() throws Throwable {
|
||||
configureByFileNoComplete(BASE_PATH + "/" + getTestName(false) + ".java");
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
PlatformTestUtil.startPerformanceTest(getTestName(false), 1000, new ThrowableRunnable() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
@@ -103,12 +105,12 @@ public class SecondSmartTypeCompletionTest extends LightCompletionTestCase {
|
||||
}
|
||||
|
||||
private void configure() {
|
||||
configureByFile(BASE_PATH + "/" + getTestName(false) + ".java");
|
||||
configureByFile(getTestName(false) + ".java");
|
||||
}
|
||||
|
||||
public void testNoArraysAsListCommonPrefix() throws Throwable {
|
||||
configure();
|
||||
checkResultByFile(BASE_PATH + "/" + getTestName(false) + ".java");
|
||||
checkResultByFile(getTestName(false) + ".java");
|
||||
assertStringItems("bar()", "foo()");
|
||||
assertEquals("Arrays.asList(f.bar())", ((LookupItem)((LookupElementDecorator)myItems[0]).getDelegate()).getPresentableText());
|
||||
assertEquals("Arrays.asList(f.foo())", ((LookupItem)((LookupElementDecorator)myItems[1]).getDelegate()).getPresentableText());
|
||||
@@ -117,11 +119,11 @@ public class SecondSmartTypeCompletionTest extends LightCompletionTestCase {
|
||||
}
|
||||
|
||||
public void testRestoreInitialPrefix() throws Throwable {
|
||||
configureByFileNoComplete(BASE_PATH + "/" + getTestName(false) + ".java");
|
||||
complete(1);
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
myFixture.complete(CompletionType.SMART);
|
||||
assertStringItems("MyEnum.Bar", "MyEnum.Foo");
|
||||
checkResult();
|
||||
complete(1);
|
||||
myFixture.complete(CompletionType.SMART);
|
||||
assertStringItems("my.getEnum", "MyEnum.Bar", "MyEnum.Foo");
|
||||
}
|
||||
|
||||
@@ -138,8 +140,8 @@ public class SecondSmartTypeCompletionTest extends LightCompletionTestCase {
|
||||
|
||||
private void doAntiTest() throws Exception {
|
||||
configure();
|
||||
assertNull(myItems);
|
||||
checkResultByFile(BASE_PATH + "/" + getTestName(false) + ".java");
|
||||
assertEmpty(myItems);
|
||||
checkResultByFile(getTestName(false) + ".java");
|
||||
}
|
||||
|
||||
public void testCastInstanceofedQualifier() throws Throwable { doTest(); }
|
||||
@@ -157,7 +159,7 @@ public class SecondSmartTypeCompletionTest extends LightCompletionTestCase {
|
||||
|
||||
public void testNoRedundantCasts() throws Throwable {
|
||||
configure();
|
||||
checkResultByFile(BASE_PATH + "/" + getTestName(false) + ".java");
|
||||
checkResultByFile(getTestName(false) + ".java");
|
||||
assertStringItems("o.gggg", "false", "true");
|
||||
}
|
||||
|
||||
@@ -168,7 +170,7 @@ public class SecondSmartTypeCompletionTest extends LightCompletionTestCase {
|
||||
}
|
||||
|
||||
private void checkResult() {
|
||||
checkResultByFile(BASE_PATH + "/" + getTestName(false) + "-out.java");
|
||||
checkResultByFile(getTestName(false) + "-out.java");
|
||||
}
|
||||
|
||||
public void testSingletonMap() throws Throwable {
|
||||
@@ -202,6 +204,11 @@ public class SecondSmartTypeCompletionTest extends LightCompletionTestCase {
|
||||
checkResult();
|
||||
}
|
||||
|
||||
public void testGlobalFactoryMethods() {
|
||||
configure();
|
||||
assertStringItems("createExpected", "createSubGeneric", "createSubRaw", "createSubString");
|
||||
}
|
||||
|
||||
public void testEmptyMapPresentation() {
|
||||
configure();
|
||||
LookupElementPresentation presentation = new LookupElementPresentation();
|
||||
@@ -216,13 +223,6 @@ public class SecondSmartTypeCompletionTest extends LightCompletionTestCase {
|
||||
assertEquals("Collections.emptyMap", presentation.getItemText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void complete() {
|
||||
complete(2);
|
||||
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(myEditor);
|
||||
myItems = lookup == null ? null : lookup.getItems().toArray(LookupElement.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
LookupManager.getInstance(getProject()).hideActiveLookup();
|
||||
super.tearDown();
|
||||
|
||||
+2
-3
@@ -301,9 +301,8 @@ public class SmartTypeCompletionOrderingTest extends CompletionSortingTestCase {
|
||||
myFixture.addClass("package foo; public class FList<T> implements java.util.List<T> { public static <T> FList<T> emptyList() {} }");
|
||||
configureNoCompletion(getTestName(false) + ".java");
|
||||
myFixture.complete(CompletionType.SMART, 2);
|
||||
assertPreferredItems(0, "local", "local.subList", "locMethod", "locMethod().subList", "emptyList", "singletonList", "unmodifiableList", "emptyList");
|
||||
assert 'Collections.emptyList' in lookup.items[4].allLookupStrings
|
||||
assert 'FList.emptyList' in lookup.items[7].allLookupStrings
|
||||
assert lookup.items.findIndexOf { 'Collections.emptyList' in it.allLookupStrings } < lookup.items.findIndexOf { 'FList.emptyList' in it.allLookupStrings }
|
||||
assertPreferredItems(0, "local", "local.subList", "locMethod")
|
||||
}
|
||||
|
||||
public void testDispreferGetterInSetterCall() {
|
||||
|
||||
+1
-2
@@ -23,7 +23,6 @@ import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -103,7 +102,7 @@ public abstract class LightCompletionTestCase extends LightCodeInsightTestCase {
|
||||
}
|
||||
|
||||
protected void assertStringItems(@NonNls String... items) {
|
||||
assertEquals(getLookupStrings(new ArrayList<String>()), Arrays.asList(items));
|
||||
assertOrderedEquals(getLookupStrings(new ArrayList<String>()), items);
|
||||
}
|
||||
|
||||
protected void assertContainsItems(final String... expected) {
|
||||
|
||||
@@ -363,7 +363,7 @@ public abstract class CompletionPhase implements Disposable {
|
||||
@Override
|
||||
public int newCompletionStarted(int time, boolean repeated) {
|
||||
CompletionServiceImpl.setCompletionPhase(NoCompletion);
|
||||
return time + 1;
|
||||
return repeated ? time + 1 : time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-10
@@ -18,7 +18,10 @@ package org.jetbrains.plugins.groovy.lang.completion;
|
||||
import com.intellij.codeInsight.completion.CompletionParameters;
|
||||
import com.intellij.codeInsight.completion.JavaCompletionUtil;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiClassType;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.filters.getters.MembersGetter;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
@@ -31,23 +34,19 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUt
|
||||
*/
|
||||
class GroovyMembersGetter extends MembersGetter {
|
||||
private final PsiClassType myExpectedType;
|
||||
private final GroovyPsiElement myContext;
|
||||
private final CompletionParameters myParameters;
|
||||
|
||||
GroovyMembersGetter(PsiClassType expectedType, PsiElement context, CompletionParameters parameters) {
|
||||
myParameters = parameters;
|
||||
GroovyMembersGetter(PsiClassType expectedType, CompletionParameters parameters) {
|
||||
super(GroovyCompletionContributor.completeStaticMembers(parameters), parameters.getPosition());
|
||||
myExpectedType = JavaCompletionUtil.originalize(expectedType);
|
||||
myContext = (GroovyPsiElement)context;
|
||||
}
|
||||
|
||||
public void processMembers(boolean searchInheritors, final Consumer<LookupElement> results) {
|
||||
processMembers(myContext, results, myExpectedType.resolve(), PsiTreeUtil.getParentOfType(myContext, GrAnnotation.class) != null, searchInheritors,
|
||||
GroovyCompletionContributor.completeStaticMembers(myParameters));
|
||||
processMembers(results, myExpectedType.resolve(), PsiTreeUtil.getParentOfType(myPlace, GrAnnotation.class) == null, searchInheritors);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LookupElement createFieldElement(PsiField field) {
|
||||
if (!TypesUtil.isAssignable(myExpectedType, field.getType(), myContext)) {
|
||||
if (!isSuitableType(field.getType())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -57,10 +56,14 @@ class GroovyMembersGetter extends MembersGetter {
|
||||
@Override
|
||||
protected LookupElement createMethodElement(PsiMethod method) {
|
||||
PsiType type = method.getReturnType();
|
||||
if (type == null || !TypesUtil.isAssignable(myExpectedType, type, myContext)) {
|
||||
if (!isSuitableType(type)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return GroovyCompletionContributor.createGlobalMemberElement(method, method.getContainingClass(), false);
|
||||
}
|
||||
|
||||
private boolean isSuitableType(PsiType type) {
|
||||
return type != null && TypesUtil.isAssignable(myExpectedType, type, (GroovyPsiElement)myPlace.getParent());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -208,10 +208,10 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
|
||||
PsiType defType = info.getDefaultType();
|
||||
boolean searchInheritors = params.getInvocationCount() > 1;
|
||||
if (type instanceof PsiClassType) {
|
||||
new GroovyMembersGetter((PsiClassType)type, reference, params).processMembers(searchInheritors, consumer);
|
||||
new GroovyMembersGetter((PsiClassType)type, params).processMembers(searchInheritors, consumer);
|
||||
}
|
||||
if (!defType.equals(type) && defType instanceof PsiClassType) {
|
||||
new GroovyMembersGetter((PsiClassType)defType, reference, params).processMembers(searchInheritors, consumer);
|
||||
new GroovyMembersGetter((PsiClassType)defType, params).processMembers(searchInheritors, consumer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user