DiegoAstiazaran created this revision.
DiegoAstiazaran added reviewers: juliehockett, jakehehrlich.
DiegoAstiazaran added a project: clang-tools-extra.

When a Record is declared in the global namespace, clang-doc serializes it as a 
child of the global namespace, so the global namespace is now one if its parent 
namespaces. This namespace was not being included in the list of namespaces of 
the Info causing paths to be incorrect and the index rendered incorrectly.
Affected tests have been fixed.


https://reviews.llvm.org/D66298

Files:
  clang-tools-extra/clang-doc/Serialize.cpp
  clang-tools-extra/test/clang-doc/single-file-public.cpp
  clang-tools-extra/unittests/clang-doc/SerializeTest.cpp

Index: clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
+++ clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
@@ -136,7 +136,9 @@
                        10, /*Public=*/false, Infos);
 
   RecordInfo *E = InfoAsRecord(Infos[0].get());
-  RecordInfo ExpectedE(EmptySID, "E");
+  RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
+  ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+                                   InfoType::IT_namespace);
   ExpectedE.TagType = TagTypeKind::TTK_Class;
   ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
   CheckRecordInfo(&ExpectedE, E);
@@ -149,6 +151,8 @@
   EConstructor.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
   EConstructor.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
   EConstructor.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
+  EConstructor.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+                                      InfoType::IT_namespace);
   EConstructor.Access = AccessSpecifier::AS_public;
   EConstructor.IsMethod = true;
   ExpectedRecordWithEConstructor.ChildFunctions.emplace_back(
@@ -163,13 +167,17 @@
   Method.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
   Method.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
   Method.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
+  Method.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+                                InfoType::IT_namespace);
   Method.Access = AccessSpecifier::AS_protected;
   Method.IsMethod = true;
   ExpectedRecordWithMethod.ChildFunctions.emplace_back(std::move(Method));
   CheckRecordInfo(&ExpectedRecordWithMethod, RecordWithMethod);
 
   RecordInfo *F = InfoAsRecord(Infos[4].get());
-  RecordInfo ExpectedF(EmptySID, "F");
+  RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
+  ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+                                   InfoType::IT_namespace);
   ExpectedF.TagType = TagTypeKind::TTK_Struct;
   ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
   CheckRecordInfo(&ExpectedF, F);
@@ -182,6 +190,8 @@
   TemplateMethod.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
   TemplateMethod.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
   TemplateMethod.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
+  TemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+                                        InfoType::IT_namespace);
   TemplateMethod.Access = AccessSpecifier::AS_public;
   TemplateMethod.IsMethod = true;
   ExpectedRecordWithTemplateMethod.ChildFunctions.emplace_back(
@@ -200,6 +210,8 @@
                                              llvm::SmallString<16>{"test.cpp"});
   SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "F",
                                                    InfoType::IT_record);
+  SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+                                                   InfoType::IT_namespace);
   SpecializedTemplateMethod.Access = AccessSpecifier::AS_public;
   SpecializedTemplateMethod.IsMethod = true;
   ExpectedTemplatedRecord.ChildFunctions.emplace_back(
@@ -207,7 +219,9 @@
   CheckRecordInfo(&ExpectedTemplatedRecord, TemplatedRecord);
 
   RecordInfo *G = InfoAsRecord(Infos[8].get());
-  RecordInfo ExpectedG(EmptySID, "G");
+  RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
+  ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+                                   InfoType::IT_namespace);
   ExpectedG.TagType = TagTypeKind::TTK_Struct;
   ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
   ExpectedG.IsTypeDef = true;
@@ -247,7 +261,9 @@
   ExtractInfosFromCode("class E;", 2, /*Public=*/false, Infos);
 
   RecordInfo *E = InfoAsRecord(Infos[0].get());
-  RecordInfo ExpectedE(EmptySID, "E");
+  RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
+  ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+                                   InfoType::IT_namespace);
   ExpectedE.TagType = TagTypeKind::TTK_Class;
   ExpectedE.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
   CheckRecordInfo(&ExpectedE, E);
@@ -258,7 +274,9 @@
   ExtractInfosFromCode("struct E { int I; };", 2, /*Public=*/false, Infos);
 
   RecordInfo *E = InfoAsRecord(Infos[0].get());
-  RecordInfo ExpectedE(EmptySID, "E");
+  RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
+  ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+                                   InfoType::IT_namespace);
   ExpectedE.TagType = TagTypeKind::TTK_Struct;
   ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
   ExpectedE.Members.emplace_back("int", "I", AccessSpecifier::AS_public);
@@ -270,16 +288,20 @@
   ExtractInfosFromCode("class E { class G {}; };", 4, /*Public=*/false, Infos);
 
   RecordInfo *E = InfoAsRecord(Infos[0].get());
-  RecordInfo ExpectedE(EmptySID, "E");
+  RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
+  ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+                                   InfoType::IT_namespace);
   ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
   ExpectedE.TagType = TagTypeKind::TTK_Class;
   CheckRecordInfo(&ExpectedE, E);
 
   RecordInfo *G = InfoAsRecord(Infos[2].get());
-  RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"E");
+  RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace/E");
   ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
   ExpectedG.TagType = TagTypeKind::TTK_Class;
   ExpectedG.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
+  ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+                                   InfoType::IT_namespace);
   CheckRecordInfo(&ExpectedG, G);
 }
 
@@ -402,13 +424,14 @@
 
   NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
   NamespaceInfo ExpectedParentA(EmptySID);
-  ExpectedParentA.ChildRecords.emplace_back(EmptySID, "A", InfoType::IT_record);
+  ExpectedParentA.ChildRecords.emplace_back(EmptySID, "A", InfoType::IT_record,
+                                            "GlobalNamespace");
   CheckNamespaceInfo(&ExpectedParentA, ParentA);
 
   RecordInfo *ParentB = InfoAsRecord(Infos[3].get());
   RecordInfo ExpectedParentB(EmptySID);
   ExpectedParentB.ChildRecords.emplace_back(EmptySID, "B", InfoType::IT_record,
-                                            "A");
+                                            "GlobalNamespace/A");
   CheckRecordInfo(&ExpectedParentB, ParentB);
 
   NamespaceInfo *ParentC = InfoAsNamespace(Infos[7].get());
Index: clang-tools-extra/test/clang-doc/single-file-public.cpp
===================================================================
--- clang-tools-extra/test/clang-doc/single-file-public.cpp
+++ clang-tools-extra/test/clang-doc/single-file-public.cpp
@@ -3,7 +3,7 @@
 // RUN: echo "" > %t/compile_flags.txt
 // RUN: cp "%s" "%t/test.cpp"
 // RUN: clang-doc --doxygen --public --executor=standalone -p %t %t/test.cpp -output=%t/docs
-// RUN: cat %t/docs/Record.yaml | FileCheck %s --check-prefix=CHECK
+// RUN: cat %t/docs/GlobalNamespace/Record.yaml | FileCheck %s --check-prefix=CHECK
 // RUN: rm -rf %t
 
 class Record {
@@ -21,8 +21,12 @@
 // CHECK: ---
 // CHECK-NEXT: USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
 // CHECK-NEXT: Name:            'Record'
+// CHECK-NEXT: Path:            'GlobalNamespace'
+// CHECK-NEXT: Namespace:
+// CHECK-NEXT:   - Type:             Namespace
+// CHECK-NEXT:     Name:             'GlobalNamespace'
 // CHECK-NEXT: DefLocation:
-// CHECK-NEXT:   LineNumber:      [[@LINE-16]]
+// CHECK-NEXT:   LineNumber:      [[@LINE-20]]
 // CHECK-NEXT:   Filename:        '{{.*}}'
 // CHECK-NEXT: TagType:         Class
 // CHECK-NEXT: ChildFunctions:
@@ -32,11 +36,13 @@
 // CHECK-NEXT:       - Type:            Record
 // CHECK-NEXT:         Name:            'Record'
 // CHECK-NEXT:         USR:             '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}'
+// CHECK-NEXT:       - Type:            Namespace
+// CHECK-NEXT:         Name:            'GlobalNamespace'
 // CHECK-NEXT:     DefLocation:
-// CHECK-NEXT:         LineNumber:      [[@LINE-17]]
+// CHECK-NEXT:         LineNumber:      [[@LINE-23]]
 // CHECK-NEXT:         Filename:        '{{.*}}'
 // CHECK-NEXT:     Location:
-// CHECK-NEXT:       - LineNumber:      [[@LINE-25]]
+// CHECK-NEXT:       - LineNumber:      [[@LINE-31]]
 // CHECK-NEXT:         Filename:        '{{.*}}'
 // CHECK-NEXT:     IsMethod:        true
 // CHECK-NEXT:     Parent:
Index: clang-tools-extra/clang-doc/Serialize.cpp
===================================================================
--- clang-tools-extra/clang-doc/Serialize.cpp
+++ clang-tools-extra/clang-doc/Serialize.cpp
@@ -331,6 +331,14 @@
       Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                               InfoType::IT_enum);
   }
+  // The global namespace should be added to the list of namespaces if the decl
+  // corresponds to a Record and if it doesn't have any namespace (because this
+  // means it's in the global namespace). Also if its outermost namespace is a
+  // record because that record matches the previous condition mentioned.
+  if ((Namespaces.empty() && dyn_cast<RecordDecl>(D)) ||
+      (!Namespaces.empty() && Namespaces.back().RefType == InfoType::IT_record))
+    Namespaces.emplace_back(SymbolID(), "GlobalNamespace",
+                            InfoType::IT_namespace);
 }
 
 template <typename T>
@@ -424,16 +432,6 @@
   }
   I->Path = getInfoRelativePath(I->Namespace);
 
-  if (I->Namespace.empty()) {
-    auto ParentI = std::make_unique<NamespaceInfo>();
-    ParentI->USR = SymbolID();
-    ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record,
-                                       getInfoRelativePath(I->Namespace));
-    ParentI->Path = getInfoRelativePath(ParentI->Namespace);
-    return {std::unique_ptr<Info>{std::move(I)},
-            std::unique_ptr<Info>{std::move(ParentI)}};
-  }
-
   switch (I->Namespace[0].RefType) {
   case InfoType::IT_namespace: {
     auto ParentI = std::make_unique<NamespaceInfo>();
@@ -510,8 +508,6 @@
   // Wrap in enclosing scope
   auto ParentI = std::make_unique<RecordInfo>();
   ParentI->USR = ParentUSR;
-  if (Func.Namespace.empty())
-    ParentI->Path = getInfoRelativePath(ParentI->Namespace);
   ParentI->ChildFunctions.emplace_back(std::move(Func));
   // Info is wrapped in its parent scope so it's returned in the second position
   return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to