1///===-- Representation.h - ClangDoc Representation -------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the internal representations of different declaration
10// types for the clang-doc tool.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
15#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
16
17#include "clang/AST/Type.h"
18#include "clang/Basic/Specifiers.h"
19#include "clang/Tooling/StandaloneExecution.h"
20#include "llvm/ADT/APSInt.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/StringExtras.h"
23#include <array>
24#include <optional>
25#include <string>
26
27namespace clang {
28namespace doc {
29
30// SHA1'd hash of a USR.
31using SymbolID = std::array<uint8_t, 20>;
32
33struct BaseRecordInfo;
34struct EnumInfo;
35struct FunctionInfo;
36struct Info;
37struct TypedefInfo;
38
39enum class InfoType {
40 IT_default,
41 IT_namespace,
42 IT_record,
43 IT_function,
44 IT_enum,
45 IT_typedef
46};
47
48// A representation of a parsed comment.
49struct CommentInfo {
50 CommentInfo() = default;
51 CommentInfo(CommentInfo &Other) = delete;
52 CommentInfo(CommentInfo &&Other) = default;
53 CommentInfo &operator=(CommentInfo &&Other) = default;
54
55 bool operator==(const CommentInfo &Other) const;
56
57 // This operator is used to sort a vector of CommentInfos.
58 // No specific order (attributes more important than others) is required. Any
59 // sort is enough, the order is only needed to call std::unique after sorting
60 // the vector.
61 bool operator<(const CommentInfo &Other) const;
62
63 SmallString<16>
64 Kind; // Kind of comment (FullComment, ParagraphComment, TextComment,
65 // InlineCommandComment, HTMLStartTagComment, HTMLEndTagComment,
66 // BlockCommandComment, ParamCommandComment,
67 // TParamCommandComment, VerbatimBlockComment,
68 // VerbatimBlockLineComment, VerbatimLineComment).
69 SmallString<64> Text; // Text of the comment.
70 SmallString<16> Name; // Name of the comment (for Verbatim and HTML).
71 SmallString<8> Direction; // Parameter direction (for (T)ParamCommand).
72 SmallString<16> ParamName; // Parameter name (for (T)ParamCommand).
73 SmallString<16> CloseName; // Closing tag name (for VerbatimBlock).
74 bool SelfClosing = false; // Indicates if tag is self-closing (for HTML).
75 bool Explicit = false; // Indicates if the direction of a param is explicit
76 // (for (T)ParamCommand).
77 llvm::SmallVector<SmallString<16>, 4>
78 AttrKeys; // List of attribute keys (for HTML).
79 llvm::SmallVector<SmallString<16>, 4>
80 AttrValues; // List of attribute values for each key (for HTML).
81 llvm::SmallVector<SmallString<16>, 4>
82 Args; // List of arguments to commands (for InlineCommand).
83 std::vector<std::unique_ptr<CommentInfo>>
84 Children; // List of child comments for this CommentInfo.
85};
86
87struct Reference {
88 // This variant (that takes no qualified name parameter) uses the Name as the
89 // QualName (very useful in unit tests to reduce verbosity). This can't use an
90 // empty string to indicate the default because we need to accept the empty
91 // string as a valid input for the global namespace (it will have
92 // "GlobalNamespace" as the name, but an empty QualName).
93 Reference(SymbolID USR = SymbolID(), StringRef Name = StringRef(),
94 InfoType IT = InfoType::IT_default)
95 : USR(USR), Name(Name), QualName(Name), RefType(IT) {}
96 Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName,
97 StringRef Path = StringRef())
98 : USR(USR), Name(Name), QualName(QualName), RefType(IT), Path(Path) {}
99
100 bool operator==(const Reference &Other) const {
101 return std::tie(args: USR, args: Name, args: QualName, args: RefType) ==
102 std::tie(args: Other.USR, args: Other.Name, args: QualName, args: Other.RefType);
103 }
104
105 bool mergeable(const Reference &Other);
106 void merge(Reference &&I);
107
108 /// Returns the path for this Reference relative to CurrentPath.
109 llvm::SmallString<64> getRelativeFilePath(const StringRef &CurrentPath) const;
110
111 /// Returns the basename that should be used for this Reference.
112 llvm::SmallString<16> getFileBaseName() const;
113
114 SymbolID USR = SymbolID(); // Unique identifier for referenced decl
115
116 // Name of type (possibly unresolved). Not including namespaces or template
117 // parameters (so for a std::vector<int> this would be "vector"). See also
118 // QualName.
119 SmallString<16> Name;
120
121 // Full qualified name of this type, including namespaces and template
122 // parameter (for example this could be "std::vector<int>"). Contrast to
123 // Name.
124 SmallString<16> QualName;
125
126 InfoType RefType = InfoType::IT_default; // Indicates the type of this
127 // Reference (namespace, record,
128 // function, enum, default).
129 // Path of directory where the clang-doc generated file will be saved
130 // (possibly unresolved)
131 llvm::SmallString<128> Path;
132};
133
134// Holds the children of a record or namespace.
135struct ScopeChildren {
136 // Namespaces and Records are references because they will be properly
137 // documented in their own info, while the entirety of Functions and Enums are
138 // included here because they should not have separate documentation from
139 // their scope.
140 //
141 // Namespaces are not syntactically valid as children of records, but making
142 // this general for all possible container types reduces code complexity.
143 std::vector<Reference> Namespaces;
144 std::vector<Reference> Records;
145 std::vector<FunctionInfo> Functions;
146 std::vector<EnumInfo> Enums;
147 std::vector<TypedefInfo> Typedefs;
148};
149
150// A base struct for TypeInfos
151struct TypeInfo {
152 TypeInfo() = default;
153 TypeInfo(const Reference &R) : Type(R) {}
154
155 // Convenience constructor for when there is no symbol ID or info type
156 // (normally used for built-in types in tests).
157 TypeInfo(StringRef Name, StringRef Path = StringRef())
158 : Type(SymbolID(), Name, InfoType::IT_default, Name, Path) {}
159
160 bool operator==(const TypeInfo &Other) const { return Type == Other.Type; }
161
162 Reference Type; // Referenced type in this info.
163};
164
165// Represents one template parameter.
166//
167// This is a very simple serialization of the text of the source code of the
168// template parameter. It is saved in a struct so there is a place to add the
169// name and default values in the future if needed.
170struct TemplateParamInfo {
171 TemplateParamInfo() = default;
172 explicit TemplateParamInfo(StringRef Contents) : Contents(Contents) {}
173
174 // The literal contents of the code for that specifies this template parameter
175 // for this declaration. Typical values will be "class T" and
176 // "typename T = int".
177 SmallString<16> Contents;
178};
179
180struct TemplateSpecializationInfo {
181 // Indicates the declaration that this specializes.
182 SymbolID SpecializationOf;
183
184 // Template parameters applying to the specialized record/function.
185 std::vector<TemplateParamInfo> Params;
186};
187
188// Records the template information for a struct or function that is a template
189// or an explicit template specialization.
190struct TemplateInfo {
191 // May be empty for non-partial specializations.
192 std::vector<TemplateParamInfo> Params;
193
194 // Set when this is a specialization of another record/function.
195 std::optional<TemplateSpecializationInfo> Specialization;
196};
197
198// Info for field types.
199struct FieldTypeInfo : public TypeInfo {
200 FieldTypeInfo() = default;
201 FieldTypeInfo(const TypeInfo &TI, StringRef Name = StringRef(),
202 StringRef DefaultValue = StringRef())
203 : TypeInfo(TI), Name(Name), DefaultValue(DefaultValue) {}
204
205 bool operator==(const FieldTypeInfo &Other) const {
206 return std::tie(args: Type, args: Name, args: DefaultValue) ==
207 std::tie(args: Other.Type, args: Other.Name, args: Other.DefaultValue);
208 }
209
210 SmallString<16> Name; // Name associated with this info.
211
212 // When used for function parameters, contains the string representing the
213 // expression of the default value, if any.
214 SmallString<16> DefaultValue;
215};
216
217// Info for member types.
218struct MemberTypeInfo : public FieldTypeInfo {
219 MemberTypeInfo() = default;
220 MemberTypeInfo(const TypeInfo &TI, StringRef Name, AccessSpecifier Access)
221 : FieldTypeInfo(TI, Name), Access(Access) {}
222
223 bool operator==(const MemberTypeInfo &Other) const {
224 return std::tie(args: Type, args: Name, args: Access, args: Description) ==
225 std::tie(args: Other.Type, args: Other.Name, args: Other.Access, args: Other.Description);
226 }
227
228 // Access level associated with this info (public, protected, private, none).
229 // AS_public is set as default because the bitcode writer requires the enum
230 // with value 0 to be used as the default.
231 // (AS_public = 0, AS_protected = 1, AS_private = 2, AS_none = 3)
232 AccessSpecifier Access = AccessSpecifier::AS_public;
233
234 std::vector<CommentInfo> Description; // Comment description of this field.
235};
236
237struct Location {
238 Location(int LineNumber = 0, StringRef Filename = StringRef(),
239 bool IsFileInRootDir = false)
240 : LineNumber(LineNumber), Filename(Filename),
241 IsFileInRootDir(IsFileInRootDir) {}
242
243 bool operator==(const Location &Other) const {
244 return std::tie(args: LineNumber, args: Filename) ==
245 std::tie(args: Other.LineNumber, args: Other.Filename);
246 }
247
248 // This operator is used to sort a vector of Locations.
249 // No specific order (attributes more important than others) is required. Any
250 // sort is enough, the order is only needed to call std::unique after sorting
251 // the vector.
252 bool operator<(const Location &Other) const {
253 return std::tie(args: LineNumber, args: Filename) <
254 std::tie(args: Other.LineNumber, args: Other.Filename);
255 }
256
257 int LineNumber = 0; // Line number of this Location.
258 SmallString<32> Filename; // File for this Location.
259 bool IsFileInRootDir = false; // Indicates if file is inside root directory
260};
261
262/// A base struct for Infos.
263struct Info {
264 Info(InfoType IT = InfoType::IT_default, SymbolID USR = SymbolID(),
265 StringRef Name = StringRef(), StringRef Path = StringRef())
266 : USR(USR), IT(IT), Name(Name), Path(Path) {}
267
268 Info(const Info &Other) = delete;
269 Info(Info &&Other) = default;
270
271 virtual ~Info() = default;
272
273 SymbolID USR =
274 SymbolID(); // Unique identifier for the decl described by this Info.
275 const InfoType IT = InfoType::IT_default; // InfoType of this particular Info.
276 SmallString<16> Name; // Unqualified name of the decl.
277 llvm::SmallVector<Reference, 4>
278 Namespace; // List of parent namespaces for this decl.
279 std::vector<CommentInfo> Description; // Comment description of this decl.
280 llvm::SmallString<128> Path; // Path of directory where the clang-doc
281 // generated file will be saved
282
283 void mergeBase(Info &&I);
284 bool mergeable(const Info &Other);
285
286 llvm::SmallString<16> extractName() const;
287
288 /// Returns the file path for this Info relative to CurrentPath.
289 llvm::SmallString<64> getRelativeFilePath(const StringRef &CurrentPath) const;
290
291 /// Returns the basename that should be used for this Info.
292 llvm::SmallString<16> getFileBaseName() const;
293};
294
295// Info for namespaces.
296struct NamespaceInfo : public Info {
297 NamespaceInfo(SymbolID USR = SymbolID(), StringRef Name = StringRef(),
298 StringRef Path = StringRef());
299
300 void merge(NamespaceInfo &&I);
301
302 ScopeChildren Children;
303};
304
305// Info for symbols.
306struct SymbolInfo : public Info {
307 SymbolInfo(InfoType IT, SymbolID USR = SymbolID(),
308 StringRef Name = StringRef(), StringRef Path = StringRef())
309 : Info(IT, USR, Name, Path) {}
310
311 void merge(SymbolInfo &&I);
312
313 std::optional<Location> DefLoc; // Location where this decl is defined.
314 llvm::SmallVector<Location, 2> Loc; // Locations where this decl is declared.
315};
316
317// TODO: Expand to allow for documenting templating and default args.
318// Info for functions.
319struct FunctionInfo : public SymbolInfo {
320 FunctionInfo(SymbolID USR = SymbolID())
321 : SymbolInfo(InfoType::IT_function, USR) {}
322
323 void merge(FunctionInfo &&I);
324
325 bool IsMethod = false; // Indicates whether this function is a class method.
326 Reference Parent; // Reference to the parent class decl for this method.
327 TypeInfo ReturnType; // Info about the return type of this function.
328 llvm::SmallVector<FieldTypeInfo, 4> Params; // List of parameters.
329 // Access level for this method (public, private, protected, none).
330 // AS_public is set as default because the bitcode writer requires the enum
331 // with value 0 to be used as the default.
332 // (AS_public = 0, AS_protected = 1, AS_private = 2, AS_none = 3)
333 AccessSpecifier Access = AccessSpecifier::AS_public;
334
335 // Full qualified name of this function, including namespaces and template
336 // specializations.
337 SmallString<16> FullName;
338
339 // When present, this function is a template or specialization.
340 std::optional<TemplateInfo> Template;
341};
342
343// TODO: Expand to allow for documenting templating, inheritance access,
344// friend classes
345// Info for types.
346struct RecordInfo : public SymbolInfo {
347 RecordInfo(SymbolID USR = SymbolID(), StringRef Name = StringRef(),
348 StringRef Path = StringRef());
349
350 void merge(RecordInfo &&I);
351
352 // Type of this record (struct, class, union, interface).
353 TagTypeKind TagType = TagTypeKind::Struct;
354
355 // Full qualified name of this record, including namespaces and template
356 // specializations.
357 SmallString<16> FullName;
358
359 // When present, this record is a template or specialization.
360 std::optional<TemplateInfo> Template;
361
362 // Indicates if the record was declared using a typedef. Things like anonymous
363 // structs in a typedef:
364 // typedef struct { ... } foo_t;
365 // are converted into records with the typedef as the Name + this flag set.
366 bool IsTypeDef = false;
367
368 llvm::SmallVector<MemberTypeInfo, 4>
369 Members; // List of info about record members.
370 llvm::SmallVector<Reference, 4> Parents; // List of base/parent records
371 // (does not include virtual
372 // parents).
373 llvm::SmallVector<Reference, 4>
374 VirtualParents; // List of virtual base/parent records.
375
376 std::vector<BaseRecordInfo>
377 Bases; // List of base/parent records; this includes inherited methods and
378 // attributes
379
380 ScopeChildren Children;
381};
382
383// Info for typedef and using statements.
384struct TypedefInfo : public SymbolInfo {
385 TypedefInfo(SymbolID USR = SymbolID())
386 : SymbolInfo(InfoType::IT_typedef, USR) {}
387
388 void merge(TypedefInfo &&I);
389
390 TypeInfo Underlying;
391
392 // Inidicates if this is a new C++ "using"-style typedef:
393 // using MyVector = std::vector<int>
394 // False means it's a C-style typedef:
395 // typedef std::vector<int> MyVector;
396 bool IsUsing = false;
397};
398
399struct BaseRecordInfo : public RecordInfo {
400 BaseRecordInfo();
401 BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path, bool IsVirtual,
402 AccessSpecifier Access, bool IsParent);
403
404 // Indicates if base corresponds to a virtual inheritance
405 bool IsVirtual = false;
406 // Access level associated with this inherited info (public, protected,
407 // private).
408 AccessSpecifier Access = AccessSpecifier::AS_public;
409 bool IsParent = false; // Indicates if this base is a direct parent
410};
411
412// Information for a single possible value of an enumeration.
413struct EnumValueInfo {
414 explicit EnumValueInfo(StringRef Name = StringRef(),
415 StringRef Value = StringRef("0"),
416 StringRef ValueExpr = StringRef())
417 : Name(Name), Value(Value), ValueExpr(ValueExpr) {}
418
419 bool operator==(const EnumValueInfo &Other) const {
420 return std::tie(args: Name, args: Value, args: ValueExpr) ==
421 std::tie(args: Other.Name, args: Other.Value, args: Other.ValueExpr);
422 }
423
424 SmallString<16> Name;
425
426 // The computed value of the enumeration constant. This could be the result of
427 // evaluating the ValueExpr, or it could be automatically generated according
428 // to C rules.
429 SmallString<16> Value;
430
431 // Stores the user-supplied initialization expression for this enumeration
432 // constant. This will be empty for implicit enumeration values.
433 SmallString<16> ValueExpr;
434};
435
436// TODO: Expand to allow for documenting templating.
437// Info for types.
438struct EnumInfo : public SymbolInfo {
439 EnumInfo() : SymbolInfo(InfoType::IT_enum) {}
440 EnumInfo(SymbolID USR) : SymbolInfo(InfoType::IT_enum, USR) {}
441
442 void merge(EnumInfo &&I);
443
444 // Indicates whether this enum is scoped (e.g. enum class).
445 bool Scoped = false;
446
447 // Set to nonempty to the type when this is an explicitly typed enum. For
448 // enum Foo : short { ... };
449 // this will be "short".
450 std::optional<TypeInfo> BaseType;
451
452 llvm::SmallVector<EnumValueInfo, 4> Members; // List of enum members.
453};
454
455struct Index : public Reference {
456 Index() = default;
457 Index(StringRef Name) : Reference(SymbolID(), Name) {}
458 Index(StringRef Name, StringRef JumpToSection)
459 : Reference(SymbolID(), Name), JumpToSection(JumpToSection) {}
460 Index(SymbolID USR, StringRef Name, InfoType IT, StringRef Path)
461 : Reference(USR, Name, IT, Name, Path) {}
462 // This is used to look for a USR in a vector of Indexes using std::find
463 bool operator==(const SymbolID &Other) const { return USR == Other; }
464 bool operator<(const Index &Other) const;
465
466 std::optional<SmallString<16>> JumpToSection;
467 std::vector<Index> Children;
468
469 void sort();
470};
471
472// TODO: Add functionality to include separate markdown pages.
473
474// A standalone function to call to merge a vector of infos into one.
475// This assumes that all infos in the vector are of the same type, and will fail
476// if they are different.
477llvm::Expected<std::unique_ptr<Info>>
478mergeInfos(std::vector<std::unique_ptr<Info>> &Values);
479
480struct ClangDocContext {
481 ClangDocContext() = default;
482 ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName,
483 bool PublicOnly, StringRef OutDirectory, StringRef SourceRoot,
484 StringRef RepositoryUrl,
485 std::vector<std::string> UserStylesheets,
486 std::vector<std::string> JsScripts);
487 tooling::ExecutionContext *ECtx;
488 std::string ProjectName; // Name of project clang-doc is documenting.
489 bool PublicOnly; // Indicates if only public declarations are documented.
490 std::string OutDirectory; // Directory for outputting generated files.
491 std::string SourceRoot; // Directory where processed files are stored. Links
492 // to definition locations will only be generated if
493 // the file is in this dir.
494 // URL of repository that hosts code used for links to definition locations.
495 std::optional<std::string> RepositoryUrl;
496 // Path of CSS stylesheets that will be copied to OutDirectory and used to
497 // style all HTML files.
498 std::vector<std::string> UserStylesheets;
499 // JavaScript files that will be imported in allHTML file.
500 std::vector<std::string> JsScripts;
501 // Other files that should be copied to OutDirectory, besides UserStylesheets.
502 std::vector<std::string> FilesToCopy;
503 Index Idx;
504};
505
506} // namespace doc
507} // namespace clang
508
509#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
510

source code of clang-tools-extra/clang-doc/Representation.h