1 ///===-- Representation.h - ClangDoc Representation -------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines the internal representations of different declaration
10 // types for the clang-doc tool.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
15 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
17 #include "clang/AST/Type.h"
18 #include "clang/Basic/Specifiers.h"
19 #include "clang/Tooling/StandaloneExecution.h"
20 #include "llvm/ADT/Optional.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringExtras.h"
29 // SHA1'd hash of a USR.
30 using SymbolID
= std::array
<uint8_t, 20>;
35 struct BaseRecordInfo
;
45 // A representation of a parsed comment.
47 CommentInfo() = default;
48 CommentInfo(CommentInfo
&Other
) = delete;
49 CommentInfo(CommentInfo
&&Other
) = default;
50 CommentInfo
&operator=(CommentInfo
&&Other
) = default;
52 bool operator==(const CommentInfo
&Other
) const {
53 auto FirstCI
= std::tie(Kind
, Text
, Name
, Direction
, ParamName
, CloseName
,
54 SelfClosing
, Explicit
, AttrKeys
, AttrValues
, Args
);
56 std::tie(Other
.Kind
, Other
.Text
, Other
.Name
, Other
.Direction
,
57 Other
.ParamName
, Other
.CloseName
, Other
.SelfClosing
,
58 Other
.Explicit
, Other
.AttrKeys
, Other
.AttrValues
, Other
.Args
);
60 if (FirstCI
!= SecondCI
|| Children
.size() != Other
.Children
.size())
63 return std::equal(Children
.begin(), Children
.end(), Other
.Children
.begin(),
64 llvm::deref
<std::equal_to
<>>{});
67 // This operator is used to sort a vector of CommentInfos.
68 // No specific order (attributes more important than others) is required. Any
69 // sort is enough, the order is only needed to call std::unique after sorting
71 bool operator<(const CommentInfo
&Other
) const {
72 auto FirstCI
= std::tie(Kind
, Text
, Name
, Direction
, ParamName
, CloseName
,
73 SelfClosing
, Explicit
, AttrKeys
, AttrValues
, Args
);
75 std::tie(Other
.Kind
, Other
.Text
, Other
.Name
, Other
.Direction
,
76 Other
.ParamName
, Other
.CloseName
, Other
.SelfClosing
,
77 Other
.Explicit
, Other
.AttrKeys
, Other
.AttrValues
, Other
.Args
);
79 if (FirstCI
< SecondCI
)
82 if (FirstCI
== SecondCI
) {
83 return std::lexicographical_compare(
84 Children
.begin(), Children
.end(), Other
.Children
.begin(),
85 Other
.Children
.end(), llvm::deref
<std::less
<>>());
92 Kind
; // Kind of comment (FullComment, ParagraphComment, TextComment,
93 // InlineCommandComment, HTMLStartTagComment, HTMLEndTagComment,
94 // BlockCommandComment, ParamCommandComment,
95 // TParamCommandComment, VerbatimBlockComment,
96 // VerbatimBlockLineComment, VerbatimLineComment).
97 SmallString
<64> Text
; // Text of the comment.
98 SmallString
<16> Name
; // Name of the comment (for Verbatim and HTML).
99 SmallString
<8> Direction
; // Parameter direction (for (T)ParamCommand).
100 SmallString
<16> ParamName
; // Parameter name (for (T)ParamCommand).
101 SmallString
<16> CloseName
; // Closing tag name (for VerbatimBlock).
102 bool SelfClosing
= false; // Indicates if tag is self-closing (for HTML).
103 bool Explicit
= false; // Indicates if the direction of a param is explicit
104 // (for (T)ParamCommand).
105 llvm::SmallVector
<SmallString
<16>, 4>
106 AttrKeys
; // List of attribute keys (for HTML).
107 llvm::SmallVector
<SmallString
<16>, 4>
108 AttrValues
; // List of attribute values for each key (for HTML).
109 llvm::SmallVector
<SmallString
<16>, 4>
110 Args
; // List of arguments to commands (for InlineCommand).
111 std::vector
<std::unique_ptr
<CommentInfo
>>
112 Children
; // List of child comments for this CommentInfo.
116 Reference() = default;
117 Reference(llvm::StringRef Name
) : Name(Name
) {}
118 // An empty path means the info is in the global namespace because the path is
119 // a composite of the parent namespaces.
120 Reference(llvm::StringRef Name
, StringRef Path
)
121 : Name(Name
), Path(Path
), IsInGlobalNamespace(Path
.empty()) {}
122 Reference(SymbolID USR
, StringRef Name
, InfoType IT
)
123 : USR(USR
), Name(Name
), RefType(IT
) {}
124 // An empty path means the info is in the global namespace because the path is
125 // a composite of the parent namespaces.
126 Reference(SymbolID USR
, StringRef Name
, InfoType IT
, StringRef Path
)
127 : USR(USR
), Name(Name
), RefType(IT
), Path(Path
),
128 IsInGlobalNamespace(Path
.empty()) {}
130 bool operator==(const Reference
&Other
) const {
131 return std::tie(USR
, Name
, RefType
) ==
132 std::tie(Other
.USR
, Other
.Name
, Other
.RefType
);
135 bool mergeable(const Reference
&Other
);
136 void merge(Reference
&&I
);
138 /// Returns the path for this Reference relative to CurrentPath.
139 llvm::SmallString
<64> getRelativeFilePath(const StringRef
&CurrentPath
) const;
141 /// Returns the basename that should be used for this Reference.
142 llvm::SmallString
<16> getFileBaseName() const;
144 SymbolID USR
= SymbolID(); // Unique identifier for referenced decl
145 SmallString
<16> Name
; // Name of type (possibly unresolved).
146 InfoType RefType
= InfoType::IT_default
; // Indicates the type of this
147 // Reference (namespace, record,
148 // function, enum, default).
149 // Path of directory where the clang-doc generated file will be saved
150 // (possibly unresolved)
151 llvm::SmallString
<128> Path
;
152 // Indicates if the info's parent is the global namespace, or if the info is
153 // the global namespace
154 bool IsInGlobalNamespace
= false;
157 // A base struct for TypeInfos
159 TypeInfo() = default;
160 TypeInfo(SymbolID Type
, StringRef Field
, InfoType IT
)
161 : Type(Type
, Field
, IT
) {}
162 TypeInfo(SymbolID Type
, StringRef Field
, InfoType IT
, StringRef Path
)
163 : Type(Type
, Field
, IT
, Path
) {}
164 TypeInfo(llvm::StringRef RefName
) : Type(RefName
) {}
165 TypeInfo(llvm::StringRef RefName
, StringRef Path
) : Type(RefName
, Path
) {}
167 bool operator==(const TypeInfo
&Other
) const { return Type
== Other
.Type
; }
169 Reference Type
; // Referenced type in this info.
172 // Info for field types.
173 struct FieldTypeInfo
: public TypeInfo
{
174 FieldTypeInfo() = default;
175 FieldTypeInfo(SymbolID Type
, StringRef Field
, InfoType IT
, StringRef Path
,
176 llvm::StringRef Name
)
177 : TypeInfo(Type
, Field
, IT
, Path
), Name(Name
) {}
178 FieldTypeInfo(llvm::StringRef RefName
, llvm::StringRef Name
)
179 : TypeInfo(RefName
), Name(Name
) {}
180 FieldTypeInfo(llvm::StringRef RefName
, StringRef Path
, llvm::StringRef Name
)
181 : TypeInfo(RefName
, Path
), Name(Name
) {}
183 bool operator==(const FieldTypeInfo
&Other
) const {
184 return std::tie(Type
, Name
) == std::tie(Other
.Type
, Other
.Name
);
187 SmallString
<16> Name
; // Name associated with this info.
190 // Info for member types.
191 struct MemberTypeInfo
: public FieldTypeInfo
{
192 MemberTypeInfo() = default;
193 MemberTypeInfo(SymbolID Type
, StringRef Field
, InfoType IT
, StringRef Path
,
194 llvm::StringRef Name
, AccessSpecifier Access
)
195 : FieldTypeInfo(Type
, Field
, IT
, Path
, Name
), Access(Access
) {}
196 MemberTypeInfo(llvm::StringRef RefName
, llvm::StringRef Name
,
197 AccessSpecifier Access
)
198 : FieldTypeInfo(RefName
, Name
), Access(Access
) {}
199 MemberTypeInfo(llvm::StringRef RefName
, StringRef Path
, llvm::StringRef Name
,
200 AccessSpecifier Access
)
201 : FieldTypeInfo(RefName
, Path
, Name
), Access(Access
) {}
203 bool operator==(const MemberTypeInfo
&Other
) const {
204 return std::tie(Type
, Name
, Access
, Description
) ==
205 std::tie(Other
.Type
, Other
.Name
, Other
.Access
, Other
.Description
);
208 // Access level associated with this info (public, protected, private, none).
209 // AS_public is set as default because the bitcode writer requires the enum
210 // with value 0 to be used as the default.
211 // (AS_public = 0, AS_protected = 1, AS_private = 2, AS_none = 3)
212 AccessSpecifier Access
= AccessSpecifier::AS_public
;
214 std::vector
<CommentInfo
> Description
; // Comment description of this field.
218 Location() = default;
219 Location(int LineNumber
, SmallString
<16> Filename
)
220 : LineNumber(LineNumber
), Filename(std::move(Filename
)) {}
221 Location(int LineNumber
, SmallString
<16> Filename
, bool IsFileInRootDir
)
222 : LineNumber(LineNumber
), Filename(std::move(Filename
)),
223 IsFileInRootDir(IsFileInRootDir
) {}
225 bool operator==(const Location
&Other
) const {
226 return std::tie(LineNumber
, Filename
) ==
227 std::tie(Other
.LineNumber
, Other
.Filename
);
230 // This operator is used to sort a vector of Locations.
231 // No specific order (attributes more important than others) is required. Any
232 // sort is enough, the order is only needed to call std::unique after sorting
234 bool operator<(const Location
&Other
) const {
235 return std::tie(LineNumber
, Filename
) <
236 std::tie(Other
.LineNumber
, Other
.Filename
);
239 int LineNumber
; // Line number of this Location.
240 SmallString
<32> Filename
; // File for this Location.
241 bool IsFileInRootDir
= false; // Indicates if file is inside root directory
244 /// A base struct for Infos.
247 Info(InfoType IT
) : IT(IT
) {}
248 Info(InfoType IT
, SymbolID USR
) : USR(USR
), IT(IT
) {}
249 Info(InfoType IT
, SymbolID USR
, StringRef Name
)
250 : USR(USR
), IT(IT
), Name(Name
) {}
251 Info(InfoType IT
, SymbolID USR
, StringRef Name
, StringRef Path
)
252 : USR(USR
), IT(IT
), Name(Name
), Path(Path
) {}
253 Info(const Info
&Other
) = delete;
254 Info(Info
&&Other
) = default;
256 virtual ~Info() = default;
259 SymbolID(); // Unique identifier for the decl described by this Info.
260 const InfoType IT
= InfoType::IT_default
; // InfoType of this particular Info.
261 SmallString
<16> Name
; // Unqualified name of the decl.
262 llvm::SmallVector
<Reference
, 4>
263 Namespace
; // List of parent namespaces for this decl.
264 std::vector
<CommentInfo
> Description
; // Comment description of this decl.
265 llvm::SmallString
<128> Path
; // Path of directory where the clang-doc
266 // generated file will be saved
268 void mergeBase(Info
&&I
);
269 bool mergeable(const Info
&Other
);
271 llvm::SmallString
<16> extractName() const;
273 /// Returns the file path for this Info relative to CurrentPath.
274 llvm::SmallString
<64> getRelativeFilePath(const StringRef
&CurrentPath
) const;
276 /// Returns the basename that should be used for this Info.
277 llvm::SmallString
<16> getFileBaseName() const;
279 // Returns a reference to the parent scope (that is, the immediate parent
280 // namespace or class in which this decl resides).
281 llvm::Expected
<Reference
> getEnclosingScope();
284 // Info for namespaces.
285 struct NamespaceInfo
: public Info
{
286 NamespaceInfo() : Info(InfoType::IT_namespace
) {}
287 NamespaceInfo(SymbolID USR
) : Info(InfoType::IT_namespace
, USR
) {}
288 NamespaceInfo(SymbolID USR
, StringRef Name
)
289 : Info(InfoType::IT_namespace
, USR
, Name
) {}
290 NamespaceInfo(SymbolID USR
, StringRef Name
, StringRef Path
)
291 : Info(InfoType::IT_namespace
, USR
, Name
, Path
) {}
293 void merge(NamespaceInfo
&&I
);
295 // Namespaces and Records are references because they will be properly
296 // documented in their own info, while the entirety of Functions and Enums are
297 // included here because they should not have separate documentation from
299 std::vector
<Reference
> ChildNamespaces
;
300 std::vector
<Reference
> ChildRecords
;
301 std::vector
<FunctionInfo
> ChildFunctions
;
302 std::vector
<EnumInfo
> ChildEnums
;
306 struct SymbolInfo
: public Info
{
307 SymbolInfo(InfoType IT
) : Info(IT
) {}
308 SymbolInfo(InfoType IT
, SymbolID USR
) : Info(IT
, USR
) {}
309 SymbolInfo(InfoType IT
, SymbolID USR
, StringRef Name
) : Info(IT
, USR
, Name
) {}
310 SymbolInfo(InfoType IT
, SymbolID USR
, StringRef Name
, StringRef Path
)
311 : Info(IT
, USR
, Name
, Path
) {}
313 void merge(SymbolInfo
&&I
);
315 llvm::Optional
<Location
> DefLoc
; // Location where this decl is defined.
316 llvm::SmallVector
<Location
, 2> Loc
; // Locations where this decl is declared.
319 // TODO: Expand to allow for documenting templating and default args.
320 // Info for functions.
321 struct FunctionInfo
: public SymbolInfo
{
322 FunctionInfo() : SymbolInfo(InfoType::IT_function
) {}
323 FunctionInfo(SymbolID USR
) : SymbolInfo(InfoType::IT_function
, USR
) {}
325 void merge(FunctionInfo
&&I
);
327 bool IsMethod
= false; // Indicates whether this function is a class method.
328 Reference Parent
; // Reference to the parent class decl for this method.
329 TypeInfo ReturnType
; // Info about the return type of this function.
330 llvm::SmallVector
<FieldTypeInfo
, 4> Params
; // List of parameters.
331 // Access level for this method (public, private, protected, none).
332 // AS_public is set as default because the bitcode writer requires the enum
333 // with value 0 to be used as the default.
334 // (AS_public = 0, AS_protected = 1, AS_private = 2, AS_none = 3)
335 AccessSpecifier Access
= AccessSpecifier::AS_public
;
338 // TODO: Expand to allow for documenting templating, inheritance access,
341 struct RecordInfo
: public SymbolInfo
{
342 RecordInfo() : SymbolInfo(InfoType::IT_record
) {}
343 RecordInfo(SymbolID USR
) : SymbolInfo(InfoType::IT_record
, USR
) {}
344 RecordInfo(SymbolID USR
, StringRef Name
)
345 : SymbolInfo(InfoType::IT_record
, USR
, Name
) {}
346 RecordInfo(SymbolID USR
, StringRef Name
, StringRef Path
)
347 : SymbolInfo(InfoType::IT_record
, USR
, Name
, Path
) {}
349 void merge(RecordInfo
&&I
);
351 // Type of this record (struct, class, union, interface).
352 TagTypeKind TagType
= TagTypeKind::TTK_Struct
;
354 // Indicates if the record was declared using a typedef. Things like anonymous
355 // structs in a typedef:
356 // typedef struct { ... } foo_t;
357 // are converted into records with the typedef as the Name + this flag set.
358 bool IsTypeDef
= false;
360 llvm::SmallVector
<MemberTypeInfo
, 4>
361 Members
; // List of info about record members.
362 llvm::SmallVector
<Reference
, 4> Parents
; // List of base/parent records
363 // (does not include virtual
365 llvm::SmallVector
<Reference
, 4>
366 VirtualParents
; // List of virtual base/parent records.
368 std::vector
<BaseRecordInfo
>
369 Bases
; // List of base/parent records; this includes inherited methods and
372 // Records are references because they will be properly documented in their
373 // own info, while the entirety of Functions and Enums are included here
374 // because they should not have separate documentation from their scope.
375 std::vector
<Reference
> ChildRecords
;
376 std::vector
<FunctionInfo
> ChildFunctions
;
377 std::vector
<EnumInfo
> ChildEnums
;
380 struct BaseRecordInfo
: public RecordInfo
{
381 BaseRecordInfo() : RecordInfo() {}
382 BaseRecordInfo(SymbolID USR
, StringRef Name
, StringRef Path
, bool IsVirtual
,
383 AccessSpecifier Access
, bool IsParent
)
384 : RecordInfo(USR
, Name
, Path
), IsVirtual(IsVirtual
), Access(Access
),
385 IsParent(IsParent
) {}
387 // Indicates if base corresponds to a virtual inheritance
388 bool IsVirtual
= false;
389 // Access level associated with this inherited info (public, protected,
391 AccessSpecifier Access
= AccessSpecifier::AS_public
;
392 bool IsParent
= false; // Indicates if this base is a direct parent
395 // TODO: Expand to allow for documenting templating.
397 struct EnumInfo
: public SymbolInfo
{
398 EnumInfo() : SymbolInfo(InfoType::IT_enum
) {}
399 EnumInfo(SymbolID USR
) : SymbolInfo(InfoType::IT_enum
, USR
) {}
401 void merge(EnumInfo
&&I
);
404 false; // Indicates whether this enum is scoped (e.g. enum class).
405 llvm::SmallVector
<SmallString
<16>, 4> Members
; // List of enum members.
408 struct Index
: public Reference
{
410 Index(StringRef Name
) : Reference(Name
) {}
411 Index(StringRef Name
, StringRef JumpToSection
)
412 : Reference(Name
), JumpToSection(JumpToSection
) {}
413 Index(SymbolID USR
, StringRef Name
, InfoType IT
, StringRef Path
)
414 : Reference(USR
, Name
, IT
, Path
) {}
415 // This is used to look for a USR in a vector of Indexes using std::find
416 bool operator==(const SymbolID
&Other
) const { return USR
== Other
; }
417 bool operator<(const Index
&Other
) const;
419 llvm::Optional
<SmallString
<16>> JumpToSection
;
420 std::vector
<Index
> Children
;
425 // TODO: Add functionality to include separate markdown pages.
427 // A standalone function to call to merge a vector of infos into one.
428 // This assumes that all infos in the vector are of the same type, and will fail
429 // if they are different.
430 llvm::Expected
<std::unique_ptr
<Info
>>
431 mergeInfos(std::vector
<std::unique_ptr
<Info
>> &Values
);
433 struct ClangDocContext
{
434 ClangDocContext() = default;
435 ClangDocContext(tooling::ExecutionContext
*ECtx
, StringRef ProjectName
,
436 bool PublicOnly
, StringRef OutDirectory
, StringRef SourceRoot
,
437 StringRef RepositoryUrl
,
438 std::vector
<std::string
> UserStylesheets
,
439 std::vector
<std::string
> JsScripts
);
440 tooling::ExecutionContext
*ECtx
;
441 std::string ProjectName
; // Name of project clang-doc is documenting.
442 bool PublicOnly
; // Indicates if only public declarations are documented.
443 std::string OutDirectory
; // Directory for outputting generated files.
444 std::string SourceRoot
; // Directory where processed files are stored. Links
445 // to definition locations will only be generated if
446 // the file is in this dir.
447 // URL of repository that hosts code used for links to definition locations.
448 llvm::Optional
<std::string
> RepositoryUrl
;
449 // Path of CSS stylesheets that will be copied to OutDirectory and used to
450 // style all HTML files.
451 std::vector
<std::string
> UserStylesheets
;
452 // JavaScript files that will be imported in allHTML file.
453 std::vector
<std::string
> JsScripts
;
454 // Other files that should be copied to OutDirectory, besides UserStylesheets.
455 std::vector
<std::string
> FilesToCopy
;
462 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H