Skip to content

Commit d785504

Browse files
committed
store record members in corpus
1 parent e2c8aac commit d785504

File tree

10 files changed

+280
-194
lines changed

10 files changed

+280
-194
lines changed

include/mrdocs/Corpus.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ class MRDOCS_VISIBLE
221221
{
222222
if (!opts.skipInherited)
223223
{
224-
auto MS = allMembers(I);
224+
auto&& MS = allMembers(I);
225225
visitIDs(MS,
226226
std::forward<F>(f),
227227
std::forward<Args>(args)...);
@@ -257,7 +257,7 @@ class MRDOCS_VISIBLE
257257
}
258258
else /* ordered */
259259
{
260-
auto members0 = allMembers(I);
260+
auto&& members0 = allMembers(I);
261261
static_assert(range_of<decltype(members0), SymbolID>);
262262
std::vector<SymbolID> members;
263263
members.reserve(std::ranges::distance(members0));

include/mrdocs/Metadata/Info/Record.hpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,6 @@ tag_invoke(
200200
v = dom::LazyObject(I, domCorpus);
201201
}
202202

203-
204203
inline
205204
auto
206205
allMembers(RecordInterface const& T)
@@ -275,6 +274,13 @@ tag_invoke(
275274
v = toString(kind);
276275
}
277276

277+
struct MemberInfo
278+
{
279+
AccessKind EffectiveAccess;
280+
InfoKind Kind;
281+
SymbolID id;
282+
};
283+
278284
/** Metadata for struct, class, or union.
279285
*/
280286
struct RecordInfo final
@@ -301,11 +307,15 @@ struct RecordInfo final
301307
*/
302308
std::vector<BaseInfo> Bases;
303309

304-
/** List of derived classes
310+
/** List of derived classes.
305311
*/
306312
std::vector<SymbolID> Derived;
307313

308-
/** Lists of members.
314+
/** List of members.
315+
*/
316+
std::vector<MemberInfo> Members;
317+
318+
/** Record Interface (NOT part of the Corpus.)
309319
*/
310320
RecordInterface Interface;
311321

@@ -345,6 +355,7 @@ inline
345355
auto
346356
allMembers(RecordInfo const& T)
347357
{
358+
//return std::views::transform(T.Members, &MemberInfo::id);
348359
return allMembers(T.Interface);
349360
}
350361

@@ -374,6 +385,7 @@ tag_invoke(
374385
io.map("isTypedef", I.IsTypeDef);
375386
io.map("bases", dom::LazyArray(I.Bases, domCorpus));
376387
io.map("derived", dom::LazyArray(I.Derived, domCorpus));
388+
//io.map("members", dom::LazyArray(I.Members, domCorpus));
377389
io.map("interface", I.Interface);
378390
io.map("template", I.Template);
379391
io.map("friends", dom::LazyArray(I.Friends, domCorpus));

src/lib/AST/ASTVisitor.cpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,19 +1770,9 @@ addMember(
17701770
RecordInfo& I,
17711771
Info const& Member)
17721772
{
1773-
switch (Member.Access)
1773+
if (!std::ranges::contains(I.Members, Member.id, &MemberInfo::id))
17741774
{
1775-
case AccessKind::Public:
1776-
addMember(I.Interface.Public, Member);
1777-
break;
1778-
case AccessKind::Private:
1779-
addMember(I.Interface.Private, Member);
1780-
break;
1781-
case AccessKind::Protected:
1782-
addMember(I.Interface.Protected, Member);
1783-
break;
1784-
default:
1785-
MRDOCS_UNREACHABLE();
1775+
I.Members.emplace_back(Member.Access, Member.Kind, Member.id);
17861776
}
17871777
}
17881778

src/lib/CorpusImpl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "lib/Metadata/Finalizers/JavadocFinalizer.hpp"
2121
#include "lib/Metadata/Finalizers/NamespacesFinalizer.hpp"
2222
#include "lib/Metadata/Finalizers/OverloadsFinalizer.hpp"
23+
#include "lib/Metadata/Finalizers/RecordsFinalizer.hpp"
2324
#include "lib/Metadata/Finalizers/SortMembersFinalizer.hpp"
2425
#include "lib/Support/Chrono.hpp"
2526
#include "lib/Support/Report.hpp"
@@ -1003,6 +1004,13 @@ qualifiedName(
10031004
void
10041005
CorpusImpl::finalize()
10051006
{
1007+
// Finalizing record interfaces
1008+
{
1009+
report::debug(" - Finalizing records");
1010+
RecordsFinalizer finalizer(*this);
1011+
finalizer.build();
1012+
}
1013+
10061014
report::info("Finalizing corpus");
10071015

10081016
{

src/lib/Metadata/Finalizers/BaseMembersFinalizer.cpp

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,6 @@ namespace clang::mrdocs {
1818
void
1919
BaseMembersFinalizer::
2020
inheritBaseMembers(RecordInfo& I, RecordInfo const& B, AccessKind const A)
21-
{
22-
inheritBaseMembers(I.id, I.Interface, B.Interface, A);
23-
}
24-
25-
void
26-
BaseMembersFinalizer::
27-
inheritBaseMembers(
28-
SymbolID const& derivedId,
29-
RecordInterface& derived,
30-
RecordInterface const& base,
31-
AccessKind const A)
3221
{
3322
if (A == AccessKind::Public)
3423
{
@@ -37,26 +26,26 @@ inheritBaseMembers(
3726
// members of the derived class and all protected members of the base
3827
// class are accessible as protected members of the derived class.
3928
// Private members of the base are never accessible unless friended.
40-
inheritBaseMembers(derivedId, derived.Public, base.Public);
41-
inheritBaseMembers(derivedId, derived.Protected, base.Protected);
29+
inheritBaseMembers(I.id, I.Interface.Public, B.Interface.Public);
30+
inheritBaseMembers(I.id, I.Interface.Protected, B.Interface.Protected);
4231
}
4332
else if (A == AccessKind::Protected)
4433
{
4534
// When a class uses protected member access specifier to derive from a
4635
// base, all public and protected members of the base class are
4736
// accessible as protected members of the derived class (private members
4837
// of the base are never accessible unless friended).
49-
inheritBaseMembers(derivedId, derived.Protected, base.Public);
50-
inheritBaseMembers(derivedId, derived.Protected, base.Protected);
38+
inheritBaseMembers(I.id, I.Interface.Protected, B.Interface.Public);
39+
inheritBaseMembers(I.id, I.Interface.Protected, B.Interface.Protected);
5140
}
5241
else if (A == AccessKind::Private && corpus_.config->extractPrivate)
5342
{
5443
// When a class uses private member access specifier to derive from a
5544
// base, all public and protected members of the base class are
5645
// accessible as private members of the derived class (private members
5746
// of the base are never accessible unless friended).
58-
inheritBaseMembers(derivedId, derived.Private, base.Public);
59-
inheritBaseMembers(derivedId, derived.Private, base.Protected);
47+
inheritBaseMembers(I.id, I.Interface.Private, B.Interface.Public);
48+
inheritBaseMembers(I.id, I.Interface.Private, B.Interface.Protected);
6049
}
6150
}
6251

src/lib/Metadata/Finalizers/BaseMembersFinalizer.hpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,6 @@ class BaseMembersFinalizer
3232
void
3333
inheritBaseMembers(RecordInfo& I, RecordInfo const& B, AccessKind A);
3434

35-
void
36-
inheritBaseMembers(
37-
SymbolID const& derivedId,
38-
RecordInterface& derived,
39-
RecordInterface const& base,
40-
AccessKind A);
41-
4235
void
4336
inheritBaseMembers(
4437
SymbolID const& derivedId,

src/lib/Metadata/Finalizers/NamespacesFinalizer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ operator()(NamespaceInfo& I)
4949
MRDOCS_CHECK_OR(!I.javadoc, FinalizerResult::None);
5050

5151
// 3) Remove empty undocumented namespaces
52-
auto memberIds = allMembers(I);
52+
auto&& memberIds = allMembers(I);
5353
if (std::ranges::empty(memberIds))
5454
{
5555
if (!corpus_.config->extractEmptyNamespaces)
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
//
2+
// Licensed under the Apache License v2.0 with LLVM Exceptions.
3+
// See https://llvm.org/LICENSE.txt for license information.
4+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
//
6+
// Copyright (c) 2025 Alan de Freitas ([email protected])
7+
//
8+
// Official repository: https://github.com/cppalliance/mrdocs
9+
//
10+
11+
#include "RecordsFinalizer.hpp"
12+
#include <mrdocs/Support/Algorithm.hpp>
13+
#include <mrdocs/Support/Report.hpp>
14+
15+
namespace clang::mrdocs {
16+
17+
namespace {
18+
19+
void
20+
addMember(std::vector<SymbolID>& container, Info const& Member)
21+
{
22+
if (!contains(container, Member.id))
23+
{
24+
container.push_back(Member.id);
25+
}
26+
}
27+
28+
void
29+
addMember(RecordTranche& T, Info const& Member)
30+
{
31+
if (auto const* U = Member.asNamespaceAliasPtr())
32+
{
33+
addMember(T.NamespaceAliases, *U);
34+
return;
35+
}
36+
if (auto const* U = Member.asTypedefPtr())
37+
{
38+
addMember(T.Typedefs, *U);
39+
return;
40+
}
41+
if (auto const* U = Member.asRecordPtr())
42+
{
43+
addMember(T.Records, *U);
44+
return;
45+
}
46+
if (auto const* U = Member.asEnumPtr())
47+
{
48+
addMember(T.Enums, *U);
49+
return;
50+
}
51+
if (auto const* U = Member.asFunctionPtr())
52+
{
53+
if (U->StorageClass != StorageClassKind::Static)
54+
{
55+
addMember(T.Functions, *U);
56+
}
57+
else
58+
{
59+
addMember(T.StaticFunctions, *U);
60+
}
61+
return;
62+
}
63+
if (auto const* U = Member.asVariablePtr())
64+
{
65+
if (U->StorageClass != StorageClassKind::Static)
66+
{
67+
addMember(T.Variables, *U);
68+
}
69+
else
70+
{
71+
addMember(T.StaticVariables, *U);
72+
}
73+
return;
74+
}
75+
if (auto const* U = Member.asConceptPtr())
76+
{
77+
addMember(T.Concepts, *U);
78+
return;
79+
}
80+
if (auto const* U = Member.asGuidePtr())
81+
{
82+
addMember(T.Guides, *U);
83+
return;
84+
}
85+
if (auto const* U = Member.asUsingPtr())
86+
{
87+
addMember(T.Usings, *U);
88+
return;
89+
}
90+
if (auto const* U = Member.asOverloadsPtr())
91+
{
92+
addMember(T.Functions, *U);
93+
return;
94+
}
95+
report::error("Cannot push {} of type {} into tranche",
96+
Member.Name,
97+
mrdocs::toString(Member.Kind).c_str());
98+
}
99+
100+
}
101+
102+
void
103+
RecordsFinalizer::
104+
generateRecordInterface(RecordInfo& I)
105+
{
106+
for (auto const& m: I.Members)
107+
{
108+
Info* infoPtr = corpus_.find(m.id);
109+
MRDOCS_CHECK_OR_CONTINUE(infoPtr);
110+
111+
Info const& Member = *infoPtr;
112+
switch (Member.Access)
113+
{
114+
case AccessKind::Public:
115+
addMember(I.Interface.Public, Member);
116+
break;
117+
case AccessKind::Private:
118+
addMember(I.Interface.Private, Member);
119+
break;
120+
case AccessKind::Protected:
121+
addMember(I.Interface.Protected, Member);
122+
break;
123+
default:
124+
MRDOCS_UNREACHABLE();
125+
}
126+
}
127+
}
128+
129+
void
130+
RecordsFinalizer::
131+
finalizeRecords(std::vector<SymbolID> const& ids)
132+
{
133+
for (SymbolID const& id: ids)
134+
{
135+
Info* infoPtr = corpus_.find(id);
136+
MRDOCS_CHECK_OR_CONTINUE(infoPtr);
137+
auto* record = infoPtr->asRecordPtr();
138+
MRDOCS_CHECK_OR_CONTINUE(record);
139+
operator()(*record);
140+
}
141+
}
142+
143+
void
144+
RecordsFinalizer::
145+
finalizeNamespaces(std::vector<SymbolID> const& ids)
146+
{
147+
for (SymbolID const& id: ids)
148+
{
149+
Info* infoPtr = corpus_.find(id);
150+
MRDOCS_CHECK_OR_CONTINUE(infoPtr);
151+
auto* ns = infoPtr->asNamespacePtr();
152+
MRDOCS_CHECK_OR_CONTINUE(ns);
153+
operator()(*ns);
154+
}
155+
}
156+
157+
void
158+
RecordsFinalizer::
159+
operator()(NamespaceInfo& I)
160+
{
161+
report::trace(
162+
"Generating record interfaces for namespace '{}'",
163+
corpus_.Corpus::qualifiedName(I));
164+
finalizeRecords(I.Members.Records);
165+
finalizeNamespaces(I.Members.Namespaces);
166+
}
167+
168+
void
169+
RecordsFinalizer::
170+
operator()(RecordInfo& I)
171+
{
172+
report::trace(
173+
"Generating record interface for record '{}'",
174+
corpus_.Corpus::qualifiedName(I));
175+
MRDOCS_CHECK_OR(!finalized_.contains(I.id));
176+
generateRecordInterface(I);
177+
finalizeRecords(I.Interface.Public.Records);
178+
finalizeRecords(I.Interface.Protected.Records);
179+
finalizeRecords(I.Interface.Private.Records);
180+
finalized_.emplace(I.id);
181+
}
182+
183+
} // clang::mrdocs

0 commit comments

Comments
 (0)