mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-229306 (IDEA-CR-56836) Goto Class should prefer start matches
GitOrigin-RevId: 4481c7ac60053834905010e7d0ac69f495a0629d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
259ad973f4
commit
ee23cde7a8
@@ -296,6 +296,7 @@ public final class NameUtil {
|
||||
private String separators = "";
|
||||
private MatchingCaseSensitivity caseSensitivity = MatchingCaseSensitivity.NONE;
|
||||
private boolean typoTolerant = Registry.is("ide.completion.typo.tolerance");
|
||||
private boolean preferStartMatches = false;
|
||||
|
||||
public MatcherBuilder(String pattern) {
|
||||
this.pattern = pattern;
|
||||
@@ -316,9 +317,15 @@ public final class NameUtil {
|
||||
return this;
|
||||
}
|
||||
|
||||
public MatcherBuilder preferringStartMatches() {
|
||||
preferStartMatches = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MinusculeMatcher build() {
|
||||
return typoTolerant ? FixingLayoutTypoTolerantMatcher.create(pattern, caseSensitivity, separators)
|
||||
: new FixingLayoutMatcher(pattern, caseSensitivity, separators);
|
||||
MinusculeMatcher matcher = typoTolerant ? FixingLayoutTypoTolerantMatcher.create(pattern, caseSensitivity, separators)
|
||||
: new FixingLayoutMatcher(pattern, caseSensitivity, separators);
|
||||
return preferStartMatches ? new PreferStartMatchMatcherWrapper(matcher) : matcher;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// Copyright 2000-2019 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.psi.codeStyle;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.util.containers.FList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PreferStartMatchMatcherWrapper extends MinusculeMatcher {
|
||||
public static final int START_MATCH_WEIGHT = 10000;
|
||||
@NotNull
|
||||
private final MinusculeMatcher myDelegateMatcher;
|
||||
|
||||
public PreferStartMatchMatcherWrapper(@NotNull MinusculeMatcher matcher) {
|
||||
myDelegateMatcher = matcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getPattern() {
|
||||
return myDelegateMatcher.getPattern();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FList<TextRange> matchingFragments(@NotNull String name) {
|
||||
return myDelegateMatcher.matchingFragments(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int matchingDegree(@NotNull String name,
|
||||
boolean valueStartCaseMatch,
|
||||
@Nullable FList<? extends TextRange> fragments) {
|
||||
int degree = myDelegateMatcher.matchingDegree(name, valueStartCaseMatch, fragments);
|
||||
if (fragments == null || fragments.isEmpty()) return degree;
|
||||
|
||||
if (fragments.getHead().getStartOffset() == 0) degree += START_MATCH_WEIGHT;
|
||||
return degree;
|
||||
}
|
||||
}
|
||||
@@ -144,7 +144,12 @@ public class GotoFileItemProvider extends DefaultChooseByNameItemProvider {
|
||||
|
||||
@NotNull
|
||||
public static MinusculeMatcher getQualifiedNameMatcher(@NotNull String pattern) {
|
||||
return NameUtil.buildMatcher("*" + StringUtil.replace(StringUtil.replace(pattern, "\\", "*\\*"), "/", "*/*"), NameUtil.MatchingCaseSensitivity.NONE);
|
||||
pattern = "*" + StringUtil.replace(StringUtil.replace(pattern, "\\", "*\\*"), "/", "*/*");
|
||||
|
||||
return NameUtil.buildMatcher(pattern)
|
||||
.withCaseSensitivity(NameUtil.MatchingCaseSensitivity.NONE)
|
||||
.preferringStartMatches()
|
||||
.build();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -318,7 +323,15 @@ public class GotoFileItemProvider extends DefaultChooseByNameItemProvider {
|
||||
|
||||
SuffixMatches(@NotNull String pattern, int from, @NotNull ProgressIndicator indicator) {
|
||||
patternSuffix = pattern.substring(from);
|
||||
matcher = NameUtil.buildMatcher((from > 0 ? " " : "*") + patternSuffix, NameUtil.MatchingCaseSensitivity.NONE);
|
||||
boolean preferStartMatches = from == 0 && !patternSuffix.startsWith("*");
|
||||
String matchPattern = (from > 0 ? " " : "*") + patternSuffix;
|
||||
|
||||
NameUtil.MatcherBuilder builder = NameUtil.buildMatcher(matchPattern).withCaseSensitivity(NameUtil.MatchingCaseSensitivity.NONE);
|
||||
if (preferStartMatches) {
|
||||
builder.preferringStartMatches();
|
||||
}
|
||||
|
||||
this.matcher = builder.build();
|
||||
this.indicator = indicator;
|
||||
}
|
||||
|
||||
@@ -355,7 +368,7 @@ public class GotoFileItemProvider extends DefaultChooseByNameItemProvider {
|
||||
}
|
||||
}
|
||||
|
||||
List<List<MatchResult>> groups = groupByMatchingDegree(!parameters.getCompletePattern().startsWith("*"), matchingNames);
|
||||
List<List<MatchResult>> groups = groupByMatchingDegree(matchingNames);
|
||||
for (List<MatchResult> group : groups) {
|
||||
JBIterable<FoundItemDescriptor<PsiFileSystemItem>> filesMatchingPath = getFilesMatchingPath(parameters, group, dirMatcher, indicator);
|
||||
Iterable<FoundItemDescriptor<PsiFileSystemItem>> matchedFiles =
|
||||
@@ -389,13 +402,13 @@ public class GotoFileItemProvider extends DefaultChooseByNameItemProvider {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<List<MatchResult>> groupByMatchingDegree(boolean preferStartMatches, @NotNull List<MatchResult> matchingNames) {
|
||||
private List<List<MatchResult>> groupByMatchingDegree(@NotNull List<MatchResult> matchingNames) {
|
||||
Comparator<MatchResult> comparator = (mr1, mr2) -> {
|
||||
boolean exactPrefix1 = StringUtil.startsWith(mr1.elementName, patternSuffix);
|
||||
boolean exactPrefix2 = StringUtil.startsWith(mr2.elementName, patternSuffix);
|
||||
if (exactPrefix1 && exactPrefix2) return 0;
|
||||
if (exactPrefix1 != exactPrefix2) return exactPrefix1 ? -1 : 1;
|
||||
return mr1.compareDegrees(mr2, preferStartMatches);
|
||||
return mr1.compareDegrees(mr2);
|
||||
};
|
||||
|
||||
return sortAndGroup(matchingNames, comparator);
|
||||
|
||||
+6
-1
@@ -62,7 +62,12 @@ public class RecentFilesSEContributor extends FileSearchEverywhereContributor {
|
||||
}
|
||||
|
||||
String searchString = filterControlSymbols(pattern);
|
||||
MinusculeMatcher matcher = NameUtil.buildMatcher("*" + searchString).build();
|
||||
boolean preferStartMatches = !searchString.startsWith("*");
|
||||
NameUtil.MatcherBuilder builder = NameUtil.buildMatcher("*" + searchString);
|
||||
if (preferStartMatches) {
|
||||
builder = builder.preferringStartMatches();
|
||||
}
|
||||
MinusculeMatcher matcher = builder.build();
|
||||
List<VirtualFile> opened = Arrays.asList(FileEditorManager.getInstance(myProject).getSelectedFiles());
|
||||
List<VirtualFile> history = Lists.reverse(EditorHistoryManager.getInstance(myProject).getFileList());
|
||||
|
||||
|
||||
+20
-13
@@ -114,7 +114,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameInScopeItemP
|
||||
|
||||
indicator.checkCanceled();
|
||||
|
||||
return processByNames(base, everywhere, indicator, context, consumer, preferStartMatches, namesList, parameters);
|
||||
return processByNames(base, everywhere, indicator, context, consumer, namesList, parameters);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -152,7 +152,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameInScopeItemP
|
||||
@NotNull ProgressIndicator indicator,
|
||||
@Nullable Supplier<String[]> allNamesProducer,
|
||||
String namePattern, boolean preferStartMatches) {
|
||||
List<MatchResult> namesList = getAllNames(base, parameters, indicator, allNamesProducer, namePattern);
|
||||
List<MatchResult> namesList = getAllNames(base, parameters, indicator, allNamesProducer, namePattern, preferStartMatches);
|
||||
|
||||
indicator.checkCanceled();
|
||||
String pattern = parameters.getCompletePattern();
|
||||
@@ -160,7 +160,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameInScopeItemP
|
||||
long started = System.currentTimeMillis();
|
||||
namesList.sort(Comparator.comparing((MatchResult mr) -> !pattern.equalsIgnoreCase(mr.elementName))
|
||||
.thenComparing((MatchResult mr) -> !namePattern.equalsIgnoreCase(mr.elementName))
|
||||
.thenComparing((mr1, mr2) -> mr1.compareWith(mr2, preferStartMatches)));
|
||||
.thenComparing(Comparator.naturalOrder()));
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("sorted:"+ (System.currentTimeMillis() - started) + ",results:" + namesList.size());
|
||||
}
|
||||
@@ -172,7 +172,8 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameInScopeItemP
|
||||
@NotNull FindSymbolParameters parameters,
|
||||
@NotNull ProgressIndicator indicator,
|
||||
@Nullable Supplier<String[]> allNamesProducer,
|
||||
@NotNull String namePattern) {
|
||||
@NotNull String namePattern,
|
||||
boolean preferStartMatches) {
|
||||
List<MatchResult> namesList = new ArrayList<>();
|
||||
|
||||
final CollectConsumer<MatchResult> collect = new SynchronizedCollectConsumer<>(namesList);
|
||||
@@ -182,7 +183,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameInScopeItemP
|
||||
indicator.checkCanceled();
|
||||
long started = System.currentTimeMillis();
|
||||
String fullPattern = parameters.getCompletePattern();
|
||||
MinusculeMatcher matcher = buildPatternMatcher(namePattern);
|
||||
MinusculeMatcher matcher = buildPatternMatcher(namePattern, preferStartMatches);
|
||||
((ChooseByNameModelEx)model).processNames(sequence -> {
|
||||
indicator.checkCanceled();
|
||||
MatchResult result = matches(base, fullPattern, matcher, sequence);
|
||||
@@ -202,7 +203,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameInScopeItemP
|
||||
}
|
||||
String[] names = allNamesProducer.get();
|
||||
long started = System.currentTimeMillis();
|
||||
processNamesByPattern(base, names, namePattern, indicator, collect);
|
||||
processNamesByPattern(base, names, namePattern, indicator, collect, preferStartMatches);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("matched:"+ (System.currentTimeMillis() - started)+ "," + names.length);
|
||||
}
|
||||
@@ -225,7 +226,6 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameInScopeItemP
|
||||
@NotNull ProgressIndicator indicator,
|
||||
@Nullable PsiElement context,
|
||||
@NotNull Processor<? super FoundItemDescriptor<?>> consumer,
|
||||
boolean preferStartMatches,
|
||||
@NotNull List<? extends MatchResult> namesList,
|
||||
@NotNull FindSymbolParameters parameters) {
|
||||
List<Pair<Object, MatchResult>> sameNameElements = new SmartList<>();
|
||||
@@ -239,7 +239,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameInScopeItemP
|
||||
@Override
|
||||
public int compare(Pair<Object, MatchResult> o1, Pair<Object, MatchResult> o2) {
|
||||
int result = modelComparator.compare(o1.first, o2.first);
|
||||
return result != 0 ? result : o1.second.compareWith(o2.second, preferStartMatches);
|
||||
return result != 0 ? result : o1.second.compareTo(o2.second);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -333,6 +333,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameInScopeItemP
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> filterNames(@NotNull ChooseByNameBase base, @NotNull String[] names, @NotNull String pattern) {
|
||||
boolean preferStartMatches = pattern.startsWith("*");
|
||||
pattern = convertToMatchingPattern(base, pattern);
|
||||
if (pattern.isEmpty() && !base.canShowListForEmptyPattern()) return Collections.emptyList();
|
||||
|
||||
@@ -341,7 +342,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameInScopeItemP
|
||||
synchronized (filtered) {
|
||||
filtered.add(result.elementName);
|
||||
}
|
||||
});
|
||||
}, preferStartMatches);
|
||||
synchronized (filtered) {
|
||||
return filtered;
|
||||
}
|
||||
@@ -351,8 +352,9 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameInScopeItemP
|
||||
@NotNull final String[] names,
|
||||
@NotNull final String pattern,
|
||||
final ProgressIndicator indicator,
|
||||
@NotNull final Consumer<? super MatchResult> consumer) {
|
||||
MinusculeMatcher matcher = buildPatternMatcher(pattern);
|
||||
@NotNull final Consumer<? super MatchResult> consumer,
|
||||
boolean preferStartMatches) {
|
||||
MinusculeMatcher matcher = buildPatternMatcher(pattern, preferStartMatches);
|
||||
Processor<String> processor = name -> {
|
||||
ProgressManager.checkCanceled();
|
||||
MatchResult result = matches(base, pattern, matcher, name);
|
||||
@@ -415,8 +417,13 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameInScopeItemP
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static MinusculeMatcher buildPatternMatcher(@NotNull String pattern) {
|
||||
return NameUtil.buildMatcher(pattern, NameUtil.MatchingCaseSensitivity.NONE);
|
||||
private static MinusculeMatcher buildPatternMatcher(@NotNull String pattern, boolean preferStartMatches) {
|
||||
NameUtil.MatcherBuilder builder = NameUtil.buildMatcher(pattern).withCaseSensitivity(NameUtil.MatchingCaseSensitivity.NONE);
|
||||
if (preferStartMatches) {
|
||||
builder = builder.preferringStartMatches();
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected static class PathProximityComparator implements Comparator<Object> {
|
||||
|
||||
@@ -17,7 +17,7 @@ package com.intellij.ide.util.gotoByName;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class MatchResult {
|
||||
public class MatchResult implements Comparable<MatchResult> {
|
||||
@NotNull
|
||||
public final String elementName;
|
||||
public final int matchingDegree;
|
||||
@@ -29,22 +29,13 @@ public class MatchResult {
|
||||
this.startMatch = startMatch;
|
||||
}
|
||||
|
||||
public int compareDegrees(@NotNull MatchResult that, boolean preferStartMatches) {
|
||||
boolean start1 = startMatch;
|
||||
boolean start2 = that.startMatch;
|
||||
int startMatchResult = start1 == start2 ? 0 : start1 ? -1 : 1;
|
||||
if (preferStartMatches && startMatchResult != 0) return startMatchResult;
|
||||
|
||||
int degree1 = matchingDegree;
|
||||
int degree2 = that.matchingDegree;
|
||||
if (degree2 < degree1) return -1;
|
||||
if (degree2 > degree1) return 1;
|
||||
|
||||
return -startMatchResult;
|
||||
public int compareDegrees(@NotNull MatchResult that) {
|
||||
return Integer.compare(that.matchingDegree, matchingDegree);
|
||||
}
|
||||
|
||||
int compareWith(@NotNull MatchResult that, boolean preferStartMatches) {
|
||||
int result = compareDegrees(that, preferStartMatches);
|
||||
@Override
|
||||
public int compareTo(@NotNull MatchResult that) {
|
||||
int result = compareDegrees(that);
|
||||
return result != 0 ? result : elementName.compareToIgnoreCase(that.elementName);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user