[clang-doc] Fix records in global namespace
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.
Differential revision: https://reviews.llvm.org/D66298
git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@369123 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/clang-doc/Serialize.cpp b/clang-doc/Serialize.cpp
index 559bc12..38ac576 100644
--- a/clang-doc/Serialize.cpp
+++ b/clang-doc/Serialize.cpp
@@ -378,6 +378,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>
@@ -528,16 +536,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>();
@@ -611,8 +609,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)}};
diff --git a/test/clang-doc/single-file-public.cpp b/test/clang-doc/single-file-public.cpp
index 86a1f04..20cf18c 100644
--- a/test/clang-doc/single-file-public.cpp
+++ b/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:
diff --git a/unittests/clang-doc/SerializeTest.cpp b/unittests/clang-doc/SerializeTest.cpp
index 9c804ee..b846f0a 100644
--- a/unittests/clang-doc/SerializeTest.cpp
+++ b/unittests/clang-doc/SerializeTest.cpp
@@ -137,7 +137,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);
@@ -150,6 +152,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(
@@ -164,13 +168,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);
@@ -183,6 +191,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(
@@ -201,6 +211,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(
@@ -208,7 +220,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;
@@ -248,7 +262,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);
@@ -259,7 +275,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);
@@ -271,16 +289,22 @@
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");
+ llvm::SmallString<128> ExpectedGPath("GlobalNamespace/E");
+ llvm::sys::path::native(ExpectedGPath);
+ RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/ExpectedGPath);
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);
}
@@ -333,23 +357,32 @@
14, /*Public=*/false, Infos);
RecordInfo *F = InfoAsRecord(Infos[0].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_Class;
ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
CheckRecordInfo(&ExpectedF, F);
RecordInfo *G = InfoAsRecord(Infos[3].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_Class;
ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
ExpectedG.Members.emplace_back("int", "I", AccessSpecifier::AS_protected);
CheckRecordInfo(&ExpectedG, G);
RecordInfo *E = InfoAsRecord(Infos[6].get());
- RecordInfo ExpectedE(EmptySID, "E");
- ExpectedE.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
- ExpectedE.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
- ExpectedE.Bases.emplace_back(EmptySID, "F", "", false,
+ RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
+ ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+ InfoType::IT_namespace);
+ ExpectedE.Parents.emplace_back(EmptySID, /*Name=*/"F", InfoType::IT_record,
+ /*Path*=*/"GlobalNamespace");
+ ExpectedE.VirtualParents.emplace_back(
+ EmptySID, /*Name=*/"G", InfoType::IT_record, /*Path*=*/"GlobalNamespace");
+ ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"F",
+ /*Path=*/"GlobalNamespace", false,
AccessSpecifier::AS_public, true);
FunctionInfo FunctionSet;
FunctionSet.Name = "set";
@@ -357,16 +390,21 @@
FunctionSet.Loc.emplace_back();
FunctionSet.Params.emplace_back("int", "N");
FunctionSet.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
+ FunctionSet.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+ InfoType::IT_namespace);
FunctionSet.Access = AccessSpecifier::AS_protected;
FunctionSet.IsMethod = true;
ExpectedE.Bases.back().ChildFunctions.emplace_back(std::move(FunctionSet));
- ExpectedE.Bases.emplace_back(EmptySID, "G", "", true,
+ ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"G",
+ /*Path=*/"GlobalNamespace", true,
AccessSpecifier::AS_private, true);
FunctionInfo FunctionGet;
FunctionGet.Name = "get";
FunctionGet.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default);
FunctionGet.DefLoc = Location();
FunctionGet.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
+ FunctionGet.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+ InfoType::IT_namespace);
FunctionGet.Access = AccessSpecifier::AS_private;
FunctionGet.IsMethod = true;
ExpectedE.Bases.back().ChildFunctions.emplace_back(std::move(FunctionGet));
@@ -377,14 +415,20 @@
CheckRecordInfo(&ExpectedE, E);
RecordInfo *H = InfoAsRecord(Infos[8].get());
- RecordInfo ExpectedH(EmptySID, "H");
+ RecordInfo ExpectedH(EmptySID, /*Name=*/"H", /*Path=*/"GlobalNamespace");
+ ExpectedH.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+ InfoType::IT_namespace);
ExpectedH.TagType = TagTypeKind::TTK_Class;
ExpectedH.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
- ExpectedH.Parents.emplace_back(EmptySID, "E", InfoType::IT_record);
- ExpectedH.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
- ExpectedH.Bases.emplace_back(EmptySID, "E", "", false,
+ ExpectedH.Parents.emplace_back(EmptySID, /*Name=*/"E", InfoType::IT_record,
+ /*Path=*/"GlobalNamespace");
+ ExpectedH.VirtualParents.emplace_back(
+ EmptySID, /*Name=*/"G", InfoType::IT_record, /*Path=*/"GlobalNamespace");
+ ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"E",
+ /*Path=*/"GlobalNamespace", false,
AccessSpecifier::AS_private, true);
- ExpectedH.Bases.emplace_back(EmptySID, "F", "", false,
+ ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"F",
+ /*Path=*/"GlobalNamespace", false,
AccessSpecifier::AS_private, false);
FunctionInfo FunctionSetNew;
FunctionSetNew.Name = "set";
@@ -392,16 +436,21 @@
FunctionSetNew.Loc.emplace_back();
FunctionSetNew.Params.emplace_back("int", "N");
FunctionSetNew.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
+ FunctionSetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+ InfoType::IT_namespace);
FunctionSetNew.Access = AccessSpecifier::AS_private;
FunctionSetNew.IsMethod = true;
ExpectedH.Bases.back().ChildFunctions.emplace_back(std::move(FunctionSetNew));
- ExpectedH.Bases.emplace_back(EmptySID, "G", "", true,
+ ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"G",
+ /*Path=*/"GlobalNamespace", true,
AccessSpecifier::AS_private, false);
FunctionInfo FunctionGetNew;
FunctionGetNew.Name = "get";
FunctionGetNew.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default);
FunctionGetNew.DefLoc = Location();
FunctionGetNew.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
+ FunctionGetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+ InfoType::IT_namespace);
FunctionGetNew.Access = AccessSpecifier::AS_private;
FunctionGetNew.IsMethod = true;
ExpectedH.Bases.back().ChildFunctions.emplace_back(std::move(FunctionGetNew));
@@ -410,15 +459,21 @@
CheckRecordInfo(&ExpectedH, H);
RecordInfo *I = InfoAsRecord(Infos[10].get());
- RecordInfo ExpectedI(EmptySID, "I");
+ RecordInfo ExpectedI(EmptySID, /*Name=*/"I", /*Path=*/"GlobalNamespace");
+ ExpectedI.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+ InfoType::IT_namespace);
ExpectedI.TagType = TagTypeKind::TTK_Class;
ExpectedI.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
CheckRecordInfo(&ExpectedI, I);
RecordInfo *J = InfoAsRecord(Infos[12].get());
- RecordInfo ExpectedJ(EmptySID, "J");
- ExpectedJ.Parents.emplace_back(EmptySID, "I<int>", InfoType::IT_record);
- ExpectedJ.Bases.emplace_back(EmptySID, "I<int>", "", false,
+ RecordInfo ExpectedJ(EmptySID, /*Name=*/"J", /*Path=*/"GlobalNamespace");
+ ExpectedJ.Namespace.emplace_back(EmptySID, "GlobalNamespace",
+ InfoType::IT_namespace);
+ ExpectedJ.Parents.emplace_back(EmptySID, /*Name=*/"I<int>",
+ InfoType::IT_record);
+ ExpectedJ.Bases.emplace_back(EmptySID, /*Name=*/"I<int>",
+ /*Path=*/"GlobalNamespace", false,
AccessSpecifier::AS_public, true);
ExpectedJ.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
ExpectedJ.TagType = TagTypeKind::TTK_Class;
@@ -467,13 +522,16 @@
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);
+ llvm::SmallString<128> ExpectedParentBPath("GlobalNamespace/A");
+ llvm::sys::path::native(ExpectedParentBPath);
ExpectedParentB.ChildRecords.emplace_back(EmptySID, "B", InfoType::IT_record,
- "A");
+ ExpectedParentBPath);
CheckRecordInfo(&ExpectedParentB, ParentB);
NamespaceInfo *ParentC = InfoAsNamespace(Infos[7].get());