From 6a467c2fa237cdc0053d9fb3c97efa6cb72c0f3b Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 18 Mar 2020 12:26:46 -0700 Subject: [PATCH 1/2] Add loose fuzzy matching for workspace symbol queries --- src/LanguageServer/Impl/Indexing/SymbolIndex.cs | 16 +++++++++++++++- src/LanguageServer/Test/SymbolIndexTests.cs | 17 +++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/LanguageServer/Impl/Indexing/SymbolIndex.cs b/src/LanguageServer/Impl/Indexing/SymbolIndex.cs index 7b97905b7..de913eff3 100644 --- a/src/LanguageServer/Impl/Indexing/SymbolIndex.cs +++ b/src/LanguageServer/Impl/Indexing/SymbolIndex.cs @@ -98,7 +98,7 @@ private IEnumerable WorkspaceSymbolsQuery(string path, string query, var sym = symAndPar.symbol; return DecorateWithParentsName((sym.Children ?? Enumerable.Empty()).ToList(), sym.Name); }); - return treeSymbols.Where(sym => sym.symbol.Name.ContainsOrdinal(query, ignoreCase: true)) + return treeSymbols.Where(sym => FuzzyMatch(query, sym.symbol.Name)) .Select(sym => new FlatSymbol(sym.symbol.Name, sym.symbol.Kind, path, sym.symbol.SelectionRange, sym.parentName, sym.symbol._existInAllVariable)); } @@ -114,5 +114,19 @@ private IMostRecentDocumentSymbols MakeMostRecentDocSymbols(string path) { public void Dispose() { _disposables.TryDispose(); } + + private bool FuzzyMatch(string pattern, string name) { + var patternPos = 0; + var namePos = 0; + + while (patternPos < pattern.Length && namePos < name.Length) { + if (char.ToLowerInvariant(pattern[patternPos]) == char.ToLowerInvariant(name[namePos])) { + patternPos++; + } + namePos++; + } + + return patternPos == pattern.Length; + } } } diff --git a/src/LanguageServer/Test/SymbolIndexTests.cs b/src/LanguageServer/Test/SymbolIndexTests.cs index 861eb1cec..d695ad8ce 100644 --- a/src/LanguageServer/Test/SymbolIndexTests.cs +++ b/src/LanguageServer/Test/SymbolIndexTests.cs @@ -160,6 +160,23 @@ public async Task IndexWorkspaceSymbolsCaseInsensitiveAsync() { } } + [TestMethod, Priority(0)] + public async Task IndexWorkspaceSymbolsFuzzyAsync() { + const string code = @"class FXoo(object): + def foxo(self, x): ..."; + + using (var index = MakeSymbolIndex()) { + var path = TestData.GetDefaultModulePath(); + index.Add(path, DocumentWithAst(code)); + + var symbols = await index.WorkspaceSymbolsAsync("foo", maxSymbols); + symbols.Should().BeEquivalentToWithStrictOrdering(new[] { + new FlatSymbol("FXoo", SymbolKind.Class, path, new SourceSpan(1, 7, 1, 11)), + new FlatSymbol("foxo", SymbolKind.Method, path, new SourceSpan(2, 9, 2, 13), "FXoo"), + }); + } + } + [TestMethod, Priority(0)] public void MarkAsPendingWaitsForUpdates() { using (var index = MakeSymbolIndex()) { From 38e1188dcd69bff223661dc9b43358eba03edbd8 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 18 Mar 2020 12:28:05 -0700 Subject: [PATCH 2/2] Make function static --- src/LanguageServer/Impl/Indexing/SymbolIndex.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LanguageServer/Impl/Indexing/SymbolIndex.cs b/src/LanguageServer/Impl/Indexing/SymbolIndex.cs index de913eff3..5d901f634 100644 --- a/src/LanguageServer/Impl/Indexing/SymbolIndex.cs +++ b/src/LanguageServer/Impl/Indexing/SymbolIndex.cs @@ -115,7 +115,7 @@ public void Dispose() { _disposables.TryDispose(); } - private bool FuzzyMatch(string pattern, string name) { + private static bool FuzzyMatch(string pattern, string name) { var patternPos = 0; var namePos = 0;