mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
autopopup with all class names when nothing imported is found
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class ClassByNameMerger implements Consumer<LookupElement> {
|
||||
private int number = 0;
|
||||
private LookupElement lastElement;
|
||||
private final boolean myShouldMerge;
|
||||
private final CompletionResultSet myResult;
|
||||
|
||||
public ClassByNameMerger(boolean shouldMerge, CompletionResultSet result) {
|
||||
myShouldMerge = shouldMerge;
|
||||
myResult = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
if (!myShouldMerge) {
|
||||
myResult.addElement(element);
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastElement != null) {
|
||||
if (lastElement.getLookupString().equals(element.getLookupString())) {
|
||||
number++;
|
||||
lastElement = LookupElementBuilder.create(element.getLookupString()).setTailText(" (" + number + " variants...)", true);
|
||||
return;
|
||||
}
|
||||
|
||||
myResult.addElement(lastElement);
|
||||
}
|
||||
lastElement = element;
|
||||
number = 1;
|
||||
}
|
||||
|
||||
public void finishedClassProcessing() {
|
||||
if (lastElement != null) {
|
||||
myResult.addElement(lastElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-2
@@ -36,11 +36,17 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
|
||||
};
|
||||
result.runRemainingContributors(parameters, passResult);
|
||||
|
||||
if (!empty.get() && parameters.getInvocationCount() == 0) {
|
||||
result.restartCompletionWhenNothingMatches();
|
||||
}
|
||||
|
||||
if (empty.get()) {
|
||||
if (parameters.getCompletionType() == CompletionType.BASIC &&
|
||||
parameters.getInvocationCount() == 1 &&
|
||||
parameters.getInvocationCount() <= 1 &&
|
||||
JavaCompletionContributor.mayStartClassName(result, false) &&
|
||||
JavaCompletionContributor.isClassNamePossible(parameters.getPosition())) {
|
||||
final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result);
|
||||
|
||||
JavaClassNameCompletionContributor.addAllClasses(parameters, JavaCompletionSorting.addJavaSorting(parameters, result),
|
||||
true, new Consumer<LookupElement>() {
|
||||
@Override
|
||||
@@ -49,9 +55,13 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
|
||||
if (classElement != null) {
|
||||
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
|
||||
}
|
||||
result.addElement(element);
|
||||
|
||||
merger.consume(classElement);
|
||||
}
|
||||
});
|
||||
|
||||
merger.finishedClassProcessing();
|
||||
|
||||
} else if (parameters.getCompletionType() == CompletionType.SMART && parameters.getInvocationCount() == 2) {
|
||||
result.runRemainingContributors(parameters.withInvocationCount(3), passResult);
|
||||
}
|
||||
|
||||
@@ -1095,5 +1095,20 @@ class Foo {{
|
||||
assert end == myFixture.editor.caretModel.logicalPosition
|
||||
}
|
||||
|
||||
public void testNonImportedClass() {
|
||||
myFixture.addClass("package foo; public class Abcdefg {}")
|
||||
myFixture.configureByText 'a.java', 'class Foo extends <caret>'
|
||||
type 'Abcde '
|
||||
myFixture.checkResult 'import foo.Abcdefg;\n\nclass Foo extends Abcdefg <caret>'
|
||||
}
|
||||
|
||||
public void testTwoNonImportedClasses() {
|
||||
myFixture.addClass("package foo; public class Abcdefg {}")
|
||||
myFixture.addClass("package bar; public class Abcdefg {}")
|
||||
myFixture.configureByText 'a.java', 'class Foo extends <caret>'
|
||||
type 'Abcde '
|
||||
myFixture.checkResult 'class Foo extends Abcdefg <caret>'
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -99,4 +99,6 @@ public abstract class CompletionResultSet {
|
||||
}
|
||||
|
||||
public abstract void restartCompletionOnPrefixChange(ElementPattern<String> prefixCondition);
|
||||
|
||||
public abstract void restartCompletionWhenNothingMatches();
|
||||
}
|
||||
|
||||
+4
-2
@@ -501,7 +501,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
|
||||
private boolean hideAutopopupIfMeaningless() {
|
||||
if (isAutopopupCompletion() && !myLookup.isSelectionTouched() && !myLookup.isCalculating()) {
|
||||
if (!myLookup.isLookupDisposed() && isAutopopupCompletion() && !myLookup.isSelectionTouched() && !myLookup.isCalculating()) {
|
||||
myLookup.refreshUi(true);
|
||||
final List<LookupElement> items = myLookup.getItems();
|
||||
|
||||
@@ -618,7 +618,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
final CompletionProgressIndicator current = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
|
||||
LOG.assertTrue(this == current, current + "!=" + this);
|
||||
|
||||
if (isAutopopupCompletion() && (myLookup.isLookupDisposed() || !myLookup.isShown() || hideAutopopupIfMeaningless())) {
|
||||
if (isAutopopupCompletion() && !myLookup.isShown()) {
|
||||
if (CompletionServiceImpl.getCompletionService().getCurrentCompletion() == this) {
|
||||
closeAndFinish(true);
|
||||
}
|
||||
@@ -627,6 +627,8 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
return;
|
||||
}
|
||||
|
||||
hideAutopopupIfMeaningless();
|
||||
|
||||
final CompletionPhase.CommittingDocuments phase = new CompletionPhase.CommittingDocuments(this, myEditor);
|
||||
CompletionServiceImpl.setCompletionPhase(phase);
|
||||
|
||||
|
||||
+8
@@ -181,6 +181,14 @@ public class CompletionServiceImpl extends CompletionService{
|
||||
indicator.addWatchedPrefix(myTextBeforePosition.length() - getPrefixMatcher().getPrefix().length(), prefixCondition);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restartCompletionWhenNothingMatches() {
|
||||
final CompletionProgressIndicator indicator = getCompletionService().getCurrentCompletion();
|
||||
if (indicator != null) {
|
||||
indicator.getLookup().setStartCompletionWhenNothingMatches(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean assertPhase(Class<? extends CompletionPhase>... possibilities) {
|
||||
|
||||
@@ -84,7 +84,12 @@ public class LookupTypedHandler extends TypedHandlerDelegate {
|
||||
});
|
||||
lookup.appendPrefix(charTyped);
|
||||
if (lookup.isStartCompletionWhenNothingMatches() && lookup.getItems().isEmpty()) {
|
||||
AutoPopupController.getInstance(editor.getProject()).scheduleAutoPopup(editor, null);
|
||||
final CompletionProgressIndicator completion = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
|
||||
if (completion != null) {
|
||||
completion.scheduleRestart();
|
||||
} else {
|
||||
AutoPopupController.getInstance(editor.getProject()).scheduleAutoPopup(editor, null);
|
||||
}
|
||||
}
|
||||
|
||||
AutoHardWrapHandler.getInstance().wrapLineIfNecessary(editor, DataManager.getInstance().getDataContext(editor.getContentComponent()), modificationStamp);
|
||||
|
||||
@@ -235,6 +235,7 @@
|
||||
implementationClass="org.jetbrains.plugins.groovy.codeInsight.GroovyLineMarkerProvider"/>
|
||||
<codeInsight.gotoSuper language="Groovy" implementationClass="org.jetbrains.plugins.groovy.codeInsight.navigation.actions.GroovyGotoSuperHandler"/>
|
||||
<lookup.charFilter implementation="org.jetbrains.plugins.groovy.lang.completion.GroovyReferenceCharFilter"/>
|
||||
<completion.contributor language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.completion.GroovyNoVariantsDelegator" id="groovyBasic2ClassName" order="first"/>
|
||||
<completion.contributor language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionContributor" id="groovyBasic"/>
|
||||
<completion.contributor language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.completion.GroovySmartCompletionContributor"/>
|
||||
<completion.contributor language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.completion.GrMethodMergingContributor"
|
||||
|
||||
+17
-3
@@ -174,13 +174,22 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
|
||||
|
||||
private static void addAllClasses(CompletionParameters parameters, final CompletionResultSet result, final InheritorsHolder inheritors) {
|
||||
addAllClasses(parameters, result, new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
result.addElement(element);
|
||||
}
|
||||
}, inheritors);
|
||||
}
|
||||
|
||||
public static void addAllClasses(CompletionParameters parameters, CompletionResultSet result, final Consumer<LookupElement> consumer, final InheritorsHolder inheritors) {
|
||||
final PsiElement position = parameters.getPosition();
|
||||
final ElementFilter filter = getClassFilter(position);
|
||||
AllClassesGetter.processJavaClasses(parameters, result.getPrefixMatcher(), parameters.getInvocationCount() <= 1, new Consumer<PsiClass>() {
|
||||
@Override
|
||||
public void consume(PsiClass psiClass) {
|
||||
if (!inheritors.alreadyProcessed(psiClass) && filter.isAcceptable(psiClass, position)) {
|
||||
result.addElement(GroovyCompletionUtil.createClassLookupItem(psiClass));
|
||||
consumer.consume(GroovyCompletionUtil.createClassLookupItem(psiClass));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -311,8 +320,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
if (reference.getQualifier() == null) {
|
||||
GroovySmartCompletionContributor.addExpectedClassMembers(parameters, result);
|
||||
|
||||
if (!PsiJavaPatterns.psiElement().inside(GrImportStatement.class).accepts(position) &&
|
||||
JavaCompletionContributor.mayStartClassName(result, parameters.isRelaxedMatching())) {
|
||||
if (isClassNamePossible(position) && JavaCompletionContributor.mayStartClassName(result, parameters.isRelaxedMatching())) {
|
||||
if (JavaCompletionContributor.mayShowAllClasses(parameters)) {
|
||||
addAllClasses(parameters, result, inheritors);
|
||||
} else {
|
||||
@@ -350,6 +358,12 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
|
||||
}
|
||||
|
||||
public static boolean isClassNamePossible(PsiElement position) {
|
||||
PsiElement parent = position.getParent();
|
||||
return parent instanceof GrReferenceElement && ((GrReferenceElement)parent).getQualifier() == null &&
|
||||
!PsiJavaPatterns.psiElement().inside(GrImportStatement.class).accepts(position);
|
||||
}
|
||||
|
||||
private static void addUnfinishedMethodTypeParameters(PsiElement position, CompletionResultSet result) {
|
||||
final ProcessingContext context = new ProcessingContext();
|
||||
if (PsiJavaPatterns.psiElement().inside(
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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 org.jetbrains.plugins.groovy.lang.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class GroovyNoVariantsDelegator extends CompletionContributor {
|
||||
|
||||
@Override
|
||||
public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
|
||||
final Ref<Boolean> empty = Ref.create(true);
|
||||
Consumer<CompletionResult> passResult = new Consumer<CompletionResult>() {
|
||||
public void consume(final CompletionResult lookupElement) {
|
||||
empty.set(false);
|
||||
result.passResult(lookupElement);
|
||||
}
|
||||
};
|
||||
result.runRemainingContributors(parameters, passResult);
|
||||
|
||||
if (!empty.get() && parameters.getInvocationCount() == 0) {
|
||||
result.restartCompletionWhenNothingMatches();
|
||||
}
|
||||
|
||||
if (empty.get()) {
|
||||
if (parameters.getCompletionType() == CompletionType.BASIC &&
|
||||
parameters.getInvocationCount() <= 1 &&
|
||||
JavaCompletionContributor.mayStartClassName(result, false) &&
|
||||
GroovyCompletionContributor.isClassNamePossible(parameters.getPosition())) {
|
||||
final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result);
|
||||
|
||||
GroovyCompletionContributor.addAllClasses(parameters, result,
|
||||
new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
JavaPsiClassReferenceElement classElement = element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
|
||||
if (classElement != null) {
|
||||
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
|
||||
}
|
||||
merger.consume(classElement);
|
||||
}
|
||||
}, new InheritorsHolder(parameters.getPosition(), result));
|
||||
|
||||
merger.finishedClassProcessing();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+16
@@ -197,4 +197,20 @@ class GroovyAutoPopupTest extends CompletionAutoPopupTestCase {
|
||||
type ' in c'
|
||||
assert lookup.focused
|
||||
}
|
||||
|
||||
public void testNonImportedClass() {
|
||||
myFixture.addClass("package foo; public class Abcdefg {}")
|
||||
myFixture.configureByText 'a.groovy', '<caret>'
|
||||
type 'Abcde '
|
||||
myFixture.checkResult 'import foo.Abcdefg\n\nAbcdefg <caret>'
|
||||
}
|
||||
|
||||
public void testTwoNonImportedClasses() {
|
||||
myFixture.addClass("package foo; public class Abcdefg {}")
|
||||
myFixture.addClass("package bar; public class Abcdefg {}")
|
||||
myFixture.configureByText 'a.groovy', '<caret>'
|
||||
type 'Abcde '
|
||||
myFixture.checkResult 'Abcdefg <caret>'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user