[PATCH] D58448: [clangd] Improve global code completion when scope specifier is unresolved.

Eric Liu via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 20 06:43:12 PST 2019


ioeric created this revision.
ioeric added reviewers: ilya-biryukov, sammccall.
Herald added subscribers: cfe-commits, jdoerfert, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

Suppose `clangd::` is unresolved in the following example. Currently,
we simply use "clangd::" as the query scope. We can do better by combining with
accessible scopes in the context. The query scopes can be `{clangd::, clang::clangd::}`.

  namespace clang { clangd::^ }


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D58448

Files:
  clangd/CodeComplete.cpp
  unittests/clangd/CodeCompleteTests.cpp


Index: unittests/clangd/CodeCompleteTests.cpp
===================================================================
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1094,8 +1094,10 @@
       } // namespace ns
   )cpp");
 
-  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
-                                          UnorderedElementsAre("bar::"))));
+  EXPECT_THAT(Requests,
+              ElementsAre(Field(
+                  &FuzzyFindRequest::Scopes,
+                  UnorderedElementsAre("a::bar::", "ns::bar::", "bar::"))));
 }
 
 TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
@@ -2314,6 +2316,35 @@
   EXPECT_THAT(R.Completions, ElementsAre(Named("loopVar")));
 }
 
+TEST(CompletionTest, ScopeIsUnresolved) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(R"cpp(
+    namespace a {
+    void f() { b::X^ }
+    }
+  )cpp",
+                             {cls("a::b::XYZ")}, Opts);
+  EXPECT_THAT(Results.Completions,
+              UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ"))));
+}
+
+TEST(CompletionTest, NestedScopeIsUnresolved) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(R"cpp(
+    namespace a {
+    namespace b {}
+    void f() { b::c::X^ }
+    }
+  )cpp",
+                             {cls("a::b::c::XYZ")}, Opts);
+  EXPECT_THAT(Results.Completions,
+              UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ"))));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.cpp
===================================================================
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -48,6 +48,7 @@
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
@@ -526,7 +527,7 @@
     std::set<std::string> Results;
     for (llvm::StringRef AS : AccessibleScopes)
       Results.insert(
-          ((UnresolvedQualifier ? *UnresolvedQualifier : "") + AS).str());
+          (AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());
     return {Results.begin(), Results.end()};
   }
 };
@@ -570,16 +571,16 @@
   }
 
   // Unresolved qualifier.
-  // FIXME: When Sema can resolve part of a scope chain (e.g.
-  // "known::unknown::id"), we should expand the known part ("known::") rather
-  // than treating the whole thing as unknown.
-  SpecifiedScope Info;
-  Info.AccessibleScopes.push_back(""); // global namespace
+  SpecifiedScope Info = GetAllAccessibleScopes(CCContext);
+  if (Info.AccessibleScopes.empty())
+    Info.AccessibleScopes.push_back(""); // Fallback to global namespace.
 
-  Info.UnresolvedQualifier =
+  llvm::StringRef SpelledSpecifier =
       Lexer::getSourceText(CharSourceRange::getCharRange((*SS)->getRange()),
-                           CCSema.SourceMgr, clang::LangOptions())
-          .ltrim("::");
+                           CCSema.SourceMgr, clang::LangOptions());
+  if (SpelledSpecifier.consume_front("::"))
+    Info.AccessibleScopes = {""};
+  Info.UnresolvedQualifier = SpelledSpecifier;
   // Sema excludes the trailing "::".
   if (!Info.UnresolvedQualifier->empty())
     *Info.UnresolvedQualifier += "::";


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D58448.187568.patch
Type: text/x-patch
Size: 3411 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20190220/81dd7b87/attachment.bin>


More information about the cfe-commits mailing list