java/groovy completion: load more class name variants when prefix is changed (IDEA-168079)

This commit is contained in:
peter
2017-02-16 18:46:53 +01:00
parent 848bcd5367
commit daa8dd3eee
5 changed files with 118 additions and 23 deletions
@@ -65,8 +65,8 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
result.runRemainingContributors(parameters, tracker);
final boolean empty = tracker.containsOnlyPackages || suggestAllAnnotations(parameters);
if (!empty && parameters.getInvocationCount() == 0) {
result.restartCompletionWhenNothingMatches();
if (JavaCompletionContributor.isClassNamePossible(parameters) && !JavaCompletionContributor.mayStartClassName(result)) {
result.restartCompletionOnAnyPrefixChange();
}
if (empty) {
@@ -207,7 +207,7 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
public ResultTracker(CompletionResultSet result) {
myResult = result;
betterMatcher = new BetterPrefixMatcher(result);
betterMatcher = new BetterPrefixMatcher.AutoRestarting(result);
}
@Override
@@ -1805,4 +1805,32 @@ ita<caret>
assert lookup
assert myFixture.lookupElementStrings == ['itar']
}
void "test expand class list when typing more or moving caret"() {
myFixture.addClass 'package foo; public class KimeFamilyRange {}'
myFixture.addClass 'package foo; public class FamiliesRangesMetaData {}'
myFixture.addClass 'public class KSomethingInCurrentPackage {}'
myFixture.configureByText 'a.java', 'class Foo { <caret> }'
type 'F'
assert !myFixture.lookupElementStrings.contains('KimeFamilyRange')
type 'aRa'
myFixture.assertPreferredCompletionItems 0, 'FamiliesRangesMetaData', 'KimeFamilyRange'
4.times {
edt { myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT) }
joinCompletion()
}
assert !myFixture.lookupElementStrings.contains('KimeFamilyRange')
type 'K'
4.times {
edt { myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT) }
joinCompletion()
}
myFixture.assertPreferredCompletionItems 0, 'KimeFamilyRange'
}
}
@@ -39,32 +39,43 @@ public class BetterPrefixMatcher extends PrefixMatcher {
myMinMatchingDegree = minMatchingDegree;
}
public BetterPrefixMatcher(CompletionResultSet set) {
this(set.getPrefixMatcher(), Integer.MIN_VALUE);
}
@NotNull
public BetterPrefixMatcher improve(CompletionResult result) {
int degree = RealPrefixMatchingWeigher.getBestMatchingDegree(result.getLookupElement(), result.getPrefixMatcher());
if (degree <= myMinMatchingDegree) return this;
return new BetterPrefixMatcher(myOriginal, degree);
return createCopy(myOriginal, degree);
}
@NotNull
protected BetterPrefixMatcher createCopy(PrefixMatcher original, int degree) {
return new BetterPrefixMatcher(original, degree);
}
@Override
public boolean prefixMatches(@NotNull String name) {
if (myHumpMatcher != null) {
FList<TextRange> fragments = myHumpMatcher.matchingFragments(name);
if (fragments == null || !MinusculeMatcher.isStartMatch(fragments)) {
return false;
}
return myHumpMatcher.matchingDegree(name, fragments) >= myMinMatchingDegree;
}
return prefixMatchesEx(name) == MatchingOutcome.BETTER_MATCH;
}
if (!myOriginal.prefixMatches(name) || !myOriginal.isStartMatch(name)) {
return false;
}
return myOriginal.matchingDegree(name) >= myMinMatchingDegree;
protected MatchingOutcome prefixMatchesEx(String name) {
return myHumpMatcher != null ? matchOptimized(name, myHumpMatcher) : matchGeneric(name);
}
private MatchingOutcome matchGeneric(String name) {
if (!myOriginal.prefixMatches(name)) return MatchingOutcome.NON_MATCH;
if (!myOriginal.isStartMatch(name)) return MatchingOutcome.WORSE_MATCH;
return myOriginal.matchingDegree(name) >= myMinMatchingDegree ? MatchingOutcome.BETTER_MATCH : MatchingOutcome.WORSE_MATCH;
}
private MatchingOutcome matchOptimized(String name, CamelHumpMatcher matcher) {
FList<TextRange> fragments = matcher.matchingFragments(name);
if (fragments == null) return MatchingOutcome.NON_MATCH;
if (!MinusculeMatcher.isStartMatch(fragments)) return MatchingOutcome.WORSE_MATCH;
return matcher.matchingDegree(name, fragments) >= myMinMatchingDegree ? MatchingOutcome.BETTER_MATCH : MatchingOutcome.WORSE_MATCH;
}
protected enum MatchingOutcome {
NON_MATCH, WORSE_MATCH, BETTER_MATCH
}
@Override
@@ -80,6 +91,34 @@ public class BetterPrefixMatcher extends PrefixMatcher {
@NotNull
@Override
public PrefixMatcher cloneWithPrefix(@NotNull String prefix) {
return new BetterPrefixMatcher(myOriginal.cloneWithPrefix(prefix), myMinMatchingDegree);
return createCopy(myOriginal.cloneWithPrefix(prefix), myMinMatchingDegree);
}
public static class AutoRestarting extends BetterPrefixMatcher {
private final CompletionResultSet myResult;
public AutoRestarting(@NotNull CompletionResultSet result) {
this(result, result.getPrefixMatcher(), Integer.MIN_VALUE);
}
private AutoRestarting(CompletionResultSet result, PrefixMatcher original, int minMatchingDegree) {
super(original, minMatchingDegree);
myResult = result;
}
@NotNull
@Override
protected BetterPrefixMatcher createCopy(PrefixMatcher original, int degree) {
return new AutoRestarting(myResult, original, degree);
}
@Override
protected MatchingOutcome prefixMatchesEx(String name) {
MatchingOutcome outcome = super.prefixMatchesEx(name);
if (outcome == MatchingOutcome.WORSE_MATCH) {
myResult.restartCompletionOnAnyPrefixChange();
}
return outcome;
}
}
}
@@ -52,8 +52,8 @@ public class GroovyNoVariantsDelegator extends CompletionContributor {
result.runRemainingContributors(parameters, tracker);
final boolean empty = tracker.containsOnlyPackages || suggestAnnotations(parameters);
if (!empty && parameters.getInvocationCount() == 0) {
result.restartCompletionWhenNothingMatches();
if (GrMainCompletionProvider.isClassNamePossible(parameters.getPosition()) && !JavaCompletionContributor.mayStartClassName(result)) {
result.restartCompletionOnAnyPrefixChange();
}
if (empty) {
@@ -248,5 +248,33 @@ foo(new <caret>)
assert !lookup
}
void "test expand class list when typing more or moving caret"() {
myFixture.addClass 'package foo; public class KimeFamilyRange {}'
myFixture.addClass 'package foo; public class FamiliesRangesMetaData {}'
myFixture.addClass 'public class KSomethingInCurrentPackage {}'
myFixture.configureByText 'a.groovy', '<caret>'
type 'F'
assert !myFixture.lookupElementStrings.contains('KimeFamilyRange')
type 'aRa'
myFixture.assertPreferredCompletionItems 0, 'FamiliesRangesMetaData', 'KimeFamilyRange'
4.times {
edt { myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT) }
myTester.joinCompletion()
}
assert !myFixture.lookupElementStrings.contains('KimeFamilyRange')
type 'K'
4.times {
edt { myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT) }
myTester.joinCompletion()
}
myFixture.assertPreferredCompletionItems 0, 'KimeFamilyRange'
}
}