0.5.4
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
translation_unit_visitor.h
Go to the documentation of this file.
1/**
2 * @file src/class_diagram/visitor/translation_unit_visitor.h
3 *
4 * Copyright (c) 2021-2024 Bartek Kryza <bkryza@gmail.com>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18#pragma once
19
23#include "common/model/enums.h"
27#include "config/config.h"
28
29#include <clang/AST/RecursiveASTVisitor.h>
30#include <clang/Basic/SourceManager.h>
31
32#include <deque>
33#include <functional>
34#include <map>
35#include <memory>
36#include <string>
37
39
57
61
62/**
63 * @brief Class diagram translation unit visitor
64 *
65 * This class implements the `clang::RecursiveASTVisitor` interface
66 * for selected visitors relevant to generating class diagrams.
67 */
69 : public clang::RecursiveASTVisitor<translation_unit_visitor>,
71public:
74
76
77 /**
78 * @brief Constructor.
79 *
80 * @param sm Current source manager reference
81 * @param diagram Diagram model
82 * @param config Diagram configuration
83 */
84 explicit translation_unit_visitor(clang::SourceManager &sm,
87
88 /**
89 * \defgroup Implementation of ResursiveASTVisitor methods
90 * @{
91 */
92 bool shouldVisitTemplateInstantiations() const { return false; }
93
94 bool shouldVisitImplicitCode() const { return false; }
95
96 virtual bool VisitNamespaceDecl(clang::NamespaceDecl *ns);
97
98 virtual bool VisitRecordDecl(clang::RecordDecl *D);
99
100 virtual bool VisitCXXRecordDecl(clang::CXXRecordDecl *d);
101
102 virtual bool VisitEnumDecl(clang::EnumDecl *e);
103
104 virtual bool VisitClassTemplateDecl(
105 clang::ClassTemplateDecl *class_template_declaration);
106
108 clang::ClassTemplateSpecializationDecl *cls);
109
110 virtual bool VisitTypeAliasTemplateDecl(clang::TypeAliasTemplateDecl *cls);
111
112 virtual bool TraverseConceptDecl(clang::ConceptDecl *cpt);
113 /** @} */
114
115 /**
116 * @brief Finalize diagram model
117 *
118 * This method is called after the entire AST has been visited by this
119 * visitor. It is used to perform necessary post processing on the diagram
120 * (e.g. resolve translation unit local element ID's into global ID's based
121 * on elements full names).
122 */
123 void finalize();
124
125 /**
126 * @brief Add class (or template class) to the diagram.
127 *
128 * @param c Class model
129 */
130 void add_class(std::unique_ptr<class_> &&c);
131
132 /**
133 * @brief Add enum to the diagram.
134 *
135 * @param e Enum model
136 */
137 void add_enum(std::unique_ptr<enum_> &&e);
138
139 /**
140 * @brief Add concept to the diagram.
141 *
142 * @param c Concept model
143 */
144 void add_concept(std::unique_ptr<concept_> &&c);
145
147 std::unique_ptr<common::model::template_element> element) override;
148
149 std::unique_ptr<class_> create_element(const clang::NamedDecl *decl) const;
150
152 common::model::template_element &template_instantiation_base,
153 const std::string &full_name, eid_t templated_decl_id);
154
155private:
156 /**
157 * @brief Create class element model from class declaration
158 *
159 * @param cls Class declaration
160 * @return Class diagram element model
161 */
162 std::unique_ptr<clanguml::class_diagram::model::class_>
163 create_class_declaration(clang::CXXRecordDecl *cls);
164
165 /**
166 * @brief Create class element model from record (e.g. struct) declaration
167 *
168 * @param rec Record declaration
169 * @return Class diagram element model
170 */
171 std::unique_ptr<clanguml::class_diagram::model::class_>
172 create_record_declaration(clang::RecordDecl *rec);
173
174 /**
175 * @brief Create concept element model from concept declaration
176 * @param cpt Concept declaration
177 * @return Concept diagram element model
178 */
179 std::unique_ptr<clanguml::class_diagram::model::concept_>
180 create_concept_declaration(clang::ConceptDecl *cpt);
181
182 /**
183 * @brief Process class declaration
184 *
185 * @param cls Class declaration
186 * @param c Class diagram element return from `create_class_declaration`
187 */
188 void process_class_declaration(const clang::CXXRecordDecl &cls,
190
191 /**
192 * @brief Process class declaration bases (parents), if any
193 *
194 * @param cls Class declaration
195 * @param c Class diagram element model
196 */
197 void process_class_bases(const clang::CXXRecordDecl *cls,
199
200 /**
201 * @brief Process class children elements (members and methods)
202 *
203 * @param cls Class declaration
204 * @param c Class diagram element model
205 */
206 void process_class_children(const clang::CXXRecordDecl *cls,
208
209 /**
210 * @brief Process class or record data members
211 * @param cls Class declaration
212 * @param c Class diagram element model
213 */
214 void process_record_members(const clang::RecordDecl *cls, class_ &c);
215
216 /**
217 * @brief Process class template specialization/instantiation
218 *
219 * @param cls Class template specialization declaration
220 * @return Class diagram element model
221 */
222 std::unique_ptr<clanguml::class_diagram::model::class_>
224 clang::ClassTemplateSpecializationDecl *cls);
225
226 /**
227 * @brief Process template specialization children (members and methods)
228 * @param cls Class template specialization declaration
229 * @param c Class diagram element model
230 */
232 const clang::ClassTemplateSpecializationDecl *cls, class_ &c);
233
234 /**
235 * @brief Process class method
236 *
237 * @param mf Method declaration
238 * @param c Class diagram element model
239 */
240 void process_method(const clang::CXXMethodDecl &mf,
242
243 /**
244 * @brief Process class method properties
245 * @param mf Method declaration
246 * @param c Class diagram element model
247 * @param method_name Method name
248 * @param method Method model
249 */
250 void process_method_properties(const clang::CXXMethodDecl &mf,
251 const class_ &c, const std::string &method_name,
252 class_method &method) const;
253
254 /**
255 * @brief Process class template method
256 *
257 * @param mf Method declaration
258 * @param c Class diagram element model
259 */
260 void process_template_method(const clang::FunctionTemplateDecl &mf,
262
263 /**
264 * @brief Process class static data member
265 *
266 * @param field_declaration Static data member declaration
267 * @param c Class diagram element model
268 */
269 void process_static_field(const clang::VarDecl &field_declaration,
271
272 /**
273 * @brief Process class data member
274 *
275 * @param field_declaration Data member declaration
276 * @param c Class diagram element model
277 */
278 void process_field(const clang::FieldDecl &field_declaration,
280
281 /**
282 * @brief Process function/method parameter
283 *
284 * @param param Parameter declaration
285 * @param method Class method model
286 * @param c Class diagram element model
287 * @param template_parameter_names Ignored
288 */
289 void process_function_parameter(const clang::ParmVarDecl &param,
292 const std::set<std::string> &template_parameter_names = {});
293
294 /**
295 * @brief Process class friend
296 *
297 * @param f Friend declaration
298 * @param c Class diagram element model
299 */
300 void process_friend(
301 const clang::FriendDecl &f, clanguml::class_diagram::model::class_ &c);
302
303 /**
304 * @brief Find relationships in a specific type
305 *
306 * @param type Type to search for relationships
307 * @param relationship_hint Default relationship type to infer from this
308 * type
309 * @return True, if any relationships were found
310 */
311 bool find_relationships(const clang::QualType &type,
312 found_relationships_t & /*relationships*/,
314
315 /**
316 * @brief Add relationships from relationship list to a class model
317 *
318 * This method takes a list of relationships whose originating element
319 * is class `c` and adds them to it, ignoring any duplicates and skipping
320 * relationships that should be excluded from the diagram.
321 *
322 * @param c Class diagram element model
323 * @param field Class member model
324 * @param relationships List of found relationships
325 * @param break_on_first_aggregation Stop adding relatinoships, after first
326 * aggregation is found
327 */
330 const found_relationships_t &relationships,
331 bool break_on_first_aggregation = false);
332
333 /**
334 * @brief Process record parent element (e.g. for nested classes)
335 *
336 * This method handles nested classes or structs.
337 *
338 * @param cls Record declaration
339 * @param c Class diagram element model
340 * @param ns Package in the diagram to which the class `c` should belong
341 */
343 clang::RecordDecl *cls, class_ &c, const namespace_ &ns);
344
345 /**
346 * @brief Find relationships in function parameter
347 *
348 * @param c Class diagram element model
349 * @param atsp `auto` type
350 */
352 model::class_ &c, const clang::AutoType *atsp);
353
354 /**
355 * @brief Find relationships in concept constraint expression
356 *
357 * @param c Diagram element model (concept)
358 * @param expr Concept constraint expression
359 */
361 clanguml::common::model::element &c, const clang::Expr *expr);
362
363 /**
364 * @brief Register incomplete forward declaration to be updated later
365 */
367
368 /**
369 * @brief Replace any AST local ids in diagram elements with global ones
370 *
371 * Not all elements global ids can be set in relationships during
372 * traversal of the AST. In such cases, a local id (obtained from `getID()`)
373 * and at after the traversal is complete, the id is replaced with the
374 * global diagram id.
375 */
377
378 /**
379 * @brief Process concept constraint requirements
380 *
381 * @param cpt Concept declaration
382 * @param expr Requires expression
383 * @param concept_model Concept diagram element model
384 */
385 void process_constraint_requirements(const clang::ConceptDecl *cpt,
386 const clang::Expr *expr, model::concept_ &concept_model) const;
387
388 /**
389 * @brief Find concept specializations relationships
390 *
391 * @param c Concept element model
392 * @param concept_specialization Concept specialization expression
393 */
395 const clang::ConceptSpecializationExpr *concept_specialization);
396
397 /**
398 * @brief Extract template contraint parameter name from raw source code
399 *
400 * @param concept_specialization Concept specialization expression
401 * @param cpt Concept declaration
402 * @param constrained_template_params Found constraint template param names
403 * @param argument_index Argument index
404 * @param type_name Type parameter name - used if extraction fails
405 */
407 const clang::ConceptSpecializationExpr *concept_specialization,
408 const clang::ConceptDecl *cpt,
409 std::vector<std::string> &constrained_template_params,
410 size_t argument_index, std::string &type_name) const;
411
412 /**
413 * @brief Register already processed template class name
414 *
415 * @param qualified_name Fully qualified template class name
416 */
417 void add_processed_template_class(std::string qualified_name);
418
419 /**
420 * @brief Check if template class has already been processed
421 *
422 * @param qualified_name Fully qualified template class name
423 * @return True, if template class has already been processed
424 */
425 bool has_processed_template_class(const std::string &qualified_name) const;
426
427 /**
428 * @brief Get template builder reference
429 *
430 * @return Reference to 'template_builder' instance
431 */
433
435
436 std::map<eid_t, std::unique_ptr<clanguml::class_diagram::model::class_>>
438
439 std::map<int64_t /* local anonymous struct id */,
440 std::tuple<std::string /* field name */, common::model::relationship_t,
442 std::optional<size_t> /* destination_multiplicity */>>
444
445 /**
446 * When visiting CXX records we need to know if they have already been
447 * process in VisitClassTemplateDecl or
448 * VisitClassTemplateSpecializationDecl. If yes, then we need to skip it
449 *
450 * @todo There must be a better way to do this...
451 */
453};
454} // namespace clanguml::class_diagram::visitor