[clang] 529e912 - [clang][doc]: Merge entries with duplicate content. (#134089)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 7 11:43:01 PDT 2025
Author: YLChenZ
Date: 2025-04-07T14:42:57-04:00
New Revision: 529e9127f0d61f177f2c62ade531d876cf89bf59
URL: https://github.com/llvm/llvm-project/commit/529e9127f0d61f177f2c62ade531d876cf89bf59
DIFF: https://github.com/llvm/llvm-project/commit/529e9127f0d61f177f2c62ade531d876cf89bf59.diff
LOG: [clang][doc]: Merge entries with duplicate content. (#134089)
Before the patch:

after the patch:

Fixes #133706
Added:
Modified:
clang/utils/TableGen/ClangAttrEmitter.cpp
Removed:
################################################################################
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 06f6b073240ba..07844c8f0967b 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -5144,6 +5144,14 @@ class SpellingList {
Spellings[(size_t)Kind].push_back(Name);
}
+
+ void merge(const SpellingList &Other) {
+ for (size_t Kind = 0; Kind < NumSpellingKinds; ++Kind) {
+ Spellings[Kind].insert(Spellings[Kind].end(),
+ Other.Spellings[Kind].begin(),
+ Other.Spellings[Kind].end());
+ }
+ }
};
class DocumentationData {
@@ -5301,31 +5309,89 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
return L->getValueAsString("Name") < R->getValueAsString("Name");
}
};
- std::map<const Record *, std::vector<DocumentationData>, CategoryLess>
- SplitDocs;
+
+ std::map<const Record *, std::map<uint32_t, DocumentationData>, CategoryLess>
+ MergedDocs;
+
+ std::vector<DocumentationData> UndocumentedDocs;
+ const Record *UndocumentedCategory = nullptr;
+
+ // Collect documentation data, grouping by category and heading.
for (const auto *A : Records.getAllDerivedDefinitions("Attr")) {
const Record &Attr = *A;
std::vector<const Record *> Docs =
Attr.getValueAsListOfDefs("Documentation");
+
for (const auto *D : Docs) {
const Record &Doc = *D;
const Record *Category = Doc.getValueAsDef("Category");
// If the category is "InternalOnly", then there cannot be any other
// documentation categories (otherwise, the attribute would be
// emitted into the docs).
- const StringRef Cat = Category->getValueAsString("Name");
- bool InternalOnly = Cat == "InternalOnly";
- if (InternalOnly && Docs.size() > 1)
+ StringRef Cat = Category->getValueAsString("Name");
+ if (Cat == "InternalOnly" && Docs.size() > 1)
PrintFatalError(Doc.getLoc(),
"Attribute is \"InternalOnly\", but has multiple "
"documentation categories");
- if (!InternalOnly)
- SplitDocs[Category].push_back(DocumentationData(
- Doc, Attr, GetAttributeHeadingAndSpellings(Doc, Attr, Cat)));
+ if (Cat == "InternalOnly")
+ continue;
+
+ // Track the Undocumented category Record for later grouping
+ if (Cat == "Undocumented" && !UndocumentedCategory)
+ UndocumentedCategory = Category;
+
+ // Generate Heading and Spellings.
+ auto HeadingAndSpellings =
+ GetAttributeHeadingAndSpellings(Doc, Attr, Cat);
+
+ // Handle Undocumented category separately - no content merging
+ if (Cat == "Undocumented" && UndocumentedCategory) {
+ UndocumentedDocs.push_back(
+ DocumentationData(Doc, Attr, HeadingAndSpellings));
+ continue;
+ }
+
+ auto &CategoryDocs = MergedDocs[Category];
+
+ std::string key = Doc.getValueAsString("Content").str();
+ uint32_t keyHash = llvm::hash_value(key);
+
+ // If the content already exists, merge the documentation.
+ auto It = CategoryDocs.find(keyHash);
+ if (It != CategoryDocs.end()) {
+ // Merge heading
+ if (It->second.Heading != HeadingAndSpellings.first)
+ It->second.Heading += ", " + HeadingAndSpellings.first;
+ // Merge spellings
+ It->second.SupportedSpellings.merge(HeadingAndSpellings.second);
+ // Merge content
+ It->second.Documentation = &Doc; // Update reference
+ } else {
+ // Create new entry for unique content
+ CategoryDocs.emplace(keyHash,
+ DocumentationData(Doc, Attr, HeadingAndSpellings));
+ }
}
}
+ std::map<const Record *, std::vector<DocumentationData>, CategoryLess>
+ SplitDocs;
+
+ for (auto &CategoryPair : MergedDocs) {
+
+ std::vector<DocumentationData> MD;
+ for (auto &DocPair : CategoryPair.second)
+ MD.push_back(std::move(DocPair.second));
+
+ SplitDocs.emplace(CategoryPair.first, MD);
+ }
+
+ // Append Undocumented category entries
+ if (!UndocumentedDocs.empty() && UndocumentedCategory) {
+ SplitDocs.emplace(UndocumentedCategory, UndocumentedDocs);
+ }
+
// Having split the attributes out based on what documentation goes where,
// we can begin to generate sections of documentation.
for (auto &I : SplitDocs) {
More information about the cfe-commits
mailing list