summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-doc/Representation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-doc/Representation.cpp')
-rw-r--r--clang-tools-extra/clang-doc/Representation.cpp72
1 files changed, 67 insertions, 5 deletions
diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp
index 6107b98ecdc..eacf11a8509 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -26,17 +26,70 @@
namespace clang {
namespace doc {
-static const SymbolID EmptySID = SymbolID();
+namespace {
+
+const SymbolID EmptySID = SymbolID();
template <typename T>
-std::unique_ptr<Info> reduce(std::vector<std::unique_ptr<Info>> &Values) {
- std::unique_ptr<Info> Merged = llvm::make_unique<T>();
+llvm::Expected<std::unique_ptr<Info>>
+reduce(std::vector<std::unique_ptr<Info>> &Values) {
+ if (Values.empty())
+ return llvm::make_error<llvm::StringError>(" No values to reduce.\n",
+ llvm::inconvertibleErrorCode());
+ std::unique_ptr<Info> Merged = llvm::make_unique<T>(Values[0]->USR);
T *Tmp = static_cast<T *>(Merged.get());
for (auto &I : Values)
Tmp->merge(std::move(*static_cast<T *>(I.get())));
- return Merged;
+ return std::move(Merged);
+}
+
+// Return the index of the matching child in the vector, or -1 if merge is not
+// necessary.
+template <typename T>
+int getChildIndexIfExists(std::vector<T> &Children, T &ChildToMerge) {
+ for (unsigned long I = 0; I < Children.size(); I++) {
+ if (ChildToMerge.USR == Children[I].USR)
+ return I;
+ }
+ return -1;
+}
+
+// For References, we don't need to actually merge them, we just don't want
+// duplicates.
+void reduceChildren(std::vector<Reference> &Children,
+ std::vector<Reference> &&ChildrenToMerge) {
+ for (auto &ChildToMerge : ChildrenToMerge) {
+ if (getChildIndexIfExists(Children, ChildToMerge) == -1)
+ Children.push_back(std::move(ChildToMerge));
+ }
+}
+
+void reduceChildren(std::vector<FunctionInfo> &Children,
+ std::vector<FunctionInfo> &&ChildrenToMerge) {
+ for (auto &ChildToMerge : ChildrenToMerge) {
+ int mergeIdx = getChildIndexIfExists(Children, ChildToMerge);
+ if (mergeIdx == -1) {
+ Children.push_back(std::move(ChildToMerge));
+ continue;
+ }
+ Children[mergeIdx].merge(std::move(ChildToMerge));
+ }
}
+void reduceChildren(std::vector<EnumInfo> &Children,
+ std::vector<EnumInfo> &&ChildrenToMerge) {
+ for (auto &ChildToMerge : ChildrenToMerge) {
+ int mergeIdx = getChildIndexIfExists(Children, ChildToMerge);
+ if (mergeIdx == -1) {
+ Children.push_back(std::move(ChildToMerge));
+ continue;
+ }
+ Children[mergeIdx].merge(std::move(ChildToMerge));
+ }
+}
+
+} // namespace
+
// Dispatch function.
llvm::Expected<std::unique_ptr<Info>>
mergeInfos(std::vector<std::unique_ptr<Info>> &Values) {
@@ -73,7 +126,7 @@ void Info::mergeBase(Info &&Other) {
}
bool Info::mergeable(const Info &Other) {
- return IT == Other.IT && (USR == EmptySID || USR == Other.USR);
+ return IT == Other.IT && USR == Other.USR;
}
void SymbolInfo::merge(SymbolInfo &&Other) {
@@ -87,6 +140,11 @@ void SymbolInfo::merge(SymbolInfo &&Other) {
void NamespaceInfo::merge(NamespaceInfo &&Other) {
assert(mergeable(Other));
+ // Reduce children if necessary.
+ reduceChildren(ChildNamespaces, std::move(Other.ChildNamespaces));
+ reduceChildren(ChildRecords, std::move(Other.ChildRecords));
+ reduceChildren(ChildFunctions, std::move(Other.ChildFunctions));
+ reduceChildren(ChildEnums, std::move(Other.ChildEnums));
mergeBase(std::move(Other));
}
@@ -100,6 +158,10 @@ void RecordInfo::merge(RecordInfo &&Other) {
Parents = std::move(Other.Parents);
if (VirtualParents.empty())
VirtualParents = std::move(Other.VirtualParents);
+ // Reduce children if necessary.
+ reduceChildren(ChildRecords, std::move(Other.ChildRecords));
+ reduceChildren(ChildFunctions, std::move(Other.ChildFunctions));
+ reduceChildren(ChildEnums, std::move(Other.ChildEnums));
SymbolInfo::merge(std::move(Other));
}
OpenPOWER on IntegriCloud