summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-doc/Serialize.cpp
diff options
context:
space:
mode:
authorJulie Hockett <juliehockett@google.com>2019-07-12 18:32:00 +0000
committerJulie Hockett <juliehockett@google.com>2019-07-12 18:32:00 +0000
commit2c1c9a240776e5ccfb29b8a22bb32bb7e87ac2dd (patch)
tree01de292be1b791cca0047d25e1bed39d62e13011 /clang-tools-extra/clang-doc/Serialize.cpp
parent13f7ddff17ba1f4c5a51c83af1c83cb501ad0653 (diff)
downloadbcm5719-llvm-2c1c9a240776e5ccfb29b8a22bb32bb7e87ac2dd.tar.gz
bcm5719-llvm-2c1c9a240776e5ccfb29b8a22bb32bb7e87ac2dd.zip
[clang-doc] Add html links to references
<a> tags are added for the parents and members of records and return type and params of functions. The link redirects to the reference's info file. The directory path where each info file will be saved is now generated in the serialization phase and stored as an attribute in each Info. Bitcode writer and reader were modified to handle the new attributes. Committed on behalf of Diego Astiazarán (diegoaat97@gmail.com). Differential Revision: https://reviews.llvm.org/D63663 llvm-svn: 365937
Diffstat (limited to 'clang-tools-extra/clang-doc/Serialize.cpp')
-rw-r--r--clang-tools-extra/clang-doc/Serialize.cpp192
1 files changed, 121 insertions, 71 deletions
diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp
index 4962fa04456..ed7f98a96a2 100644
--- a/clang-tools-extra/clang-doc/Serialize.cpp
+++ b/clang-tools-extra/clang-doc/Serialize.cpp
@@ -24,6 +24,43 @@ SymbolID hashUSR(llvm::StringRef USR) {
return llvm::SHA1::hash(arrayRefFromStringRef(USR));
}
+template <typename T>
+static void
+populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
+ const T *D, bool &IsAnonymousNamespace);
+
+// A function to extract the appropriate relative path for a given info's
+// documentation. The path returned is a composite of the parent namespaces.
+//
+// Example: Given the below, the diretory path for class C info will be
+// <root>/A/B
+//
+// namespace A {
+// namesapce B {
+//
+// class C {};
+//
+// }
+// }
+llvm::SmallString<128>
+getInfoRelativePath(const llvm::SmallVectorImpl<doc::Reference> &Namespaces) {
+ std::error_code OK;
+ llvm::SmallString<128> Path;
+ for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
+ llvm::sys::path::append(Path, R->Name);
+ return Path;
+}
+
+llvm::SmallString<128> getInfoRelativePath(const Decl *D) {
+ llvm::SmallVector<Reference, 4> Namespaces;
+ // The third arg in populateParentNamespaces is a boolean passed by reference,
+ // its value is not relevant in here so it's not used anywhere besides the
+ // function call
+ bool B = true;
+ populateParentNamespaces(Namespaces, D, B);
+ return getInfoRelativePath(Namespaces);
+}
+
class ClangDocCommentVisitor
: public ConstCommentVisitor<ClangDocCommentVisitor> {
public:
@@ -203,13 +240,13 @@ static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly) {
// valid, as opposed to an assert.
if (const auto *N = dyn_cast<EnumDecl>(T)) {
I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
- InfoType::IT_enum, F->getNameAsString(),
- N->getAccessUnsafe());
+ InfoType::IT_enum, getInfoRelativePath(N),
+ F->getNameAsString(), N->getAccessUnsafe());
continue;
} else if (const auto *N = dyn_cast<RecordDecl>(T)) {
I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
- InfoType::IT_record, F->getNameAsString(),
- N->getAccessUnsafe());
+ InfoType::IT_record, getInfoRelativePath(N),
+ F->getNameAsString(), N->getAccessUnsafe());
continue;
}
}
@@ -228,11 +265,13 @@ static void parseParameters(FunctionInfo &I, const FunctionDecl *D) {
if (const auto *T = getDeclForType(P->getOriginalType())) {
if (const auto *N = dyn_cast<EnumDecl>(T)) {
I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
- InfoType::IT_enum, P->getNameAsString());
+ InfoType::IT_enum, getInfoRelativePath(N),
+ P->getNameAsString());
continue;
} else if (const auto *N = dyn_cast<RecordDecl>(T)) {
I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
- InfoType::IT_record, P->getNameAsString());
+ InfoType::IT_record, getInfoRelativePath(N),
+ P->getNameAsString());
continue;
}
}
@@ -254,14 +293,15 @@ static void parseBases(RecordInfo &I, const CXXRecordDecl *D) {
InfoType::IT_record);
} else if (const RecordDecl *P = getDeclForType(B.getType()))
I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
- InfoType::IT_record);
+ InfoType::IT_record, getInfoRelativePath(P));
else
I.Parents.emplace_back(B.getType().getAsString());
}
for (const CXXBaseSpecifier &B : D->vbases()) {
if (const auto *P = getDeclForType(B.getType()))
I.VirtualParents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
- InfoType::IT_record);
+ InfoType::IT_record,
+ getInfoRelativePath(P));
else
I.VirtualParents.emplace_back(B.getType().getAsString());
}
@@ -270,14 +310,14 @@ static void parseBases(RecordInfo &I, const CXXRecordDecl *D) {
template <typename T>
static void
populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
- const T *D, bool &IsAnonymousNamespace) {
+ const T *D, bool &IsInAnonymousNamespace) {
const auto *DC = dyn_cast<DeclContext>(D);
while ((DC = DC->getParent())) {
if (const auto *N = dyn_cast<NamespaceDecl>(DC)) {
std::string Namespace;
if (N->isAnonymousNamespace()) {
Namespace = "@nonymous_namespace";
- IsAnonymousNamespace = true;
+ IsInAnonymousNamespace = true;
} else
Namespace = N->getNameAsString();
Namespaces.emplace_back(getUSRForDecl(N), Namespace,
@@ -324,11 +364,11 @@ static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
populateSymbolInfo(I, D, FC, LineNumber, Filename, IsInAnonymousNamespace);
if (const auto *T = getDeclForType(D->getReturnType())) {
if (dyn_cast<EnumDecl>(T))
- I.ReturnType =
- TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_enum);
+ I.ReturnType = TypeInfo(getUSRForDecl(T), T->getNameAsString(),
+ InfoType::IT_enum, getInfoRelativePath(T));
else if (dyn_cast<RecordDecl>(T))
- I.ReturnType =
- TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_record);
+ I.ReturnType = TypeInfo(getUSRForDecl(T), T->getNameAsString(),
+ InfoType::IT_record, getInfoRelativePath(T));
} else {
I.ReturnType = TypeInfo(D->getReturnType().getAsString());
}
@@ -347,16 +387,18 @@ emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber,
I->Name = D->isAnonymousNamespace()
? llvm::SmallString<16>("@nonymous_namespace")
: I->Name;
+ I->Path = getInfoRelativePath(I->Namespace);
if (I->Namespace.empty() && I->USR == SymbolID())
return {std::unique_ptr<Info>{std::move(I)}, nullptr};
- SymbolID ParentUSR = I->Namespace.empty() ? SymbolID() : I->Namespace[0].USR;
-
- auto Parent = llvm::make_unique<NamespaceInfo>();
- Parent->USR = ParentUSR;
- Parent->ChildNamespaces.emplace_back(I->USR, I->Name, InfoType::IT_namespace);
+ auto ParentI = llvm::make_unique<NamespaceInfo>();
+ ParentI->USR = I->Namespace.empty() ? SymbolID() : I->Namespace[0].USR;
+ ParentI->ChildNamespaces.emplace_back(I->USR, I->Name,
+ InfoType::IT_namespace);
+ if (I->Namespace.empty())
+ ParentI->Path = getInfoRelativePath(ParentI->Namespace);
return {std::unique_ptr<Info>{std::move(I)},
- std::unique_ptr<Info>{std::move(Parent)}};
+ std::unique_ptr<Info>{std::move(ParentI)}};
}
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
@@ -378,32 +420,34 @@ emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber,
}
parseBases(*I, C);
}
+ I->Path = getInfoRelativePath(I->Namespace);
if (I->Namespace.empty()) {
- auto Parent = llvm::make_unique<NamespaceInfo>();
- Parent->USR = SymbolID();
- Parent->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+ auto ParentI = llvm::make_unique<NamespaceInfo>();
+ ParentI->USR = SymbolID();
+ ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+ ParentI->Path = getInfoRelativePath(ParentI->Namespace);
return {std::unique_ptr<Info>{std::move(I)},
- std::unique_ptr<Info>{std::move(Parent)}};
+ std::unique_ptr<Info>{std::move(ParentI)}};
}
switch (I->Namespace[0].RefType) {
case InfoType::IT_namespace: {
- auto Parent = llvm::make_unique<NamespaceInfo>();
- Parent->USR = I->Namespace[0].USR;
- Parent->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+ auto ParentI = llvm::make_unique<NamespaceInfo>();
+ ParentI->USR = I->Namespace[0].USR;
+ ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
return {std::unique_ptr<Info>{std::move(I)},
- std::unique_ptr<Info>{std::move(Parent)}};
+ std::unique_ptr<Info>{std::move(ParentI)}};
}
case InfoType::IT_record: {
- auto Parent = llvm::make_unique<RecordInfo>();
- Parent->USR = I->Namespace[0].USR;
- Parent->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+ auto ParentI = llvm::make_unique<RecordInfo>();
+ ParentI->USR = I->Namespace[0].USR;
+ ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
return {std::unique_ptr<Info>{std::move(I)},
- std::unique_ptr<Info>{std::move(Parent)}};
+ std::unique_ptr<Info>{std::move(ParentI)}};
}
default:
- llvm_unreachable("Invalid reference type");
+ llvm_unreachable("Invalid reference type for parent namespace");
}
}
@@ -420,14 +464,16 @@ emitInfo(const FunctionDecl *D, const FullComment *FC, int LineNumber,
Func.Access = clang::AccessSpecifier::AS_none;
// Wrap in enclosing scope
- auto I = llvm::make_unique<NamespaceInfo>();
+ auto ParentI = llvm::make_unique<NamespaceInfo>();
if (!Func.Namespace.empty())
- I->USR = Func.Namespace[0].USR;
+ ParentI->USR = Func.Namespace[0].USR;
else
- I->USR = SymbolID();
- I->ChildFunctions.emplace_back(std::move(Func));
- // Info es wrapped in its parent scope so it's returned in the second position
- return {nullptr, std::unique_ptr<Info>{std::move(I)}};
+ ParentI->USR = SymbolID();
+ 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)}};
}
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
@@ -455,11 +501,13 @@ emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber,
Func.Access = D->getAccess();
// Wrap in enclosing scope
- auto I = llvm::make_unique<RecordInfo>();
- I->USR = ParentUSR;
- I->ChildFunctions.emplace_back(std::move(Func));
+ auto ParentI = llvm::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(I)}};
+ return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
}
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
@@ -475,36 +523,38 @@ emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber,
Enum.Scoped = D->isScoped();
parseEnumerators(Enum, D);
- // Wrap in enclosing scope
- if (!Enum.Namespace.empty()) {
- switch (Enum.Namespace[0].RefType) {
- case InfoType::IT_namespace: {
- auto I = llvm::make_unique<NamespaceInfo>();
- I->USR = Enum.Namespace[0].USR;
- I->ChildEnums.emplace_back(std::move(Enum));
- // Info is wrapped in its parent scope so it's returned in the second
- // position
- return {nullptr, std::unique_ptr<Info>{std::move(I)}};
- }
- case InfoType::IT_record: {
- auto I = llvm::make_unique<RecordInfo>();
- I->USR = Enum.Namespace[0].USR;
- I->ChildEnums.emplace_back(std::move(Enum));
- // Info is wrapped in its parent scope so it's returned in the second
- // position
- return {nullptr, std::unique_ptr<Info>{std::move(I)}};
- }
- default:
- break;
- }
+ // Put in global namespace
+ if (Enum.Namespace.empty()) {
+ auto ParentI = llvm::make_unique<NamespaceInfo>();
+ ParentI->USR = SymbolID();
+ ParentI->ChildEnums.emplace_back(std::move(Enum));
+ ParentI->Path = getInfoRelativePath(ParentI->Namespace);
+ // Info is wrapped in its parent scope so it's returned in the second
+ // position
+ return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
}
- // Put in global namespace
- auto I = llvm::make_unique<NamespaceInfo>();
- I->USR = SymbolID();
- I->ChildEnums.emplace_back(std::move(Enum));
- // Info is wrapped in its parent scope so it's returned in the second position
- return {nullptr, std::unique_ptr<Info>{std::move(I)}};
+ // Wrap in enclosing scope
+ switch (Enum.Namespace[0].RefType) {
+ case InfoType::IT_namespace: {
+ auto ParentI = llvm::make_unique<NamespaceInfo>();
+ ParentI->USR = Enum.Namespace[0].USR;
+ ParentI->ChildEnums.emplace_back(std::move(Enum));
+ // Info is wrapped in its parent scope so it's returned in the second
+ // position
+ return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
+ }
+ case InfoType::IT_record: {
+ auto ParentI = llvm::make_unique<RecordInfo>();
+ ParentI->USR = Enum.Namespace[0].USR;
+ ParentI->ChildEnums.emplace_back(std::move(Enum));
+ // Info is wrapped in its parent scope so it's returned in the second
+ // position
+ return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
+ }
+ default:
+ llvm_unreachable("Invalid reference type for parent namespace");
+ }
}
} // namespace serialize
OpenPOWER on IntegriCloud