Skip to content

Commit ac1c7b5

Browse files
committed
[clang-doc] add suport for clang-doc enum generation
1 parent 03e1eb2 commit ac1c7b5

File tree

7 files changed

+181
-46
lines changed

7 files changed

+181
-46
lines changed

clang-tools-extra/clang-doc/BitcodeReader.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,10 @@ template <> llvm::Expected<CommentInfo *> getCommentInfo(TypedefInfo *I) {
415415
return &I->Description.emplace_back();
416416
}
417417

418+
template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumValueInfo *I) {
419+
return &I->Description.emplace_back();
420+
}
421+
418422
template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) {
419423
I->Children.emplace_back(std::make_unique<CommentInfo>());
420424
return I->Children.back().get();

clang-tools-extra/clang-doc/BitcodeWriter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,8 @@ void ClangDocBitcodeWriter::emitBlock(const EnumValueInfo &I) {
536536
emitRecord(I.Name, ENUM_VALUE_NAME);
537537
emitRecord(I.Value, ENUM_VALUE_VALUE);
538538
emitRecord(I.ValueExpr, ENUM_VALUE_EXPR);
539+
for (const auto &CI : I.Description)
540+
emitBlock(CI);
539541
}
540542

541543
void ClangDocBitcodeWriter::emitBlock(const RecordInfo &I) {

clang-tools-extra/clang-doc/HTMLGenerator.cpp

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ class HTMLTag {
4848
TAG_SPAN,
4949
TAG_TITLE,
5050
TAG_UL,
51+
TAG_TABLE,
52+
TAG_THEAD,
53+
TAG_TBODY,
54+
TAG_TR,
55+
TAG_TD,
56+
TAG_TH
5157
};
5258

5359
HTMLTag() = default;
@@ -133,6 +139,12 @@ bool HTMLTag::isSelfClosing() const {
133139
case HTMLTag::TAG_SPAN:
134140
case HTMLTag::TAG_TITLE:
135141
case HTMLTag::TAG_UL:
142+
case HTMLTag::TAG_TABLE:
143+
case HTMLTag::TAG_THEAD:
144+
case HTMLTag::TAG_TBODY:
145+
case HTMLTag::TAG_TR:
146+
case HTMLTag::TAG_TD:
147+
case HTMLTag::TAG_TH:
136148
return false;
137149
}
138150
llvm_unreachable("Unhandled HTMLTag::TagType");
@@ -174,6 +186,18 @@ StringRef HTMLTag::toString() const {
174186
return "title";
175187
case HTMLTag::TAG_UL:
176188
return "ul";
189+
case HTMLTag::TAG_TABLE:
190+
return "table";
191+
case HTMLTag::TAG_THEAD:
192+
return "thead";
193+
case HTMLTag::TAG_TBODY:
194+
return "tbody";
195+
case HTMLTag::TAG_TR:
196+
return "tr";
197+
case HTMLTag::TAG_TD:
198+
return "td";
199+
case HTMLTag::TAG_TH:
200+
return "th";
177201
}
178202
llvm_unreachable("Unhandled HTMLTag::TagType");
179203
}
@@ -352,6 +376,7 @@ genHTML(const EnumInfo &I, const ClangDocContext &CDCtx);
352376
static std::vector<std::unique_ptr<TagNode>>
353377
genHTML(const FunctionInfo &I, const ClangDocContext &CDCtx,
354378
StringRef ParentInfoDir);
379+
static std::unique_ptr<TagNode> genHTML(const std::vector<CommentInfo> &C);
355380

356381
static std::vector<std::unique_ptr<TagNode>>
357382
genEnumsBlock(const std::vector<EnumInfo> &Enums,
@@ -372,14 +397,33 @@ genEnumsBlock(const std::vector<EnumInfo> &Enums,
372397
}
373398

374399
static std::unique_ptr<TagNode>
375-
genEnumMembersBlock(const llvm::SmallVector<EnumValueInfo, 4> &Members) {
400+
genEnumMembersBlock(const llvm::SmallVector<EnumValueInfo, 4> &Members,
401+
bool HasComments) {
376402
if (Members.empty())
377403
return nullptr;
378404

379-
auto List = std::make_unique<TagNode>(HTMLTag::TAG_UL);
380-
for (const auto &M : Members)
381-
List->Children.emplace_back(
382-
std::make_unique<TagNode>(HTMLTag::TAG_LI, M.Name));
405+
auto List = std::make_unique<TagNode>(HTMLTag::TAG_TBODY);
406+
407+
for (const auto &M : Members) {
408+
auto TRNode = std::make_unique<TagNode>(HTMLTag::TAG_TR);
409+
TRNode->Children.emplace_back(
410+
std::make_unique<TagNode>(HTMLTag::TAG_TD, M.Name));
411+
// Use user supplied value if it exists, otherwise use the value
412+
if (!M.ValueExpr.empty()) {
413+
TRNode->Children.emplace_back(
414+
std::make_unique<TagNode>(HTMLTag::TAG_TD, M.ValueExpr));
415+
} else {
416+
TRNode->Children.emplace_back(
417+
std::make_unique<TagNode>(HTMLTag::TAG_TD, M.Value));
418+
}
419+
420+
if (HasComments) {
421+
auto TD = std::make_unique<TagNode>(HTMLTag::TAG_TD);
422+
TD->Children.emplace_back(genHTML(M.Description));
423+
TRNode->Children.emplace_back(std::move(TD));
424+
}
425+
List->Children.emplace_back(std::move(TRNode));
426+
}
383427
return List;
384428
}
385429

@@ -653,15 +697,35 @@ static std::vector<std::unique_ptr<TagNode>>
653697
genHTML(const EnumInfo &I, const ClangDocContext &CDCtx) {
654698
std::vector<std::unique_ptr<TagNode>> Out;
655699
std::string EnumType = I.Scoped ? "enum class " : "enum ";
700+
// Determine if enum members have comments attached
701+
bool HasComments = false;
702+
for (const auto &M : I.Members) {
703+
if (!M.Description.empty()) {
704+
HasComments = true;
705+
break;
706+
}
707+
}
708+
std::unique_ptr<TagNode> Table =
709+
std::make_unique<TagNode>(HTMLTag::TAG_TABLE);
710+
std::unique_ptr<TagNode> Thead =
711+
std::make_unique<TagNode>(HTMLTag::TAG_THEAD);
712+
std::unique_ptr<TagNode> TRow = std::make_unique<TagNode>(HTMLTag::TAG_TR);
713+
std::unique_ptr<TagNode> TD =
714+
std::make_unique<TagNode>(HTMLTag::TAG_TH, EnumType + I.Name);
715+
// Span 3 columns if enum has comments
716+
TD->Attributes.emplace_back("colspan", HasComments ? "3" : "2");
717+
718+
Table->Attributes.emplace_back("id", llvm::toHex(llvm::toStringRef(I.USR)));
719+
TRow->Children.emplace_back(std::move(TD));
720+
Thead->Children.emplace_back(std::move(TRow));
721+
Table->Children.emplace_back(std::move(Thead));
722+
723+
std::unique_ptr<TagNode> Node = genEnumMembersBlock(I.Members, HasComments);
656724

657-
Out.emplace_back(
658-
std::make_unique<TagNode>(HTMLTag::TAG_H3, EnumType + I.Name));
659-
Out.back()->Attributes.emplace_back("id",
660-
llvm::toHex(llvm::toStringRef(I.USR)));
661-
662-
std::unique_ptr<TagNode> Node = genEnumMembersBlock(I.Members);
663725
if (Node)
664-
Out.emplace_back(std::move(Node));
726+
Table->Children.emplace_back(std::move(Node));
727+
728+
Out.emplace_back(std::move(Table));
665729

666730
if (I.DefLoc) {
667731
if (!CDCtx.RepositoryUrl)

clang-tools-extra/clang-doc/Representation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ void EnumInfo::merge(EnumInfo &&Other) {
266266
Scoped = Other.Scoped;
267267
if (Members.empty())
268268
Members = std::move(Other.Members);
269+
if (Other.HasComments || HasComments)
270+
HasComments = true;
269271
SymbolInfo::merge(std::move(Other));
270272
}
271273

clang-tools-extra/clang-doc/Representation.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,8 @@ struct EnumValueInfo {
431431
// Stores the user-supplied initialization expression for this enumeration
432432
// constant. This will be empty for implicit enumeration values.
433433
SmallString<16> ValueExpr;
434+
435+
std::vector<CommentInfo> Description; // Comment description of this field.
434436
};
435437

436438
// TODO: Expand to allow for documenting templating.
@@ -443,6 +445,8 @@ struct EnumInfo : public SymbolInfo {
443445

444446
// Indicates whether this enum is scoped (e.g. enum class).
445447
bool Scoped = false;
448+
// Indicates whether or not enum members have comments attached
449+
bool HasComments = false;
446450

447451
// Set to nonempty to the type when this is an explicitly typed enum. For
448452
// enum Foo : short { ... };

clang-tools-extra/clang-doc/Serialize.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,10 +394,20 @@ static void parseEnumerators(EnumInfo &I, const EnumDecl *D) {
394394
std::string ValueExpr;
395395
if (const Expr *InitExpr = E->getInitExpr())
396396
ValueExpr = getSourceCode(D, InitExpr->getSourceRange());
397-
398397
SmallString<16> ValueStr;
399398
E->getInitVal().toString(ValueStr);
400-
I.Members.emplace_back(E->getNameAsString(), ValueStr, ValueExpr);
399+
I.Members.emplace_back(E->getNameAsString(), ValueStr.str(), ValueExpr);
400+
ASTContext &Context = E->getASTContext();
401+
RawComment *Comment = E->getASTContext().getRawCommentForDeclNoCache(E);
402+
if (Comment) {
403+
CommentInfo CInfo;
404+
Comment->setAttached();
405+
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, E)) {
406+
EnumValueInfo &Member = I.Members.back();
407+
Member.Description.emplace_back();
408+
parseFullComment(Fc, Member.Description.back());
409+
}
410+
}
401411
}
402412
}
403413

clang-tools-extra/test/clang-doc/enum.cpp

Lines changed: 81 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
enum Color {
2222
// MD-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]*
2323
// HTML-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
24-
Red, ///< Red
25-
Green, ///< Green
26-
Blue ///< Blue
24+
Red, ///< Comment 1
25+
Green, ///< Comment 2
26+
Blue ///< Comment 3
2727
};
2828

2929
// MD-INDEX: ## Enums
@@ -34,23 +34,29 @@ enum Color {
3434
// MD-INDEX: | Blue |
3535
// MD-INDEX: **brief** For specifying RGB colors
3636

37-
// HTML-INDEX: <h2 id="Enums">Enums</h2>
38-
// HTML-INDEX: <h3 id="{{([0-9A-F]{40})}}">enum Color</h3>
39-
// HTML-INDEX: <li>Red</li>
40-
// HTML-INDEX: <li>Green</li>
41-
// HTML-INDEX: <li>Blue</li>
37+
// HTML-INDEX: <th colspan="3">enum Color</th>
38+
// HTML-INDEX: <td>Red</td>
39+
// HTML-INDEX: <td>0</td>
40+
// HTML-INDEX: <p> Comment 1</p>
41+
// HTML-INDEX: <td>Green</td>
42+
// HTML-INDEX: <td>1</td>
43+
// HTML-INDEX: <p> Comment 2</p>
44+
// HTML-INDEX: <td>Blue</td>
45+
// HTML-INDEX: <td>2</td>
46+
// HTML-INDEX: <p> Comment 3</p>
4247

4348
/**
4449
* @brief Shape Types
4550
*/
4651
enum class Shapes {
4752
// MD-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]*
4853
// HTML-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
49-
/// Circle
54+
55+
/// Comment 1
5056
Circle,
51-
/// Rectangle
57+
/// Comment 2
5258
Rectangle,
53-
/// Triangle
59+
/// Comment 3
5460
Triangle
5561
};
5662
// MD-INDEX: | enum class Shapes |
@@ -60,10 +66,17 @@ enum class Shapes {
6066
// MD-INDEX: | Triangle |
6167
// MD-INDEX: **brief** Shape Types
6268

63-
// HTML-INDEX: <h3 id="{{([0-9A-F]{40})}}">enum class Shapes</h3>
64-
// HTML-INDEX: <li>Circle</li>
65-
// HTML-INDEX: <li>Rectangle</li>
66-
// HTML-INDEX: <li>Triangle</li>
69+
// HTML-INDEX: <th colspan="3">enum class Shapes</th>
70+
// HTML-INDEX: <td>Circle</td>
71+
// HTML-INDEX: <td>0</td>
72+
// HTML-INDEX: <p> Comment 1</p>
73+
// HTML-INDEX: <td>Rectangle</td>
74+
// HTML-INDEX: <td>1</td>
75+
// HTML-INDEX: <p> Comment 2</p>
76+
// HTML-INDEX: <td>Triangle</td>
77+
// HTML-INDEX: <td>2</td>
78+
// HTML-INDEX: <p> Comment 3</p>
79+
6780

6881

6982
class Animals {
@@ -76,18 +89,25 @@ class Animals {
7689
enum AnimalType {
7790
// MD-ANIMAL-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]*
7891
// HTML-ANIMAL-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
79-
Dog, /// Man's best friend
80-
Cat, /// Man's other best friend
81-
Iguana /// A lizard
92+
Dog, ///< Man's best friend
93+
Cat, ///< Man's other best friend
94+
Iguana ///< A lizard
8295
};
8396
};
8497

8598
// HTML-ANIMAL: <h1>class Animals</h1>
8699
// HTML-ANIMAL: <h2 id="Enums">Enums</h2>
87-
// HTML-ANIMAL: <h3 id="{{([0-9A-F]{40})}}">enum AnimalType</h3>
88-
// HTML-ANIMAL: <li>Dog</li>
89-
// HTML-ANIMAL: <li>Cat</li>
90-
// HTML-ANIMAL: <li>Iguana</li>
100+
// HTML-ANIMAL: <th colspan="3">enum AnimalType</th>
101+
// HTML-ANIMAL: <td>Dog</td>
102+
// HTML-ANIMAL: <td>0</td>
103+
// HTML-ANIMAL: <p> Man&apos;s best friend</p>
104+
// HTML-ANIMAL: <td>Cat</td>
105+
// HTML-ANIMAL: <td>1</td>
106+
// HTML-ANIMAL: <p> Man&apos;s other best friend</p>
107+
// HTML-ANIMAL: <td>Iguana</td>
108+
// HTML-ANIMAL: <td>2</td>
109+
// HTML-ANIMAL: <p> A lizard</p>
110+
91111

92112
// MD-ANIMAL: # class Animals
93113
// MD-ANIMAL: ## Enums
@@ -106,10 +126,11 @@ namespace Vehicles {
106126
enum Car {
107127
// MD-VEHICLES-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]*
108128
// HTML-VEHICLES-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
109-
Sedan, /// Sedan
110-
SUV, /// SUV
111-
Pickup, /// Pickup
112-
Hatchback /// Hatchback
129+
130+
Sedan, ///< Comment 1
131+
SUV, ///< Comment 2
132+
Pickup, ///< Comment 3
133+
Hatchback ///< Comment 4
113134
};
114135
}
115136

@@ -124,9 +145,37 @@ namespace Vehicles {
124145
// MD-VEHICLES: **brief** specify type of car
125146

126147
// HTML-VEHICLES: <h1>namespace Vehicles</h1>
127-
// HTML-VEHICLES: <h2 id="Enums">Enums</h2>
128-
// HTML-VEHICLES: <h3 id="{{([0-9A-F]{40})}}">enum Car</h3>
129-
// HTML-VEHICLES: <li>Sedan</li>
130-
// HTML-VEHICLES: <li>SUV</li>
131-
// HTML-VEHICLES: <li>Pickup</li>
132-
// HTML-VEHICLES: <li>Hatchback</li>
148+
// HTML-VEHICLES: <th colspan="3">enum Car</th>
149+
// HTML-VEHICLES: <td>Sedan</td>
150+
// HTML-VEHICLES: <td>0</td>
151+
// HTML-VEHICLES: <p> Comment 1</p>
152+
// HTML-VEHICLES: <td>SUV</td>
153+
// HTML-VEHICLES: <td>1</td>
154+
// HTML-VEHICLES: <p> Comment 2</p>
155+
// HTML-VEHICLES: <td>Pickup</td>
156+
// HTML-VEHICLES: <td>2</td>
157+
// HTML-VEHICLES: <p> Comment 3</p>
158+
// HTML-VEHICLES: <td>Hatchback</td>
159+
// HTML-VEHICLES: <td>3</td>
160+
// HTML-VEHICLES: <p> Comment 4</p>
161+
162+
163+
enum ColorUserSpecified {
164+
RedUserSpecified = 'A',
165+
GreenUserSpecified = 2,
166+
BlueUserSpecified = 'C'
167+
};
168+
169+
// MD-INDEX: | enum ColorUserSpecified |
170+
// MD-INDEX: --
171+
// MD-INDEX: | RedUserSpecified |
172+
// MD-INDEX: | GreenUserSpecified |
173+
// MD-INDEX: | BlueUserSpecified |
174+
175+
// HTML-INDEX: <th colspan="2">enum ColorUserSpecified</th>
176+
// HTML-INDEX: <td>RedUserSpecified</td>
177+
// HTML-INDEX: <td>&apos;A&apos;</td>
178+
// HTML-INDEX: <td>GreenUserSpecified</td>
179+
// HTML-INDEX: <td>2</td>
180+
// HTML-INDEX: <td>BlueUserSpecified</td>
181+
// HTML-INDEX: <td>&apos;C&apos;</td>

0 commit comments

Comments
 (0)