mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEABKL-6585 Completion: suggest variants for mistyped pattern
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
public class Util {
|
||||
int goo() {
|
||||
retru<caret>
|
||||
}
|
||||
}
|
||||
+1
@@ -139,6 +139,7 @@ public class KeywordCompletionTest extends LightCompletionTestCase {
|
||||
public void testCharInAnnotatedParameter() { doTest(1, "char"); }
|
||||
public void testReturnInTernary() { doTest(1, "return"); }
|
||||
public void testReturnInRussian() { doTest(1, "return"); }
|
||||
public void testReturnWithTypo() { doTest(1, "return"); }
|
||||
public void testFinalAfterParameterAnno() { doTest(2, "final", "float", "class"); }
|
||||
public void testFinalAfterParameterAnno2() { doTest(2, "final", "float", "class"); }
|
||||
public void testFinalAfterCase() { doTest(3, "final", "float", "class"); }
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
PublicInterface i = PublicInterface.createPrivateImplementation();
|
||||
i.getV<caret>x
|
||||
i.getVa<caret>x
|
||||
}
|
||||
}'''
|
||||
|
||||
|
||||
+7
@@ -1907,4 +1907,11 @@ class Abc {
|
||||
myFixture.type('O')
|
||||
myFixture.assertPreferredCompletionItems 0, 'SubOther'
|
||||
}
|
||||
|
||||
void "test correct typos"() {
|
||||
myFixture.configureByText("a.java", "class MyClass { MyCals<caret> }")
|
||||
myFixture.completeBasic()
|
||||
myFixture.type('\n')
|
||||
myFixture.checkResult("class MyClass { MyClass<caret> }")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ public abstract class CompletionResultSet implements Consumer<LookupElement> {
|
||||
if (stop) {
|
||||
stopHere();
|
||||
}
|
||||
myCompletionService.getVariantsFromContributors(parameters, myContributor, new BatchConsumer<CompletionResult>() {
|
||||
myCompletionService.getVariantsFromContributors(parameters, myContributor, getPrefixMatcher(), new BatchConsumer<CompletionResult>() {
|
||||
@Override
|
||||
public void startBatch() {
|
||||
CompletionResultSet.this.startBatch();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
@@ -13,6 +14,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* For completion FAQ, see {@link CompletionContributor}.
|
||||
@@ -45,13 +47,19 @@ public abstract class CompletionService {
|
||||
public void getVariantsFromContributors(final CompletionParameters parameters,
|
||||
@Nullable final CompletionContributor from,
|
||||
final Consumer<CompletionResult> consumer) {
|
||||
getVariantsFromContributors(parameters, from, createMatcher(suggestPrefix(parameters), false), consumer);
|
||||
}
|
||||
|
||||
protected void getVariantsFromContributors(CompletionParameters parameters,
|
||||
@Nullable CompletionContributor from,
|
||||
PrefixMatcher matcher, Consumer<CompletionResult> consumer) {
|
||||
final List<CompletionContributor> contributors = CompletionContributor.forParameters(parameters);
|
||||
|
||||
for (int i = contributors.indexOf(from) + 1; i < contributors.size(); i++) {
|
||||
ProgressManager.checkCanceled();
|
||||
CompletionContributor contributor = contributors.get(i);
|
||||
|
||||
CompletionResultSet result = createResultSet(parameters, consumer, contributor);
|
||||
CompletionResultSet result = createResultSet(parameters, consumer, contributor, matcher);
|
||||
contributor.fillCompletionVariants(parameters, result);
|
||||
if (result.isStopped()) {
|
||||
return;
|
||||
@@ -60,7 +68,13 @@ public abstract class CompletionService {
|
||||
}
|
||||
|
||||
protected abstract CompletionResultSet createResultSet(CompletionParameters parameters, Consumer<CompletionResult> consumer,
|
||||
@NotNull CompletionContributor contributor);
|
||||
@NotNull CompletionContributor contributor, PrefixMatcher matcher);
|
||||
|
||||
protected abstract String suggestPrefix(CompletionParameters parameters);
|
||||
|
||||
@NotNull
|
||||
protected abstract PrefixMatcher createMatcher(String prefix, boolean typoTolerant);
|
||||
|
||||
|
||||
@Nullable
|
||||
public abstract CompletionProcess getCurrentCompletion();
|
||||
@@ -74,7 +88,9 @@ public abstract class CompletionService {
|
||||
public void performCompletion(CompletionParameters parameters, Consumer<? super CompletionResult> consumer) {
|
||||
final Set<LookupElement> lookupSet = ContainerUtil.newConcurrentSet();
|
||||
|
||||
getVariantsFromContributors(parameters, null, new BatchConsumer<CompletionResult>() {
|
||||
AtomicBoolean typoTolerant = new AtomicBoolean();
|
||||
|
||||
BatchConsumer<CompletionResult> batchConsumer = new BatchConsumer<CompletionResult>() {
|
||||
@Override
|
||||
public void startBatch() {
|
||||
if (consumer instanceof BatchConsumer) {
|
||||
@@ -91,11 +107,20 @@ public abstract class CompletionService {
|
||||
|
||||
@Override
|
||||
public void consume(CompletionResult result) {
|
||||
if (typoTolerant.get() && result.getLookupElement().getAutoCompletionPolicy() != AutoCompletionPolicy.NEVER_AUTOCOMPLETE) {
|
||||
result = result.withLookupElement(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(result.getLookupElement()));
|
||||
}
|
||||
if (lookupSet.add(result.getLookupElement())) {
|
||||
consumer.consume(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
String prefix = suggestPrefix(parameters);
|
||||
getVariantsFromContributors(parameters, null, createMatcher(prefix, false), batchConsumer);
|
||||
if (lookupSet.isEmpty() && prefix.length() > 2) {
|
||||
typoTolerant.set(true);
|
||||
getVariantsFromContributors(parameters, null, createMatcher(prefix, true), batchConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract CompletionSorter defaultSorter(CompletionParameters parameters, PrefixMatcher matcher);
|
||||
|
||||
+23
-11
@@ -26,6 +26,7 @@ public class CamelHumpMatcher extends PrefixMatcher {
|
||||
private final MinusculeMatcher myCaseInsensitiveMatcher;
|
||||
private final boolean myCaseSensitive;
|
||||
private static boolean ourForceStartMatching;
|
||||
private final boolean myTypoTolerant;
|
||||
|
||||
|
||||
public CamelHumpMatcher(@NotNull final String prefix) {
|
||||
@@ -33,8 +34,13 @@ public class CamelHumpMatcher extends PrefixMatcher {
|
||||
}
|
||||
|
||||
public CamelHumpMatcher(String prefix, boolean caseSensitive) {
|
||||
this(prefix, caseSensitive, false);
|
||||
}
|
||||
|
||||
CamelHumpMatcher(String prefix, boolean caseSensitive, boolean typoTolerant) {
|
||||
super(prefix);
|
||||
myCaseSensitive = caseSensitive;
|
||||
myTypoTolerant = typoTolerant;
|
||||
myMatcher = createMatcher(myCaseSensitive);
|
||||
myCaseInsensitiveMatcher = createMatcher(false);
|
||||
}
|
||||
@@ -57,6 +63,10 @@ public class CamelHumpMatcher extends PrefixMatcher {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isTypoTolerant() {
|
||||
return myTypoTolerant;
|
||||
}
|
||||
|
||||
private static int skipUnderscores(@NotNull String name) {
|
||||
return CharArrayUtil.shiftForward(name, 0, "_");
|
||||
}
|
||||
@@ -110,24 +120,26 @@ public class CamelHumpMatcher extends PrefixMatcher {
|
||||
return this;
|
||||
}
|
||||
|
||||
return new CamelHumpMatcher(prefix, myCaseSensitive);
|
||||
return new CamelHumpMatcher(prefix, myCaseSensitive, myTypoTolerant);
|
||||
}
|
||||
|
||||
private MinusculeMatcher createMatcher(final boolean caseSensitive) {
|
||||
String prefix = applyMiddleMatching(myPrefix);
|
||||
|
||||
if (!caseSensitive) {
|
||||
return NameUtil.buildMatcher(prefix, NameUtil.MatchingCaseSensitivity.NONE);
|
||||
NameUtil.MatcherBuilder builder = NameUtil.buildMatcher(prefix);
|
||||
if (caseSensitive) {
|
||||
int setting = CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE;
|
||||
if (setting == CodeInsightSettings.FIRST_LETTER) {
|
||||
builder = builder.withCaseSensitivity(NameUtil.MatchingCaseSensitivity.FIRST_LETTER);
|
||||
}
|
||||
else if (setting == CodeInsightSettings.ALL) {
|
||||
builder = builder.withCaseSensitivity(NameUtil.MatchingCaseSensitivity.ALL);
|
||||
}
|
||||
}
|
||||
|
||||
switch (CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE) {
|
||||
case CodeInsightSettings.NONE:
|
||||
return NameUtil.buildMatcher(prefix, NameUtil.MatchingCaseSensitivity.NONE);
|
||||
case CodeInsightSettings.FIRST_LETTER:
|
||||
return NameUtil.buildMatcher(prefix, NameUtil.MatchingCaseSensitivity.FIRST_LETTER);
|
||||
default:
|
||||
return NameUtil.buildMatcher(prefix, NameUtil.MatchingCaseSensitivity.ALL);
|
||||
if (myTypoTolerant) {
|
||||
builder = builder.typoTolerant();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static String applyMiddleMatching(String prefix) {
|
||||
|
||||
+22
-7
@@ -74,17 +74,30 @@ public final class CompletionServiceImpl extends CompletionService {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompletionResultSet createResultSet(CompletionParameters parameters, Consumer<CompletionResult> consumer,
|
||||
@NotNull CompletionContributor contributor) {
|
||||
protected String suggestPrefix(CompletionParameters parameters) {
|
||||
final PsiElement position = parameters.getPosition();
|
||||
final int offset = parameters.getOffset();
|
||||
TextRange range = position.getTextRange();
|
||||
assert range.containsOffset(offset) : position + "; " + offset + " not in " + range;
|
||||
//noinspection deprecation
|
||||
final String prefix = CompletionData.findPrefixStatic(position, offset);
|
||||
CamelHumpMatcher matcher = new CamelHumpMatcher(prefix);
|
||||
CompletionSorterImpl sorter = defaultSorter(parameters, matcher);
|
||||
return new CompletionResultSetImpl(consumer, matcher, contributor, parameters, sorter, null);
|
||||
return CompletionData.findPrefixStatic(position, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected PrefixMatcher createMatcher(String prefix, boolean typoTolerant) {
|
||||
return createMatcher(prefix, true, typoTolerant);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static CamelHumpMatcher createMatcher(String prefix, boolean caseSensitive, boolean typoTolerant) {
|
||||
return new CamelHumpMatcher(prefix, caseSensitive, typoTolerant);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompletionResultSet createResultSet(CompletionParameters parameters, Consumer<CompletionResult> consumer,
|
||||
@NotNull CompletionContributor contributor, PrefixMatcher matcher) {
|
||||
return new CompletionResultSetImpl(consumer, matcher, contributor, parameters, defaultSorter(parameters, matcher), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,7 +191,9 @@ public final class CompletionServiceImpl extends CompletionService {
|
||||
@NotNull
|
||||
@Override
|
||||
public CompletionResultSet caseInsensitive() {
|
||||
return withPrefixMatcher(new CamelHumpMatcher(getPrefixMatcher().getPrefix(), false));
|
||||
PrefixMatcher matcher = getPrefixMatcher();
|
||||
boolean typoTolerant = matcher instanceof CamelHumpMatcher && ((CamelHumpMatcher)matcher).isTypoTolerant();
|
||||
return withPrefixMatcher(createMatcher(matcher.getPrefix(), false, typoTolerant));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -404,6 +404,7 @@ public class NameUtil {
|
||||
private final String pattern;
|
||||
private String separators = "";
|
||||
private MatchingCaseSensitivity caseSensitivity = MatchingCaseSensitivity.NONE;
|
||||
private boolean typoTolerant = Registry.is("ide.completion.typo.tolerance");
|
||||
|
||||
public MatcherBuilder(String pattern) {
|
||||
this.pattern = pattern;
|
||||
@@ -419,9 +420,14 @@ public class NameUtil {
|
||||
return this;
|
||||
}
|
||||
|
||||
public MatcherBuilder typoTolerant() {
|
||||
this.typoTolerant = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MinusculeMatcher build() {
|
||||
return Registry.is("ide.completion.typo.tolerance") ? FixingLayoutTypoTolerantMatcher.create(pattern, caseSensitivity, separators)
|
||||
: new FixingLayoutMatcher(pattern, caseSensitivity, separators);
|
||||
return typoTolerant ? FixingLayoutTypoTolerantMatcher.create(pattern, caseSensitivity, separators)
|
||||
: new FixingLayoutMatcher(pattern, caseSensitivity, separators);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user