java global member name completion initial (IDEA-54855)

This commit is contained in:
peter
2010-08-26 19:23:28 +01:00
parent 0afff998b0
commit 3a364bbe41
8 changed files with 171 additions and 10 deletions
@@ -0,0 +1,113 @@
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.completion.simple.PsiMethodInsertHandler;
import com.intellij.codeInsight.lookup.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Iconable;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiTreeUtil;
/**
* @author peter
*/
public class JavaGlobalMemberNameCompletionContributor extends CompletionContributor {
private static final LookupElementRenderer<LookupElement> STATIC_METHOD_RENDERER = new LookupElementRenderer<LookupElement>() {
@Override
public void renderElement(LookupElement element, LookupElementPresentation presentation) {
PsiMethod method = (PsiMethod)element.getObject();
final PsiClass containingClass = method.getContainingClass();
presentation.setIcon(method.getIcon(Iconable.ICON_FLAG_VISIBILITY)); //todo don't calculate if not a real presentation
presentation.setItemText(method.getName());
final String params = PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY,
PsiFormatUtil.SHOW_PARAMETERS,
PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE);
if (containingClass != null) {
presentation.setTailText(params + " in (" + containingClass.getName() + ")");
} else {
presentation.setTailText(params);
}
final PsiType type = method.getReturnType();
if (type != null) {
presentation.setTypeText(type.getPresentableText());
}
}
};
private static final InsertHandler<LookupElement> STATIC_METHOD_INSERT_HANDLER = new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
PsiMethodInsertHandler.INSTANCE.handleInsert(context, item);
final PsiClass containingClass = ((PsiMethod)item.getObject()).getContainingClass();
if (containingClass != null) {
PsiDocumentManager.getInstance(containingClass.getProject()).commitDocument(context.getDocument());
final PsiReferenceExpression ref = PsiTreeUtil
.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiReferenceExpression.class, false);
if (ref != null) {
ref.bindToElementViaStaticImport(containingClass);
}
}
}
};
@Override
public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) {
if (parameters.getCompletionType() != CompletionType.CLASS_NAME) {
return;
}
final PrefixMatcher matcher = result.getPrefixMatcher();
final String prefix = matcher.getPrefix();
if (prefix.length() == 0 || !Character.isLowerCase(prefix.charAt(0))) {
return;
}
final PsiElement position = parameters.getPosition();
final PsiElement parent = position.getParent();
if (!(parent instanceof PsiReferenceExpression)) {
return;
}
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)parent;
if (referenceExpression.isQualified()) {
return;
}
final Project project = position.getProject();
final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
final PsiShortNamesCache namesCache = JavaPsiFacade.getInstance(project).getShortNamesCache();
final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
final String[] methodNames = ApplicationManager.getApplication().runReadAction(new Computable<String[]>() {
public String[] compute() {
return namesCache.getAllMethodNames();
}
});
for (final String methodName : methodNames) {
if (matcher.prefixMatches(methodName)) {
final PsiMethod[] methods = ApplicationManager.getApplication().runReadAction(new Computable<PsiMethod[]>() {
public PsiMethod[] compute() {
return namesCache.getMethodsByName(methodName, scope);
}
});
for (final PsiMethod method : methods) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (method.hasModifierProperty(PsiModifier.STATIC) && resolveHelper.isAccessible(method, position, null)) {
final PsiClass containingClass = method.getContainingClass();
if (containingClass != null) {
result.addElement(LookupElementDecorator.withInsertHandler(
LookupElementDecorator.withRenderer(LookupElementBuilder.create(method), STATIC_METHOD_RENDERER),
STATIC_METHOD_INSERT_HANDLER));
}
}
}
});
}
}
}
}
}
@@ -39,11 +39,11 @@ import org.jetbrains.annotations.Nullable;
/**
* @author peter
*/
public class PsiMethodInsertHandler implements InsertHandler<LookupItem<PsiMethod>> {
public class PsiMethodInsertHandler implements InsertHandler<LookupElement> {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.simple.PsiMethodInsertHandler");
public static final PsiMethodInsertHandler INSTANCE = new PsiMethodInsertHandler();
public static void insertParentheses(final InsertionContext context, final LookupItem item, boolean overloadsMatter, boolean hasParams) {
public static void insertParentheses(final InsertionContext context, final LookupElement item, boolean overloadsMatter, boolean hasParams) {
final Editor editor = context.getEditor();
final TailType tailType = getTailType(item, context);
final PsiFile file = context.getFile();
@@ -73,12 +73,12 @@ public class PsiMethodInsertHandler implements InsertHandler<LookupItem<PsiMetho
}
}
public void handleInsert(final InsertionContext context, final LookupItem<PsiMethod> item) {
public void handleInsert(final InsertionContext context, final LookupElement item) {
final Editor editor = context.getEditor();
final Document document = editor.getDocument();
final PsiFile file = context.getFile();
final int offset = editor.getCaretModel().getOffset();
final PsiMethod method = item.getObject();
final PsiMethod method = (PsiMethod)item.getObject();
final LookupElement[] allItems = context.getElements();
final boolean overloadsMatter = allItems.length == 1 && item.getUserData(LookupItem.FORCE_SHOW_SIGNATURE_ATTR) == null;
@@ -115,9 +115,9 @@ public class PsiMethodInsertHandler implements InsertHandler<LookupItem<PsiMetho
}
@NotNull
private static TailType getTailType(final LookupItem item, InsertionContext context) {
private static TailType getTailType(final LookupElement item, InsertionContext context) {
final char completionChar = context.getCompletionChar();
if (completionChar == '!') return item.getTailType();
if (completionChar == '!') return item instanceof LookupItem ? ((LookupItem)item).getTailType() : TailType.NONE;
if (completionChar == '(') {
final Object o = item.getObject();
if (o instanceof PsiMethod) {
@@ -141,8 +141,8 @@ public class PsiMethodInsertHandler implements InsertHandler<LookupItem<PsiMetho
return !(place.getParent() instanceof PsiImportStaticReferenceElement);
}
private static void insertExplicitTypeParams(final LookupItem<PsiMethod> item, final Document document, final int offset, PsiFile file) {
final PsiMethod method = item.getObject();
private static void insertExplicitTypeParams(final LookupElement item, final Document document, final int offset, PsiFile file) {
final PsiMethod method = (PsiMethod)item.getObject();
if (!SmartCompletionDecorator.hasUnboundTypeParams(method)) {
return;
}
+1
View File
@@ -18,6 +18,7 @@
<orderEntry type="module" module-name="compiler-impl" />
<orderEntry type="library" name="asm" level="project" />
<orderEntry type="module" module-name="notNull" />
<orderEntry type="library" name="Groovy" level="project" />
</component>
</module>
@@ -0,0 +1,29 @@
package com.intellij.codeInsight.completion;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
/**
* @author peter
*/
public class GlobalMemberNameCompletionTest extends LightCodeInsightFixtureTestCase {
public void testMethodName() throws Exception {
myFixture.addClass("""
package foo;
public class Foo {
public static int abcmethod() {}
static void methodThatsNotVisible() {}
}
""")
myFixture.configureByText("a.java", "class Bar {{ abcm<caret> }}")
myFixture.complete(CompletionType.CLASS_NAME)
myFixture.type('\n')
myFixture.checkResult """import static foo.Foo.abcmethod;
class Bar {{ abcmethod()<caret> }}"""
}
}
@@ -16,11 +16,12 @@
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
@@ -65,6 +66,11 @@ public class InsertionContext {
return myEditor;
}
@NotNull
public Document getDocument() {
return getEditor().getDocument();
}
public OffsetMap getOffsetMap() {
return myOffsetMap;
}
@@ -305,6 +305,8 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture {
void type(final char c);
void type(final String s);
void performEditorAction(String actionId);
/**
@@ -602,6 +602,13 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
}.execute();
}
@Override
public void type(String s) {
for (int i = 0; i < s.length(); i++) {
type(s.charAt(i));
}
}
public void performEditorAction(final String actionId) {
assertInitialized();
final DataContext dataContext = DataManager.getInstance().getDataContext();
+4 -1
View File
@@ -229,7 +229,8 @@
order="first, before javaMemberName, after xml"/>
<completion.contributor language="JAVA" implementationClass="com.intellij.codeInsight.completion.JavaCompletionContributor" id="javaLegacy"
order="last, before legacy, before default, before javaClassName"/>
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.JavaClassReferenceCompletionContributor" id="javaClassReference"/>
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.JavaClassReferenceCompletionContributor"
id="javaClassReference"/>
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.JavaMethodMergingContributor" id="methodMerger"
order="before javaLegacy, before default"/>
@@ -237,6 +238,8 @@
order="before javaLegacy"/>
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.JavaClassNameCompletionContributor" id="javaClassName"
order="last, before default"/>
<completion.contributor language="JAVA" implementationClass="com.intellij.codeInsight.completion.JavaGlobalMemberNameCompletionContributor"
id="javaGlobalMemberName" order="last, after javaClassName"/>
<completion.contributor language="JAVA" implementationClass="com.intellij.codeInsight.completion.JavaDocCompletionContributor" id="javadoc"
order="last, before javaLegacy"/>