mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 09:19:13 +07:00
java global member name completion initial (IDEA-54855)
This commit is contained in:
+113
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
+29
@@ -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;
|
||||
}
|
||||
|
||||
+2
@@ -305,6 +305,8 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture {
|
||||
|
||||
void type(final char c);
|
||||
|
||||
void type(final String s);
|
||||
|
||||
void performEditorAction(String actionId);
|
||||
|
||||
/**
|
||||
|
||||
+7
@@ -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();
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
Reference in New Issue
Block a user