From fc42270a32be2faa4ef2104b340bdc2e0ce72326 Mon Sep 17 00:00:00 2001 From: Mikhail Sokolov Date: Wed, 8 Jul 2020 17:06:24 +0300 Subject: [PATCH] IDEA-223194 Strange pattern matching when searching for action GitOrigin-RevId: 3ba6fb82265633b41cd99d112bbddc50af73dd30 --- .../ide/util/gotoByName/GotoActionTest.groovy | 31 ++++++++++++++++--- .../ide/ui/OptionsTopHitProvider.java | 2 +- .../psi/codeStyle/WordPrefixMatcher.java | 9 ++++-- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/ide/util/gotoByName/GotoActionTest.groovy b/java/java-tests/testSrc/com/intellij/ide/util/gotoByName/GotoActionTest.groovy index 4ed17cff183d..9ef94d17886f 100644 --- a/java/java-tests/testSrc/com/intellij/ide/util/gotoByName/GotoActionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/ide/util/gotoByName/GotoActionTest.groovy @@ -18,10 +18,12 @@ import com.intellij.openapi.project.DumbAwareAction import com.intellij.openapi.project.Project import com.intellij.openapi.util.Computable import com.intellij.openapi.util.Disposer +import com.intellij.psi.codeStyle.WordPrefixMatcher import com.intellij.testFramework.PlatformTestUtil import com.intellij.testFramework.TestApplicationManager import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase import com.intellij.util.CollectConsumer +import com.intellij.util.text.Matcher import gnu.trove.Equality import groovy.transform.CompileStatic import org.jetbrains.annotations.NonNls @@ -132,7 +134,21 @@ class GotoActionTest extends LightJavaCodeInsightFixtureTestCase { def consumer = new CollectConsumer() provider.consumeTopHits("/testprovider CamelCase", consumer, project) - assert consumer.getResult() == [options[0], options[1], options[3], options[4]] + assert consumer.getResult() == [options[0], options[3]] + } + + void "test TopHit CamelCase actions found in lower case"() { + def action1 = createAction("CamelCase Name", "none") + def action2 = createAction("Simple Name", "CamelCase description") + def action3 = createAction("Prefix-CamelCase Name", "none") + def action4 = createAction("Non Camel Case Name", "none") + def action5 = createAction("Look4CamelCase Name", "none") + def pattern = "camelcase" + assert actionMatches(pattern, action1, new WordPrefixMatcher(pattern)) == MatchMode.NAME + assert actionMatches(pattern, action2, new WordPrefixMatcher(pattern)) == MatchMode.DESCRIPTION + assert actionMatches(pattern, action3, new WordPrefixMatcher(pattern)) == MatchMode.NAME + assert actionMatches(pattern, action4, new WordPrefixMatcher(pattern)) == MatchMode.NONE + assert actionMatches(pattern, action5, new WordPrefixMatcher(pattern)) == MatchMode.NAME } private static class TestBooleanOption extends BooleanOptionDescription { @@ -369,8 +385,8 @@ class GotoActionTest extends LightJavaCodeInsightFixtureTestCase { } as List } - private def actionMatches(String pattern, AnAction action) { - return new GotoActionModel(project, null, null).actionMatches(pattern, GotoActionItemProvider.buildMatcher(pattern), action) + private def actionMatches(String pattern, AnAction action, Matcher matcher = GotoActionItemProvider.buildMatcher(pattern)) { + return new GotoActionModel(project, null, null).actionMatches(pattern, matcher, action) } private MatchedValue matchedAction(String text, String pattern, MatchMode mode = MatchMode.NAME, boolean isAvailable = true) { @@ -388,12 +404,17 @@ class GotoActionTest extends LightJavaCodeInsightFixtureTestCase { new MatchedValue(wrapper, pattern) } - private static AnAction createAction(String text) { - new AnAction(text) { + private static AnAction createAction(String text, String description = null) { + def action = new AnAction(text) { @Override void actionPerformed(@NotNull AnActionEvent e) { } } + if (description != null) { + action.getTemplatePresentation().setDescription(description) + } + + return action } private static DefaultActionGroup createActionGroup(String text, boolean hideByDefault) { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/OptionsTopHitProvider.java b/platform/platform-impl/src/com/intellij/ide/ui/OptionsTopHitProvider.java index 4e9651edb7c1..1c17891a0519 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/OptionsTopHitProvider.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/OptionsTopHitProvider.java @@ -95,7 +95,7 @@ public abstract class OptionsTopHitProvider implements OptionsSearchTopHitProvid @NotNull private static Matcher buildMatcher(String pattern) { - return pattern.contains(" ") ? new WordPrefixMatcher(pattern) : NameUtil.buildMatcher("*" + pattern, NameUtil.MatchingCaseSensitivity.NONE); + return new WordPrefixMatcher(pattern); } private static @Nullable String checkPattern(@NotNull String pattern) { diff --git a/platform/util/text-matching/src/com/intellij/psi/codeStyle/WordPrefixMatcher.java b/platform/util/text-matching/src/com/intellij/psi/codeStyle/WordPrefixMatcher.java index dfdf10fa197f..238cca9ee8fe 100644 --- a/platform/util/text-matching/src/com/intellij/psi/codeStyle/WordPrefixMatcher.java +++ b/platform/util/text-matching/src/com/intellij/psi/codeStyle/WordPrefixMatcher.java @@ -12,17 +12,22 @@ public class WordPrefixMatcher implements Matcher { private final String[] myFallbackPatternWords; public WordPrefixMatcher(String pattern) { - myPatternWords = NameUtil.nameToWords(pattern); + myPatternWords = splitToWords(pattern); String fixedLayout = FixingLayoutMatcher.fixLayout(pattern); myFallbackPatternWords = fixedLayout != null && !fixedLayout.equals(pattern) ? NameUtil.nameToWords(fixedLayout) : null; } @Override public boolean matches(@NotNull String name) { - String[] nameWords = NameUtil.nameToWords(name); + String[] nameWords = splitToWords(name); return matches(myPatternWords, nameWords) || myFallbackPatternWords != null && matches(myFallbackPatternWords, nameWords); } + @NotNull + private static String[] splitToWords(@NotNull String string) { + return string.split("[^a-zA-Z]+"); + } + private static boolean matches(String[] patternWords, String[] nameWords) { return Arrays.stream(patternWords).allMatch(pw -> Arrays.stream(nameWords).anyMatch(nw -> StringUtilRt.startsWithIgnoreCase(nw, pw))); }