make smart completion work in java extends/implements clauses (IDEA-38166)

This commit is contained in:
peter
2015-12-29 18:00:59 +01:00
parent 16fb4e8473
commit 2fff9c497b
5 changed files with 39 additions and 16 deletions
@@ -33,6 +33,7 @@ import com.intellij.psi.filters.types.AssignableFromFilter;
import com.intellij.psi.filters.types.AssignableToFilter;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.proximity.ReferenceListWeigher;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
@@ -79,7 +80,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
psiElement().withText(")").withParent(PsiTypeCastExpression.class)));
@Nullable
private static ElementFilter getClassReferenceFilter(PsiElement element) {
private static ElementFilter getClassReferenceFilter(final PsiElement element, final boolean inRefList) {
//throw new foo
if (AFTER_THROW_NEW.accepts(element)) {
return THROWABLES_FILTER;
@@ -98,15 +99,25 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
}
}
// extends/implements/throws
if (inRefList) {
return new ElementExtractorFilter(new ElementFilter() {
@Override
public boolean isAcceptable(Object aClass, @Nullable PsiElement context) {
return aClass instanceof PsiClass && ReferenceListWeigher.INSTANCE.getApplicability((PsiClass)aClass, element) !=
ReferenceListWeigher.ReferenceListApplicability.inapplicable;
}
@Override
public boolean isClassAcceptable(Class hintClass) {
return true;
}
});
}
return null;
}
private static boolean isInsideThrowsList(PsiElement element) {
PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
return method != null && PsiTreeUtil.isAncestor(method.getThrowsList(), element, true);
}
public JavaSmartCompletionContributor() {
extend(CompletionType.SMART, SmartCastProvider.TYPECAST_TYPE_CANDIDATE, new SmartCastProvider());
@@ -125,16 +136,13 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
final PsiJavaCodeReferenceElement reference =
PsiTreeUtil.findElementOfClassAtOffset(element.getContainingFile(), parameters.getOffset(), PsiJavaCodeReferenceElement.class, false);
if (reference != null) {
ElementFilter filter = getClassReferenceFilter(element);
boolean completeConstructor = filter != null;
if (filter == null && isInsideThrowsList(element)) {
filter = THROWABLES_FILTER;
}
boolean inRefList = ReferenceListWeigher.INSIDE_REFERENCE_LIST.accepts(element);
ElementFilter filter = getClassReferenceFilter(element, inRefList);
if (filter != null) {
final List<ExpectedTypeInfo> infos = Arrays.asList(getExpectedTypes(parameters));
for (LookupElement item : completeReference(element, reference, filter, true, false, parameters, result.getPrefixMatcher())) {
if (item.getObject() instanceof PsiClass) {
if (completeConstructor) {
if (!inRefList) {
item = LookupElementDecorator.withInsertHandler(item, ConstructorInsertHandler.SMART_INSTANCE);
}
result.addElement(decorate(item, infos));
@@ -150,7 +158,6 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
}
}
}
}
}
});
@@ -17,8 +17,8 @@ package com.intellij.psi.util.proximity;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.ProximityLocation;
@@ -33,7 +33,7 @@ import static com.intellij.psi.util.proximity.ReferenceListWeigher.ReferenceList
public class ReferenceListWeigher extends ProximityWeigher {
public static final ReferenceListWeigher INSTANCE = new ReferenceListWeigher();
private static final PsiElementPattern.Capture<PsiElement> INSIDE_REFERENCE_LIST =
public static final ElementPattern<PsiElement> INSIDE_REFERENCE_LIST =
PlatformPatterns.psiElement().withParents(PsiJavaCodeReferenceElement.class, PsiReferenceList.class);
protected enum Preference {
@@ -0,0 +1,7 @@
public class Main implements XFooIntf<caret> {
}
class XFoo1 {}
class XFoo2 {}
interface XFooIntf {}
@@ -0,0 +1,7 @@
public class Main implements XF<caret> {
}
class XFoo1 {}
class XFoo2 {}
interface XFooIntf {}
@@ -1159,6 +1159,8 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
public void testSuggestCastReturnTypeByCalledMethod() { doTest(); }
public void testOnlyInterfacesInImplements() { doTest(); }
public void testNonStaticField() throws Exception { doAntiTest(); }
private void doActionTest() throws Exception {