IDEA-130264 Completion for super methods of containing class

This commit is contained in:
peter
2015-10-24 23:42:27 +02:00
parent 6694afe5b8
commit 3ed90b5c22
5 changed files with 135 additions and 11 deletions
@@ -274,7 +274,7 @@ public class JavaCompletionUtil {
if (runtimeQualifier != null) {
PsiType composite = qualifierType == null ? runtimeQualifier : PsiIntersectionType.createIntersection(qualifierType, runtimeQualifier);
PsiElement ctx = createContextWithXxxVariable(element, composite);
javaReference = (PsiReferenceExpression) JavaPsiFacade.getElementFactory(element.getProject()).createExpressionFromText("xxx.xxx", ctx);
javaReference = createReference("xxx.xxx", ctx);
qualifierType = runtimeQualifier;
processor.setQualifierType(qualifierType);
}
@@ -306,21 +306,32 @@ public class JavaCompletionUtil {
}
}
if (javaReference instanceof PsiJavaCodeReferenceElement && !((PsiJavaCodeReferenceElement)javaReference).isQualified()) {
final StaticMemberProcessor memberProcessor = new JavaStaticMemberProcessor(parameters);
memberProcessor.processMembersOfRegisteredClasses(matcher, new PairConsumer<PsiMember, PsiClass>() {
@Override
public void consume(PsiMember member, PsiClass psiClass) {
if (!mentioned.contains(member) && processor.satisfies(member, ResolveState.initial())) {
set.add(memberProcessor.createLookupElement(member, psiClass, true));
if (javaReference instanceof PsiJavaCodeReferenceElement) {
PsiElement refQualifier = ((PsiJavaCodeReferenceElement)javaReference).getQualifier();
if (refQualifier == null) {
final StaticMemberProcessor memberProcessor = new JavaStaticMemberProcessor(parameters);
memberProcessor.processMembersOfRegisteredClasses(matcher, new PairConsumer<PsiMember, PsiClass>() {
@Override
public void consume(PsiMember member, PsiClass psiClass) {
if (!mentioned.contains(member) && processor.satisfies(member, ResolveState.initial())) {
set.add(memberProcessor.createLookupElement(member, psiClass, true));
}
}
}
});
});
}
else if (refQualifier instanceof PsiSuperExpression && ((PsiSuperExpression)refQualifier).getQualifier() == null) {
set.addAll(SuperCalls.suggestQualifyingSuperCalls(element, javaReference, elementFilter, options, nameCondition));
}
}
return set;
}
@NotNull
static PsiReferenceExpression createReference(@NotNull String text, @NotNull PsiElement context) {
return (PsiReferenceExpression) JavaPsiFacade.getElementFactory(context.getProject()).createExpressionFromText(text, context);
}
@Nullable
private static PsiType getQualifierCastType(PsiJavaReference javaReference, CompletionParameters parameters) {
if (javaReference instanceof PsiReferenceExpression) {
@@ -480,7 +491,7 @@ public class JavaCompletionUtil {
return false;
}
private static List<? extends LookupElement> createLookupElements(CompletionElement completionElement, PsiJavaReference reference) {
static List<? extends LookupElement> createLookupElements(CompletionElement completionElement, PsiJavaReference reference) {
Object completion = completionElement.getElement();
assert !(completion instanceof LookupElement);
@@ -0,0 +1,89 @@
/*
* Copyright 2000-2015 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 com.intellij.codeInsight.completion;
import com.intellij.codeInsight.completion.scope.CompletionElement;
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementDecorator;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
/**
* @author peter
*/
class SuperCalls {
static Set<LookupElement> suggestQualifyingSuperCalls(PsiElement element,
PsiJavaReference javaReference,
ElementFilter elementFilter,
JavaCompletionProcessor.Options options,
Condition<String> nameCondition) {
Set<LookupElement> set = ContainerUtil.newLinkedHashSet();
for (final String className : getContainingClassNames(element)) {
PsiReferenceExpression fakeSuper = JavaCompletionUtil.createReference(className + ".super.rulez", element);
PsiElement leaf = ObjectUtils.assertNotNull(fakeSuper.getReferenceNameElement());
JavaCompletionProcessor superProcessor = new JavaCompletionProcessor(leaf, elementFilter, options, nameCondition);
fakeSuper.processVariants(superProcessor);
for (CompletionElement completionElement : superProcessor.getResults()) {
for (LookupElement item : JavaCompletionUtil.createLookupElements(completionElement, javaReference)) {
set.add(withQuaifiedSuper(className, item));
}
}
}
return set;
}
@NotNull
private static LookupElementDecorator<LookupElement> withQuaifiedSuper(final String className, LookupElement item) {
return LookupElementDecorator.withInsertHandler(item, new InsertHandler<LookupElementDecorator<LookupElement>>() {
@Override
public void handleInsert(InsertionContext context, LookupElementDecorator<LookupElement> item) {
context.commitDocument();
PsiJavaCodeReferenceElement ref = PsiTreeUtil
.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiJavaCodeReferenceElement.class, false);
if (ref != null) {
context.getDocument().insertString(ref.getTextRange().getStartOffset(), className + ".");
}
item.getDelegate().handleInsert(context);
}
});
}
private static Set<String> getContainingClassNames(PsiElement position) {
Set<String> result = ContainerUtil.newLinkedHashSet();
boolean add = false;
while (position != null) {
if (position instanceof PsiAnonymousClass) {
add = true;
}
else if (add && position instanceof PsiClass) {
ContainerUtil.addIfNotNull(result, ((PsiClass)position).getName());
}
position = position.getParent();
}
return result;
}
}
@@ -0,0 +1,11 @@
import java.util.HashMap;
public class Class2 extends HashMap {
void foo() {
new Runnable() {
public void run() {
super.pu<caret>
}
};
}
}
@@ -0,0 +1,11 @@
import java.util.HashMap;
public class Class2 extends HashMap {
void foo() {
new Runnable() {
public void run() {
Class2.super.put(<caret>)
}
};
}
}
@@ -1040,6 +1040,8 @@ public class ListUtils {
doTest()
}
public void testOuterSuperMethodCall() { doTest('\n') }
public void testTopLevelClassesFromPackaged() throws Throwable {
myFixture.addClass "public class Fooooo {}"
final text = "package foo; class Bar { Fooo<caret> }"