kadircet created this revision.
Herald added subscribers: cfe-commits, usaxena95, arphaman.
Herald added a project: clang.
kadircet requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

This will enable queries like "clangd::" to find symbols under clangd
namespace, without requiring full "clang::clangd::" qualification.

Since Fuzzyfind performs the search under all scopes and only boosts the symbols
from relevant namespaces, we might get symbols from non-matching namespaces.
This patch chooses to drop those as they clearly do not match the query.

Fixes https://github.com/clangd/clangd/issues/550.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D88814

Files:
  clang-tools-extra/clangd/FindSymbols.cpp
  clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp


Index: clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
+++ clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
@@ -141,7 +141,10 @@
   EXPECT_THAT(getSymbols(TU, "::"), ElementsAre(QName("ans1")));
   EXPECT_THAT(getSymbols(TU, "::a"), ElementsAre(QName("ans1")));
   EXPECT_THAT(getSymbols(TU, "ans1::"),
-              UnorderedElementsAre(QName("ans1::ai1"), QName("ans1::ans2")));
+              UnorderedElementsAre(QName("ans1::ai1"), QName("ans1::ans2"),
+                                   QName("ans1::ans2::ai2")));
+  EXPECT_THAT(getSymbols(TU, "ans2::"),
+              UnorderedElementsAre(QName("ans1::ans2::ai2")));
   EXPECT_THAT(getSymbols(TU, "::ans1"), ElementsAre(QName("ans1")));
   EXPECT_THAT(getSymbols(TU, "::ans1::"),
               UnorderedElementsAre(QName("ans1::ai1"), QName("ans1::ans2")));
Index: clang-tools-extra/clangd/FindSymbols.cpp
===================================================================
--- clang-tools-extra/clangd/FindSymbols.cpp
+++ clang-tools-extra/clangd/FindSymbols.cpp
@@ -76,20 +76,26 @@
   FuzzyFindRequest Req;
   Req.Query = std::string(Names.second);
 
-  // FuzzyFind doesn't want leading :: qualifier
-  bool IsGlobalQuery = Names.first.consume_front("::");
-  // Restrict results to the scope in the query string if present (global or
-  // not).
-  if (IsGlobalQuery || !Names.first.empty())
+  // FuzzyFind doesn't want leading :: qualifier. Also limit the query to
+  // specific namespace if it is fully-qualified.
+  Req.AnyScope = !Names.first.consume_front("::");
+  // Boost symbols from desired namespace.
+  if (!Req.AnyScope || !Names.first.empty())
     Req.Scopes = {std::string(Names.first)};
-  else
-    Req.AnyScope = true;
   if (Limit)
     Req.Limit = Limit;
   TopN<ScoredSymbolInfo, ScoredSymbolGreater> Top(
       Req.Limit ? *Req.Limit : std::numeric_limits<size_t>::max());
   FuzzyMatcher Filter(Req.Query);
-  Index->fuzzyFind(Req, [HintPath, &Top, &Filter](const Symbol &Sym) {
+  Index->fuzzyFind(Req, [HintPath, &Top, &Filter, &Names](const Symbol &Sym) {
+    std::string Scope = std::string(Sym.Scope);
+    llvm::StringRef ScopeRef = Scope;
+    // Fuzzfind might return symbols from irrelevant namespaces if query was 
not
+    // fully-qualified, drop those.
+    if (!ScopeRef.contains(Names.first))
+      return;
+    ScopeRef.consume_back("::");
+
     auto Loc = symbolToLocation(Sym, HintPath);
     if (!Loc) {
       log("Workspace symbols: {0}", Loc.takeError());
@@ -97,9 +103,6 @@
     }
 
     SymbolKind SK = indexSymbolKindToSymbolKind(Sym.SymInfo.Kind);
-    std::string Scope = std::string(Sym.Scope);
-    llvm::StringRef ScopeRef = Scope;
-    ScopeRef.consume_back("::");
     SymbolInformation Info = {(Sym.Name + 
Sym.TemplateSpecializationArgs).str(),
                               SK, *Loc, std::string(ScopeRef)};
 


Index: clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
+++ clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
@@ -141,7 +141,10 @@
   EXPECT_THAT(getSymbols(TU, "::"), ElementsAre(QName("ans1")));
   EXPECT_THAT(getSymbols(TU, "::a"), ElementsAre(QName("ans1")));
   EXPECT_THAT(getSymbols(TU, "ans1::"),
-              UnorderedElementsAre(QName("ans1::ai1"), QName("ans1::ans2")));
+              UnorderedElementsAre(QName("ans1::ai1"), QName("ans1::ans2"),
+                                   QName("ans1::ans2::ai2")));
+  EXPECT_THAT(getSymbols(TU, "ans2::"),
+              UnorderedElementsAre(QName("ans1::ans2::ai2")));
   EXPECT_THAT(getSymbols(TU, "::ans1"), ElementsAre(QName("ans1")));
   EXPECT_THAT(getSymbols(TU, "::ans1::"),
               UnorderedElementsAre(QName("ans1::ai1"), QName("ans1::ans2")));
Index: clang-tools-extra/clangd/FindSymbols.cpp
===================================================================
--- clang-tools-extra/clangd/FindSymbols.cpp
+++ clang-tools-extra/clangd/FindSymbols.cpp
@@ -76,20 +76,26 @@
   FuzzyFindRequest Req;
   Req.Query = std::string(Names.second);
 
-  // FuzzyFind doesn't want leading :: qualifier
-  bool IsGlobalQuery = Names.first.consume_front("::");
-  // Restrict results to the scope in the query string if present (global or
-  // not).
-  if (IsGlobalQuery || !Names.first.empty())
+  // FuzzyFind doesn't want leading :: qualifier. Also limit the query to
+  // specific namespace if it is fully-qualified.
+  Req.AnyScope = !Names.first.consume_front("::");
+  // Boost symbols from desired namespace.
+  if (!Req.AnyScope || !Names.first.empty())
     Req.Scopes = {std::string(Names.first)};
-  else
-    Req.AnyScope = true;
   if (Limit)
     Req.Limit = Limit;
   TopN<ScoredSymbolInfo, ScoredSymbolGreater> Top(
       Req.Limit ? *Req.Limit : std::numeric_limits<size_t>::max());
   FuzzyMatcher Filter(Req.Query);
-  Index->fuzzyFind(Req, [HintPath, &Top, &Filter](const Symbol &Sym) {
+  Index->fuzzyFind(Req, [HintPath, &Top, &Filter, &Names](const Symbol &Sym) {
+    std::string Scope = std::string(Sym.Scope);
+    llvm::StringRef ScopeRef = Scope;
+    // Fuzzfind might return symbols from irrelevant namespaces if query was not
+    // fully-qualified, drop those.
+    if (!ScopeRef.contains(Names.first))
+      return;
+    ScopeRef.consume_back("::");
+
     auto Loc = symbolToLocation(Sym, HintPath);
     if (!Loc) {
       log("Workspace symbols: {0}", Loc.takeError());
@@ -97,9 +103,6 @@
     }
 
     SymbolKind SK = indexSymbolKindToSymbolKind(Sym.SymInfo.Kind);
-    std::string Scope = std::string(Sym.Scope);
-    llvm::StringRef ScopeRef = Scope;
-    ScopeRef.consume_back("::");
     SymbolInformation Info = {(Sym.Name + Sym.TemplateSpecializationArgs).str(),
                               SK, *Loc, std::string(ScopeRef)};
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to