calculate all classes in autopopup background

when completion is case insensitive, show all classes (IDEA-25979)
This commit is contained in:
peter
2011-07-05 19:35:45 +02:00
parent 579d911b60
commit 4eb2b1cfe6
10 changed files with 115 additions and 28 deletions
@@ -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);
}
});
}
}
@@ -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,
@@ -3,7 +3,7 @@ import sun.swing.BakedArrayList;
class Foo {
{
Object element;
if (element instanceof bar<caret>)
if (element instanceof Bar<caret>)
}
}
@@ -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() {
@@ -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");
@@ -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()]));
}
});
}
@@ -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();
}
@@ -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)) {
@@ -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);
}
}
@@ -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() {