malaperle created this revision.
Herald added subscribers: cfe-commits, jkorous, MaskRay, ioeric, ilya-biryukov, 
klimek.

For enumerators in unscoped enums that have names, even if they are not
scoped, we add the enum name to the scope so that users can find the
enumerators when fully qualifying them, for example: MyEnum::Enumerator.
This makes it more consistent with how the code is visually laid out.

Signed-off-by: Marc-Andre Laperle <marc-andre.lape...@ericsson.com>


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D47223

Files:
  clangd/index/SymbolCollector.cpp
  unittests/clangd/SymbolCollectorTests.cpp

Index: unittests/clangd/SymbolCollectorTests.cpp
===================================================================
--- unittests/clangd/SymbolCollectorTests.cpp
+++ unittests/clangd/SymbolCollectorTests.cpp
@@ -343,9 +343,9 @@
     }
   )";
   runSymbolCollector(Header, /*Main=*/"");
-  EXPECT_THAT(Symbols, UnorderedElementsAre(QName("Red"), QName("Color"),
-                                            QName("Green"), QName("Color2"),
-                                            QName("ns"), QName("ns::Black")));
+  EXPECT_THAT(Symbols, UnorderedElementsAre(
+                           QName("Red"), QName("Color"), QName("Color::Green"),
+                           QName("Color2"), QName("ns"), QName("ns::Black")));
 }
 
 TEST_F(SymbolCollectorTest, IgnoreNamelessSymbols) {
@@ -726,10 +726,10 @@
            bool operator<(const TopLevel &, const TopLevel &);
          })";
   runSymbolCollector(Header, /*Main=*/"");
-  EXPECT_THAT(Symbols,
-              UnorderedElementsAre(QName("nx"), QName("nx::TopLevel"),
-                                   QName("nx::Kind"), QName("nx::KIND_OK"),
-                                   QName("nx::operator<")));
+  EXPECT_THAT(Symbols, UnorderedElementsAre(QName("nx"), QName("nx::TopLevel"),
+                                            QName("nx::Kind"),
+                                            QName("nx::Kind::KIND_OK"),
+                                            QName("nx::operator<")));
 }
 
 TEST_F(SymbolCollectorTest, DoubleCheckProtoHeaderComment) {
@@ -743,9 +743,9 @@
   }
   )";
   runSymbolCollector(Header, /*Main=*/"");
-  EXPECT_THAT(Symbols,
-              UnorderedElementsAre(QName("nx"), QName("nx::Top_Level"),
-                                   QName("nx::Kind"), QName("nx::Kind_Fine")));
+  EXPECT_THAT(Symbols, UnorderedElementsAre(QName("nx"), QName("nx::Top_Level"),
+                                            QName("nx::Kind"),
+                                            QName("nx::Kind::Kind_Fine")));
 }
 
 } // namespace
Index: clangd/index/SymbolCollector.cpp
===================================================================
--- clangd/index/SymbolCollector.cpp
+++ clangd/index/SymbolCollector.cpp
@@ -264,6 +264,21 @@
          match(decl(isExpansionInMainFile()), ND, ND.getASTContext()).empty();
 }
 
+std::string getQualifiedName(const NamedDecl &ND) {
+  std::string QName;
+  llvm::raw_string_ostream OS(QName);
+  PrintingPolicy Policy(ND.getASTContext().getLangOpts());
+  // Note that inline namespaces are treated as transparent scopes. This
+  // reflects the way they're most commonly used for lookup. Ideally we'd
+  // include them, but at query time it's hard to find all the inline
+  // namespaces to query: the preamble doesn't have a dedicated list.
+  Policy.SuppressUnwrittenScope = true;
+  ND.printQualifiedName(OS, Policy);
+  OS.flush();
+  assert(!StringRef(QName).startswith("::"));
+  return QName;
+}
+
 } // namespace
 
 SymbolCollector::SymbolCollector(Options Opts) : Opts(std::move(Opts)) {}
@@ -341,21 +356,29 @@
   auto &Ctx = ND.getASTContext();
   auto &SM = Ctx.getSourceManager();
 
-  std::string QName;
-  llvm::raw_string_ostream OS(QName);
-  PrintingPolicy Policy(ASTCtx->getLangOpts());
-  // Note that inline namespaces are treated as transparent scopes. This
-  // reflects the way they're most commonly used for lookup. Ideally we'd
-  // include them, but at query time it's hard to find all the inline
-  // namespaces to query: the preamble doesn't have a dedicated list.
-  Policy.SuppressUnwrittenScope = true;
-  ND.printQualifiedName(OS, Policy);
-  OS.flush();
-  assert(!StringRef(QName).startswith("::"));
+  std::string QName = getQualifiedName(ND);
 
   Symbol S;
   S.ID = std::move(ID);
   std::tie(S.Scope, S.Name) = splitQualifiedName(QName);
+
+  using namespace clang::ast_matchers;
+  // For enumerators in unscoped enums that have names, even if they are not
+  // scoped, we add the enum name to the scope so that users can find the
+  // enumerators when fully qualifying them, for example: MyEnum::Enumerator.
+  auto InUnscopedEnum =
+      match(decl(hasDeclContext(enumDecl(unless(isScoped())).bind("enum"))), ND,
+            *ASTCtx);
+  std::string EnumQName;
+  if (!InUnscopedEnum.empty()) {
+    auto Enum = InUnscopedEnum[0].getNodeAs<EnumDecl>("enum");
+    if (Enum->getDeclName()) {
+      EnumQName = getQualifiedName(*Enum);
+      EnumQName += "::";
+      S.Scope = EnumQName;
+    }
+  }
+
   S.SymInfo = index::getSymbolInfo(&ND);
   std::string FileURI;
   if (auto DeclLoc =
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to