You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor(lib): consistent metadata class family hierarchy pattern
Apply a consistent pattern for the class families in the metadata. Class names match their name in all places (such as Symbol instead of Info, and Type instead of TypeInfo), and the clang namespace is described explicitly to avoid name conflicts. The Javadoc hierarchy for blocks and inlines is also well defined.
Copy file name to clipboardExpand all lines: docs/modules/ROOT/pages/contribute.adoc
+24-17Lines changed: 24 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,9 +32,9 @@ Common options are defined in `mrdocs/Config.hpp`.
32
32
The `Config` class represents all public options that could be defined in a configuration file.
33
33
It also provides a representation plugins can use to access public options from the command line or configuration file.
34
34
35
-
The function `clang::mrdocs::loadConfig` is also provided to parse all public options from a YAML configuration file.
35
+
The function `mrdocs::loadConfig` is also provided to parse all public options from a YAML configuration file.
36
36
37
-
Internally, Mr.Docs uses the derived `clang::mrdocs::ConfigImpl` class (`src/lib/Lib/ConfigImpl.hpp`) to also store the private representation of parsed options, such as filters.
37
+
Internally, Mr.Docs uses the derived `mrdocs::ConfigImpl` class (`src/lib/Lib/ConfigImpl.hpp`) to also store the private representation of parsed options, such as filters.
38
38
39
39
==== Finalizing Options
40
40
@@ -53,6 +53,14 @@ MrDocs has many categories of objects, where we utilize polymorphism with a fixe
53
53
54
54
Each base class is defined in its own header and, when necessary, implementation file. Each derived class also has its own header and implementation file. Finally, there is a single aggregator header file that includes all the derived headers. This file centralizes logic that requires knowledge of the full set of variants, such as visitors, comparison operators, and other operations that depend on the discriminator.
55
55
56
+
Suppose we have a polymorphic family of `Symbol` objects, with derived types `Function`, `Class`, and `Enum`. The files would be organized as follows:
57
+
58
+
* The `Symbol/SymbolNodes.inc` file defines the possible derived types and is used to generate code via macros.
59
+
* The `Symbol/SymbolKind.hpp` file defines the `SymbolKind` enum, which is used as a discriminator for the derived types.
60
+
* The base class `Symbol` is defined in `Symbol/BaseSymbol.hpp` and `Symbol/BaseSymbol.cpp` (if needed).
61
+
* The available kinds of derived symbols are defined in `Symbol/<Derived>.hpp` and `Symbol/<Derived>.cpp` files, e.g., `Symbol/Function.hpp` and `Symbol/Function.cpp`.
62
+
* The `Symbol.hpp` file includes all derived headers and defines operations that require knowledge of all variants, such as visitors and comparison operators.
63
+
56
64
This pattern keeps the individual derived types self-contained while making cross-variant operations explicit and localized. When adding a new derived type, contributors should create its header and source file alongside the existing ones and update the corresponding aggregator file to register the new variant. This keeps the codebase predictable, avoids scattering logic, and ensures that operations over polymorphic families remain easy to find and maintain.
57
65
58
66
[#extract_symbols]
@@ -80,19 +88,18 @@ For each compilation command:
80
88
* Paths are normalized
81
89
* Non C++ files are filtered
82
90
83
-
[#info_nodes]
84
-
==== Info Nodes
91
+
[#symbol_nodes]
92
+
==== Symbol Nodes
85
93
86
-
MrDocs represents each C++ symbol or construct as an `Info` node (`mrdocs/Metadata/Info.hpp`).
87
-
`Info` can not only represent direct AST symbols but also {cpp} constructs that need to be inferred from these symbols.
94
+
MrDocs represents each C++ symbol or construct as an `Symbol` node (`mrdocs/Metadata/Symbol.hpp`).
95
+
`Symbol` can not only represent direct AST symbols but also {cpp} constructs that need to be inferred from these symbols.
88
96
Nodes in the first category will typically be created in the initial extraction step, and nodes in the second category will be created in the finalization step.
89
97
90
-
When defining a new `Info` type, it is important to consider how this type will be supported in all other modules of the codebase, including the AST visitor, generators, tests, and the documentation.
91
-
The script `.github/check_info_nodes_support.sh` will attempt to infer whether most of these features have been implemented for each node type.
98
+
When defining a new `Symbol` type, it is important to consider how this type will be supported in all other modules of the codebase, including the AST visitor, generators, tests, and the documentation.
92
99
93
100
==== Clang LibTooling
94
101
95
-
MrDocs uses Clang to extract `Info` objects from the {cpp} AST.
102
+
MrDocs uses Clang to extract `Symbol` objects from the {cpp} AST.
96
103
Clang offers two https://clang.llvm.org/docs/Tooling.html[interfaces] to access the C++ AST: the https://clang.llvm.org/doxygen/group__CINDEX.html[`LibClang`] and https://clang.llvm.org/docs/LibTooling.html[`LibTooling`] libraries.
97
104
MrDocs uses the latter, as it provides full control over the AST traversal process at the cost of an unstable API.
98
105
@@ -109,7 +116,7 @@ The `clang::tooling::ClangTool::run` method takes a `clang::tooling::ToolAction`
109
116
The action object usually comes from a `clang::tooling::FrontendActionFactory`.
110
117
In the example above, the `SyntaxOnlyAction` is used to parse the source code and generate the AST without any further processing.
111
118
112
-
In MrDocs, this process happens in `clang::mrdocs::CorpusImpl::build` (`src/lib/Lib/CorpusImpl.cpp`), where we call `Tool.run` for each object in the database with our custom `ASTAction` action and `ASTActionFactory` factory (`src/lib/AST/ASTVisitor.cpp`).
119
+
In MrDocs, this process happens in `mrdocs::CorpusImpl::build` (`src/lib/Lib/CorpusImpl.cpp`), where we call `Tool.run` for each object in the database with our custom `ASTAction` action and `ASTActionFactory` factory (`src/lib/AST/ASTVisitor.cpp`).
113
120
114
121
==== AST Traversal
115
122
@@ -119,7 +126,7 @@ As the AST is generated, it is traversed by the `ASTVisitor` class.
119
126
The entry point of this class is `ASTVisitor::build`, which recursively calls `ASTVisitor::traverseDecl` for the root `clang::TranslationUnitDecl` node of the translation unit.
120
127
During the AST traversal stage, the complete AST generated by the clang frontend is walked beginning with this root `TranslationUnitDecl` node.
121
128
122
-
Each `clang` node is converted into a `<<info_nodes,mrdocs::Info>>` node, which is then stored with any relevant information in a `mrdocs::Corpus` object.
129
+
Each `clang` node is converted into a `<<symbol_nodes,mrdocs::Symbol>>` node, which is then stored with any relevant information in a `mrdocs::Corpus` object.
123
130
124
131
==== USR Generation
125
132
@@ -132,15 +139,15 @@ This is necessary to generate the full interface for user-defined types.
132
139
After running the AST traversal on all translation units, `CorpusImpl::build` contains finalization steps for the `Corpus` object.
133
140
At this point, we process C++ constructs that are not directly represented in the AST.
134
141
135
-
The first finalization step happens in `CorpusImpl::build` (`src/lib/Lib/CorpusImpl.cpp`), where the `Info` objects from a single translation unit
142
+
The first finalization step happens in `CorpusImpl::build` (`src/lib/Lib/CorpusImpl.cpp`), where the `Symbol` objects from a single translation unit
136
143
are merged into a map containing the merged results from all other TUs.
137
144
The merging step is necessary as there may be multiple identical definitions of the same entity.
138
145
For instance, this represents the case where a function is declared at different points in the code base and might have different attributes or comments.
139
146
At this step, the doc comments are also finalized.
140
-
Each `Info` object has a pointer to its `Javadoc` object (`mrdocs/Metadata/Javadoc.hpp`), which is a representation of the documentation comments.
147
+
Each `Symbol` object has a pointer to its `Javadoc` object (`mrdocs/Metadata/Javadoc.hpp`), which is a representation of the documentation comments.
141
148
142
-
After AST traversal and `Info` merging, the result is stored as a map of `Info` objects indexed by their respective `SymbolID`.
143
-
A second finalization step is then performed in `clang::mrdocs::finalize`, where any references to `SymbolID` objects that don't exist are removed.
149
+
After AST traversal and `Symbol` merging, the result is stored as a map of `Symbol` objects indexed by their respective `SymbolID`.
150
+
A second finalization step is then performed in `mrdocs::finalize`, where any references to `SymbolID` objects that don't exist are removed.
144
151
This is necessary because the AST traversal will generate references to entities that should be filtered and are not present in the corpus.
145
152
146
153
At this point, the `Corpus` object contains representations of all entities in the code base and further semantic {cpp} constructs that are not directly represented in the AST can be inferred.
@@ -164,7 +171,7 @@ This directory contains the public headers for the MrDocs library.
164
171
* `include/mrdocs/`—The core library headers
165
172
** `include/mrdocs/ADT`—Data Structures
166
173
** `include/mrdocs/Dom`—The Document Object Model for Abstract Trees
167
-
** `include/mrdocs/Metadata`—`Info` nodes and metadata classes
174
+
** `include/mrdocs/Metadata`—`Symbol` nodes and metadata classes
0 commit comments