diff options
| -rw-r--r-- | clang-tools-extra/clangd/FuzzyMatch.cpp | 8 | ||||
| -rw-r--r-- | clang-tools-extra/clangd/FuzzyMatch.h | 4 | ||||
| -rw-r--r-- | clang-tools-extra/clangd/Quality.cpp | 2 | ||||
| -rw-r--r-- | clang-tools-extra/clangd/Quality.h | 2 | ||||
| -rw-r--r-- | clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp | 8 | ||||
| -rw-r--r-- | clang-tools-extra/unittests/clangd/FuzzyMatchTests.cpp | 26 |
6 files changed, 37 insertions, 13 deletions
diff --git a/clang-tools-extra/clangd/FuzzyMatch.cpp b/clang-tools-extra/clangd/FuzzyMatch.cpp index 152f1799777..0fc2e32c523 100644 --- a/clang-tools-extra/clangd/FuzzyMatch.cpp +++ b/clang-tools-extra/clangd/FuzzyMatch.cpp @@ -101,7 +101,13 @@ Optional<float> FuzzyMatcher::match(StringRef Word) { Scores[PatN][WordN][Match].Score); if (isAwful(Best)) return None; - return ScoreScale * std::min(PerfectBonus * PatN, std::max<int>(0, Best)); + float Score = + ScoreScale * std::min(PerfectBonus * PatN, std::max<int>(0, Best)); + // If the pattern is as long as the word, we have an exact string match, + // since every pattern character must match something. + if (WordN == PatN) + Score *= 2; // May not be perfect 2 if case differs in a significant way. + return Score; } // Segmentation of words and patterns. diff --git a/clang-tools-extra/clangd/FuzzyMatch.h b/clang-tools-extra/clangd/FuzzyMatch.h index 13a25e28311..d3509ad89a5 100644 --- a/clang-tools-extra/clangd/FuzzyMatch.h +++ b/clang-tools-extra/clangd/FuzzyMatch.h @@ -31,7 +31,9 @@ public: // Characters beyond MaxPat are ignored. FuzzyMatcher(llvm::StringRef Pattern); - // If Word matches the pattern, return a score in [0,1] (higher is better). + // If Word matches the pattern, return a score indicating the quality match. + // Scores usually fall in a [0,1] range, with 1 being a very good score. + // "Super" scores in (1,2] are possible if the pattern is the full word. // Characters beyond MaxWord are ignored. llvm::Optional<float> match(llvm::StringRef Word); diff --git a/clang-tools-extra/clangd/Quality.cpp b/clang-tools-extra/clangd/Quality.cpp index 1021456660b..6034faaf814 100644 --- a/clang-tools-extra/clangd/Quality.cpp +++ b/clang-tools-extra/clangd/Quality.cpp @@ -131,6 +131,8 @@ float SymbolQualitySignals::evaluate() const { Score *= 1.1; break; case Namespace: + Score *= 0.8; + break; case Macro: Score *= 0.2; break; diff --git a/clang-tools-extra/clangd/Quality.h b/clang-tools-extra/clangd/Quality.h index fa05a7234b3..99731d9408a 100644 --- a/clang-tools-extra/clangd/Quality.h +++ b/clang-tools-extra/clangd/Quality.h @@ -70,7 +70,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &, /// Attributes of a symbol-query pair that affect how much we like it. struct SymbolRelevanceSignals { - /// 0-1 fuzzy-match score for unqualified name. Must be explicitly assigned. + /// 0-1+ fuzzy-match score for unqualified name. Must be explicitly assigned. float NameMatch = 1; bool Forbidden = false; // Unavailable (e.g const) or inaccessible (private). /// Proximity between best declaration and the query. [0-1], 1 is closest. diff --git a/clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp b/clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp index 712b19d7b9b..e4eea0bebe1 100644 --- a/clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp +++ b/clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp @@ -273,10 +273,10 @@ TEST_F(WorkspaceSymbolsTest, WithLimit) { #include "foo.h" )cpp"); EXPECT_THAT(getSymbols("foo"), - ElementsAre(AllOf(Named("foo"), InContainer(""), - WithKind(SymbolKind::Variable)), - AllOf(Named("foo2"), InContainer(""), - WithKind(SymbolKind::Variable)))); + UnorderedElementsAre(AllOf(Named("foo"), InContainer(""), + WithKind(SymbolKind::Variable)), + AllOf(Named("foo2"), InContainer(""), + WithKind(SymbolKind::Variable)))); Limit = 1; EXPECT_THAT(getSymbols("foo"), diff --git a/clang-tools-extra/unittests/clangd/FuzzyMatchTests.cpp b/clang-tools-extra/unittests/clangd/FuzzyMatchTests.cpp index 3de53494701..25c06b9bf49 100644 --- a/clang-tools-extra/unittests/clangd/FuzzyMatchTests.cpp +++ b/clang-tools-extra/unittests/clangd/FuzzyMatchTests.cpp @@ -46,10 +46,14 @@ private: struct MatchesMatcher : public testing::MatcherInterface<StringRef> { ExpectedMatch Candidate; - MatchesMatcher(ExpectedMatch Candidate) : Candidate(std::move(Candidate)) {} + Optional<float> Score; + MatchesMatcher(ExpectedMatch Candidate, Optional<float> Score) + : Candidate(std::move(Candidate)), Score(Score) {} void DescribeTo(::std::ostream *OS) const override { raw_os_ostream(*OS) << "Matches " << Candidate; + if (Score) + *OS << " with score " << *Score; } bool MatchAndExplain(StringRef Pattern, @@ -60,14 +64,15 @@ struct MatchesMatcher : public testing::MatcherInterface<StringRef> { FuzzyMatcher Matcher(Pattern); auto Result = Matcher.match(Candidate.Word); auto AnnotatedMatch = Matcher.dumpLast(*OS << "\n"); - return Result && Candidate.accepts(AnnotatedMatch); + return Result && Candidate.accepts(AnnotatedMatch) && + (!Score || testing::Value(*Result, testing::FloatEq(*Score))); } }; -// Accepts patterns that match a given word. +// Accepts patterns that match a given word, optionally requiring a score. // Dumps the debug tables on match failure. -testing::Matcher<StringRef> matches(StringRef M) { - return testing::MakeMatcher<StringRef>(new MatchesMatcher(M)); +testing::Matcher<StringRef> matches(StringRef M, Optional<float> Score = {}) { + return testing::MakeMatcher<StringRef>(new MatchesMatcher(M, Score)); } TEST(FuzzyMatch, Matches) { @@ -239,7 +244,7 @@ TEST(FuzzyMatch, Ranking) { ranks("[onMess]age", "[onmess]age", "[on]This[M]ega[Es]cape[s]")); EXPECT_THAT("CC", ranks("[C]amel[C]ase", "[c]amel[C]ase")); EXPECT_THAT("cC", ranks("[c]amel[C]ase", "[C]amel[C]ase")); - EXPECT_THAT("p", ranks("[p]arse", "[p]osix", "[p]afdsa", "[p]ath", "[p]")); + EXPECT_THAT("p", ranks("[p]", "[p]arse", "[p]osix", "[p]afdsa", "[p]ath")); EXPECT_THAT("pa", ranks("[pa]rse", "[pa]th", "[pa]fdsa")); EXPECT_THAT("log", ranks("[log]", "Scroll[Log]icalPosition")); EXPECT_THAT("e", ranks("[e]lse", "Abstract[E]lement")); @@ -262,6 +267,15 @@ TEST(FuzzyMatch, Ranking) { "[c]ss.co[lo]rDecorator[s].[e]nable")); } +// Verify some bounds so we know scores fall in the right range. +// Testing exact scores is fragile, so we prefer Ranking tests. +TEST(FuzzyMatch, Scoring) { + EXPECT_THAT("abs", matches("[a]x[b]y[s]z", 0.f)); + EXPECT_THAT("abs", matches("[abs]l", 1.f)); + EXPECT_THAT("abs", matches("[abs]", 2.f)); + EXPECT_THAT("Abs", matches("[abs]", 2.f)); +} + } // namespace } // namespace clangd } // namespace clang |

