ioeric created this revision.
ioeric added a reviewer: ilya-biryukov.
Herald added subscribers: cfe-commits, jdoerfert.
Herald added a project: clang.

This will allow completion consumers to guess the specified scope by
putting together scopes in the context with the specified scope (e.g. when the
specified namespace is not imported yet).


Repository:
  rC Clang

https://reviews.llvm.org/D58446

Files:
  lib/Sema/SemaCodeComplete.cpp
  unittests/Sema/CodeCompleteTest.cpp


Index: unittests/Sema/CodeCompleteTest.cpp
===================================================================
--- unittests/Sema/CodeCompleteTest.cpp
+++ unittests/Sema/CodeCompleteTest.cpp
@@ -181,6 +181,18 @@
   EXPECT_TRUE(VisitedNS.empty());
 }
 
+TEST(SemaCodeCompleteTest, VisitedNSForInvalidQualifiedId) {
+  auto VisitedNS = runCodeCompleteOnCode(R"cpp(
+     namespace na {}
+     namespace ns1 {
+     using namespace na;
+     foo::^
+     }
+  )cpp")
+                       .VisitedNamespaces;
+  EXPECT_THAT(VisitedNS, UnorderedElementsAre("ns1::", "na::"));
+}
+
 TEST(SemaCodeCompleteTest, VisitedNSWithoutQualifier) {
   auto VisitedNS = runCodeCompleteOnCode(R"cpp(
     namespace n1 {
Index: lib/Sema/SemaCodeComplete.cpp
===================================================================
--- lib/Sema/SemaCodeComplete.cpp
+++ lib/Sema/SemaCodeComplete.cpp
@@ -5061,7 +5061,20 @@
   if (SS.isInvalid()) {
     CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol);
     CC.setCXXScopeSpecifier(SS);
-    HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
+    // As SS is invalid, we try to collect accessible contexts from the current
+    // scope with a dummy lookup so that the completion consumer can try to
+    // guess what the specified scope is.
+    ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(),
+                               CodeCompleter->getCodeCompletionTUInfo(), CC);
+    if (S->getEntity()) {
+      CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(),
+                                          BaseType);
+      LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                         /*IncludeGlobalScope=*/false,
+                         /*LoadExternal=*/false);
+    }
+    HandleCodeCompleteResults(this, CodeCompleter,
+                              DummyResults.getCompletionContext(), nullptr, 0);
     return;
   }
   // Always pretend to enter a context to ensure that a dependent type


Index: unittests/Sema/CodeCompleteTest.cpp
===================================================================
--- unittests/Sema/CodeCompleteTest.cpp
+++ unittests/Sema/CodeCompleteTest.cpp
@@ -181,6 +181,18 @@
   EXPECT_TRUE(VisitedNS.empty());
 }
 
+TEST(SemaCodeCompleteTest, VisitedNSForInvalidQualifiedId) {
+  auto VisitedNS = runCodeCompleteOnCode(R"cpp(
+     namespace na {}
+     namespace ns1 {
+     using namespace na;
+     foo::^
+     }
+  )cpp")
+                       .VisitedNamespaces;
+  EXPECT_THAT(VisitedNS, UnorderedElementsAre("ns1::", "na::"));
+}
+
 TEST(SemaCodeCompleteTest, VisitedNSWithoutQualifier) {
   auto VisitedNS = runCodeCompleteOnCode(R"cpp(
     namespace n1 {
Index: lib/Sema/SemaCodeComplete.cpp
===================================================================
--- lib/Sema/SemaCodeComplete.cpp
+++ lib/Sema/SemaCodeComplete.cpp
@@ -5061,7 +5061,20 @@
   if (SS.isInvalid()) {
     CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol);
     CC.setCXXScopeSpecifier(SS);
-    HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
+    // As SS is invalid, we try to collect accessible contexts from the current
+    // scope with a dummy lookup so that the completion consumer can try to
+    // guess what the specified scope is.
+    ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(),
+                               CodeCompleter->getCodeCompletionTUInfo(), CC);
+    if (S->getEntity()) {
+      CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(),
+                                          BaseType);
+      LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+                         /*IncludeGlobalScope=*/false,
+                         /*LoadExternal=*/false);
+    }
+    HandleCodeCompleteResults(this, CodeCompleter,
+                              DummyResults.getCompletionContext(), nullptr, 0);
     return;
   }
   // Always pretend to enter a context to ensure that a dependent type
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to