mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
calculate all classes in autopopup background
when completion is case insensitive, show all classes (IDEA-25979)
This commit is contained in:
@@ -16,15 +16,18 @@
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightUtilBase;
|
||||
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiShortNamesCache;
|
||||
import com.intellij.psi.search.searches.AllClassesSearch;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
@@ -146,14 +149,11 @@ public class AllClassesGetter {
|
||||
|
||||
final Set<String> qnames = new THashSet<String>();
|
||||
|
||||
final GlobalSearchScope scope = filterByScope ? context.getContainingFile().getResolveScope() : GlobalSearchScope.allScope(context.getProject());
|
||||
final Project project = context.getProject();
|
||||
final GlobalSearchScope scope = filterByScope ? context.getContainingFile().getResolveScope() : GlobalSearchScope.allScope(project);
|
||||
final boolean pkgContext = JavaCompletionUtil.inSomePackage(context);
|
||||
|
||||
AllClassesSearch.search(scope, context.getProject(), new Condition<String>() {
|
||||
public boolean value(String s) {
|
||||
return prefixMatcher.prefixMatches(s);
|
||||
}
|
||||
}).forEach(new Processor<PsiClass>() {
|
||||
final Processor<PsiClass> classProcessor = new Processor<PsiClass>() {
|
||||
public boolean process(PsiClass psiClass) {
|
||||
assert psiClass != null;
|
||||
if (isSuitable(context, packagePrefix, qnames, psiClass, filterByScope, pkgContext)) {
|
||||
@@ -162,7 +162,31 @@ public class AllClassesGetter {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
PsiShortNamesCache shortNamesCache = JavaPsiFacade.getInstance(project).getShortNamesCache();
|
||||
|
||||
Set<String> words = WordCompletionContributor.getAllWords(context, parameters.getOffset());
|
||||
words.add(prefixMatcher.getPrefix());
|
||||
for (String s : words) {
|
||||
for (PsiClass wordMatch : shortNamesCache.getClassesByName(s, scope)) {
|
||||
classProcessor.process(wordMatch);
|
||||
}
|
||||
}
|
||||
|
||||
final CompletionProgressIndicator indicator = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
|
||||
if (indicator != null) {
|
||||
indicator.delayAllowingFocusedLookup(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
AllClassesSearch.search(scope, project, new Condition<String>() {
|
||||
public boolean value(String s) {
|
||||
return prefixMatcher.prefixMatches(s);
|
||||
}
|
||||
}).forEach(classProcessor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+13
-1
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.TailType;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.ImportClassFix;
|
||||
import com.intellij.codeInsight.hint.ShowParameterInfoHandler;
|
||||
@@ -362,7 +363,18 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
return false;
|
||||
}
|
||||
|
||||
return StringUtil.isCapitalized(result.getPrefixMatcher().getPrefix()) || parameters.isRelaxedMatching();
|
||||
return mayStartClassName(result, parameters.isRelaxedMatching());
|
||||
}
|
||||
|
||||
public static boolean mayStartClassName(CompletionResultSet result, final boolean relaxedMatching) {
|
||||
String prefix = result.getPrefixMatcher().getPrefix();
|
||||
if (StringUtil.isEmpty(prefix)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return StringUtil.isCapitalized(prefix) ||
|
||||
relaxedMatching ||
|
||||
CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE == CodeInsightSettings.NONE;
|
||||
}
|
||||
|
||||
private static void completeAnnotationAttributeName(CompletionResultSet result, PsiElement insertedElement,
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import sun.swing.BakedArrayList;
|
||||
class Foo {
|
||||
{
|
||||
Object element;
|
||||
if (element instanceof bar<caret>)
|
||||
if (element instanceof Bar<caret>)
|
||||
}
|
||||
|
||||
}
|
||||
+13
-6
@@ -34,6 +34,7 @@ import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.extensions.LoadingOrder
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.codeInsight.CodeInsightSettings
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
@@ -637,8 +638,8 @@ public interface Test {
|
||||
public void testTemplateSelectionByComma() {
|
||||
myFixture.configureByText("a.java", """
|
||||
class Foo {
|
||||
int ITER = 2;
|
||||
int itea = 2;
|
||||
int itera = 2;
|
||||
|
||||
{
|
||||
it<caret>
|
||||
@@ -646,9 +647,9 @@ class Foo {
|
||||
}
|
||||
""")
|
||||
type 'e'
|
||||
assertOrderedEquals myFixture.lookupElementStrings, "itea"
|
||||
assertOrderedEquals myFixture.lookupElementStrings, "itea", "itera"
|
||||
type 'r'
|
||||
assertOrderedEquals myFixture.lookupElementStrings, "iter", "ITER", "Iterable", "Iterator"
|
||||
assertOrderedEquals myFixture.lookupElementStrings, "iter", "itera"
|
||||
type ','
|
||||
assert !lookup
|
||||
assert myFixture.editor.document.text.contains('iter,')
|
||||
@@ -670,9 +671,15 @@ class Foo {
|
||||
}
|
||||
|
||||
public void testNewClassParenthesis() {
|
||||
myFixture.configureByText("a.java", """ class Foo { { new <caret> } } """)
|
||||
type 'fil('
|
||||
assert myFixture.editor.document.text.contains('new File()')
|
||||
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.NONE
|
||||
try {
|
||||
myFixture.configureByText("a.java", """ class Foo { { new <caret> } } """)
|
||||
type 'fil('
|
||||
assert myFixture.editor.document.text.contains('new File()')
|
||||
}
|
||||
finally {
|
||||
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.FIRST_LETTER
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnknownMethodParenthesis() {
|
||||
|
||||
+1
-1
@@ -242,7 +242,7 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase {
|
||||
myFixture.addClass("package bar; public class Bar {}");
|
||||
final String path = getTestName(false) + ".java";
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
myFixture.complete(CompletionType.BASIC, 2);
|
||||
myFixture.complete(CompletionType.BASIC);
|
||||
assertPreferredItems(0, "Bar", "Bar");
|
||||
List<LookupElement> items = getLookup().getItems();
|
||||
assertEquals(((JavaPsiClassReferenceElement)items.get(0)).getQualifiedName(), "Bar");
|
||||
|
||||
+8
-2
@@ -300,11 +300,17 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
indicator.duringCompletion(initContext);
|
||||
ProgressManager.checkCanceled();
|
||||
|
||||
data.set(CompletionService.getCompletionService().performCompletion(parameters, new Consumer<CompletionResult>() {
|
||||
final List<LookupElement> items = new ArrayList<LookupElement>();
|
||||
CompletionService.getCompletionService().performCompletion(parameters, new Consumer<CompletionResult>() {
|
||||
public void consume(final CompletionResult result) {
|
||||
indicator.addItem(result);
|
||||
items.add(result.getLookupElement());
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
indicator.processDelayQueue();
|
||||
|
||||
data.set(items.toArray(new LookupElement[items.size()]));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+22
-1
@@ -67,6 +67,7 @@ import javax.swing.*;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
@@ -110,6 +111,8 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
};
|
||||
private volatile int myCount;
|
||||
private final ConcurrentHashMap<LookupElement, CompletionSorterImpl> myItemSorters = new ConcurrentHashMap<LookupElement, CompletionSorterImpl>(TObjectHashingStrategy.IDENTITY);
|
||||
private final LinkedList<Runnable> myDelayQueue = new LinkedList<Runnable>();
|
||||
private volatile boolean myProcessingDelayedActions;
|
||||
|
||||
public CompletionProgressIndicator(final Editor editor, CompletionParameters parameters, CodeCompletionHandlerBase handler, Semaphore freezeSemaphore,
|
||||
final OffsetMap offsetMap, boolean hasModifiers) {
|
||||
@@ -194,6 +197,17 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
}
|
||||
|
||||
public void delayAllowingFocusedLookup(@NotNull Runnable runnable) {
|
||||
myDelayQueue.addLast(runnable);
|
||||
}
|
||||
|
||||
public void processDelayQueue() {
|
||||
myProcessingDelayedActions = true;
|
||||
while (!myDelayQueue.isEmpty()) {
|
||||
myDelayQueue.removeFirst().run();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
CompletionSorterImpl getSorter(LookupElement element) {
|
||||
return myItemSorters.get(element);
|
||||
@@ -314,7 +328,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
if (isOutdated()) return;
|
||||
|
||||
boolean justShown = false;
|
||||
if (!myLookup.isShown() && (!isAutopopupCompletion() || !myLookup.isCalculating())) {
|
||||
if (!myLookup.isShown() && shouldShowLookup()) {
|
||||
if (hideAutopopupIfMeaningless()) {
|
||||
return;
|
||||
}
|
||||
@@ -337,6 +351,13 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldShowLookup() {
|
||||
if (isAutopopupCompletion() && myLookup.isCalculating()) {
|
||||
return myProcessingDelayedActions;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
final boolean isInsideIdentifier() {
|
||||
return getIdentifierEndOffset() != getSelectionEndOffset();
|
||||
}
|
||||
|
||||
+2
@@ -76,6 +76,8 @@ public class WordCompletionContributor extends CompletionContributor implements
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
final PsiFile file = insertedElement.getContainingFile();
|
||||
final CompletionData data = CompletionUtil.getCompletionDataByElement(insertedElement, file);
|
||||
if (data != null && !(data instanceof SyntaxTableCompletionData)) {
|
||||
|
||||
+4
-2
@@ -65,7 +65,9 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
import org.jetbrains.plugins.groovy.refactoring.inline.InlineMethodConflictSolver;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
import static com.intellij.patterns.PsiJavaPatterns.elementType;
|
||||
@@ -294,7 +296,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
GroovySmartCompletionContributor.addExpectedClassMembers(parameters, result);
|
||||
|
||||
if (!PsiJavaPatterns.psiElement().inside(GrImportStatement.class).accepts(position)) {
|
||||
if (StringUtil.isCapitalized(result.getPrefixMatcher().getPrefix()) || parameters.isRelaxedMatching()) {
|
||||
if (JavaCompletionContributor.mayStartClassName(result, parameters.isRelaxedMatching())) {
|
||||
addAllClasses(parameters, result, inheritors);
|
||||
}
|
||||
}
|
||||
|
||||
+20
-7
@@ -15,10 +15,11 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.completion
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings
|
||||
import com.intellij.codeInsight.completion.CompletionAutoPopupTestCase
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import org.jetbrains.plugins.groovy.LightGroovyTestCase
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.plugins.groovy.LightGroovyTestCase
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
@@ -78,9 +79,15 @@ class GroovyAutoPopupTest extends CompletionAutoPopupTestCase {
|
||||
}
|
||||
|
||||
public void testPossibleClosureParameter2() {
|
||||
myFixture.configureByText("a.gpp", "{ a, <caret> }")
|
||||
type 'h'
|
||||
assert !lookup.focused
|
||||
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.NONE
|
||||
try {
|
||||
myFixture.configureByText("a.gpp", "{ a, <caret> }")
|
||||
type 'h'
|
||||
assert !lookup.focused
|
||||
}
|
||||
finally {
|
||||
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.FIRST_LETTER
|
||||
}
|
||||
}
|
||||
|
||||
public void testImpossibleClosureParameter() {
|
||||
@@ -90,9 +97,15 @@ class GroovyAutoPopupTest extends CompletionAutoPopupTestCase {
|
||||
}
|
||||
|
||||
public void testFieldTypeLowercase() {
|
||||
myFixture.configureByText "a.groovy", "class Foo { <caret> }"
|
||||
type 'aioobe'
|
||||
assert myFixture.lookupElementStrings == [ArrayIndexOutOfBoundsException.simpleName]
|
||||
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.NONE
|
||||
try {
|
||||
myFixture.configureByText "a.groovy", "class Foo { <caret> }"
|
||||
type 'aioobe'
|
||||
assert myFixture.lookupElementStrings == [ArrayIndexOutOfBoundsException.simpleName]
|
||||
}
|
||||
finally {
|
||||
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.FIRST_LETTER
|
||||
}
|
||||
}
|
||||
|
||||
public void testNoWordCompletionAutoPopup() {
|
||||
|
||||
Reference in New Issue
Block a user