150
|
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/Optional.h"
|
|
21 #include "llvm/ADT/SmallVector.h"
|
|
22 #include "llvm/ADT/StringExtras.h"
|
|
23 #include <array>
|
|
24 #include <string>
|
|
25
|
|
26 namespace clang {
|
|
27 namespace doc {
|
|
28
|
|
29 // SHA1'd hash of a USR.
|
|
30 using SymbolID = std::array<uint8_t, 20>;
|
|
31
|
|
32 struct Info;
|
|
33 struct FunctionInfo;
|
|
34 struct EnumInfo;
|
|
35 struct BaseRecordInfo;
|
|
36
|
|
37 enum class InfoType {
|
|
38 IT_default,
|
|
39 IT_namespace,
|
|
40 IT_record,
|
|
41 IT_function,
|
|
42 IT_enum
|
|
43 };
|
|
44
|
|
45 // A representation of a parsed comment.
|
|
46 struct CommentInfo {
|
|
47 CommentInfo() = default;
|
|
48 CommentInfo(CommentInfo &Other) = delete;
|
|
49 CommentInfo(CommentInfo &&Other) = default;
|
|
50 CommentInfo &operator=(CommentInfo &&Other) = default;
|
|
51
|
|
52 bool operator==(const CommentInfo &Other) const {
|
|
53 auto FirstCI = std::tie(Kind, Text, Name, Direction, ParamName, CloseName,
|
|
54 SelfClosing, Explicit, AttrKeys, AttrValues, Args);
|
|
55 auto SecondCI =
|
|
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);
|
|
59
|
|
60 if (FirstCI != SecondCI || Children.size() != Other.Children.size())
|
|
61 return false;
|
|
62
|
|
63 return std::equal(Children.begin(), Children.end(), Other.Children.begin(),
|
|
64 llvm::deref<std::equal_to<>>{});
|
|
65 }
|
|
66
|
|
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
|
|
70 // the vector.
|
|
71 bool operator<(const CommentInfo &Other) const {
|
|
72 auto FirstCI = std::tie(Kind, Text, Name, Direction, ParamName, CloseName,
|
|
73 SelfClosing, Explicit, AttrKeys, AttrValues, Args);
|
|
74 auto SecondCI =
|
|
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);
|
|
78
|
|
79 if (FirstCI < SecondCI)
|
|
80 return true;
|
|
81
|
|
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<>>());
|
|
86 }
|
|
87
|
|
88 return false;
|
|
89 }
|
|
90
|
|
91 SmallString<16>
|
|
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.
|
|
113 };
|
|
114
|
|
115 struct Reference {
|
|
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()) {}
|
|
129
|
|
130 bool operator==(const Reference &Other) const {
|
|
131 return std::tie(USR, Name, RefType) ==
|
|
132 std::tie(Other.USR, Other.Name, Other.RefType);
|
|
133 }
|
|
134
|
|
135 bool mergeable(const Reference &Other);
|
|
136 void merge(Reference &&I);
|
|
137
|
|
138 SymbolID USR = SymbolID(); // Unique identifier for referenced decl
|
|
139 SmallString<16> Name; // Name of type (possibly unresolved).
|
|
140 InfoType RefType = InfoType::IT_default; // Indicates the type of this
|
|
141 // Reference (namespace, record,
|
|
142 // function, enum, default).
|
|
143 // Path of directory where the clang-doc generated file will be saved
|
|
144 // (possibly unresolved)
|
|
145 llvm::SmallString<128> Path;
|
|
146 // Indicates if the info's parent is the global namespace, or if the info is
|
|
147 // the global namespace
|
|
148 bool IsInGlobalNamespace = false;
|
|
149 };
|
|
150
|
|
151 // A base struct for TypeInfos
|
|
152 struct TypeInfo {
|
|
153 TypeInfo() = default;
|
|
154 TypeInfo(SymbolID Type, StringRef Field, InfoType IT)
|
|
155 : Type(Type, Field, IT) {}
|
|
156 TypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path)
|
|
157 : Type(Type, Field, IT, Path) {}
|
|
158 TypeInfo(llvm::StringRef RefName) : Type(RefName) {}
|
|
159 TypeInfo(llvm::StringRef RefName, StringRef Path) : Type(RefName, Path) {}
|
|
160
|
|
161 bool operator==(const TypeInfo &Other) const { return Type == Other.Type; }
|
|
162
|
|
163 Reference Type; // Referenced type in this info.
|
|
164 };
|
|
165
|
|
166 // Info for field types.
|
|
167 struct FieldTypeInfo : public TypeInfo {
|
|
168 FieldTypeInfo() = default;
|
|
169 FieldTypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path,
|
|
170 llvm::StringRef Name)
|
|
171 : TypeInfo(Type, Field, IT, Path), Name(Name) {}
|
|
172 FieldTypeInfo(llvm::StringRef RefName, llvm::StringRef Name)
|
|
173 : TypeInfo(RefName), Name(Name) {}
|
|
174 FieldTypeInfo(llvm::StringRef RefName, StringRef Path, llvm::StringRef Name)
|
|
175 : TypeInfo(RefName, Path), Name(Name) {}
|
|
176
|
|
177 bool operator==(const FieldTypeInfo &Other) const {
|
|
178 return std::tie(Type, Name) == std::tie(Other.Type, Other.Name);
|
|
179 }
|
|
180
|
|
181 SmallString<16> Name; // Name associated with this info.
|
|
182 };
|
|
183
|
|
184 // Info for member types.
|
|
185 struct MemberTypeInfo : public FieldTypeInfo {
|
|
186 MemberTypeInfo() = default;
|
|
187 MemberTypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path,
|
|
188 llvm::StringRef Name, AccessSpecifier Access)
|
|
189 : FieldTypeInfo(Type, Field, IT, Path, Name), Access(Access) {}
|
|
190 MemberTypeInfo(llvm::StringRef RefName, llvm::StringRef Name,
|
|
191 AccessSpecifier Access)
|
|
192 : FieldTypeInfo(RefName, Name), Access(Access) {}
|
|
193 MemberTypeInfo(llvm::StringRef RefName, StringRef Path, llvm::StringRef Name,
|
|
194 AccessSpecifier Access)
|
|
195 : FieldTypeInfo(RefName, Path, Name), Access(Access) {}
|
|
196
|
|
197 bool operator==(const MemberTypeInfo &Other) const {
|
|
198 return std::tie(Type, Name, Access) ==
|
|
199 std::tie(Other.Type, Other.Name, Other.Access);
|
|
200 }
|
|
201
|
|
202 // Access level associated with this info (public, protected, private, none).
|
|
203 // AS_public is set as default because the bitcode writer requires the enum
|
|
204 // with value 0 to be used as the default.
|
|
205 // (AS_public = 0, AS_protected = 1, AS_private = 2, AS_none = 3)
|
|
206 AccessSpecifier Access = AccessSpecifier::AS_public;
|
|
207 };
|
|
208
|
|
209 struct Location {
|
|
210 Location() = default;
|
|
211 Location(int LineNumber, SmallString<16> Filename)
|
|
212 : LineNumber(LineNumber), Filename(std::move(Filename)) {}
|
|
213 Location(int LineNumber, SmallString<16> Filename, bool IsFileInRootDir)
|
|
214 : LineNumber(LineNumber), Filename(std::move(Filename)),
|
|
215 IsFileInRootDir(IsFileInRootDir) {}
|
|
216
|
|
217 bool operator==(const Location &Other) const {
|
|
218 return std::tie(LineNumber, Filename) ==
|
|
219 std::tie(Other.LineNumber, Other.Filename);
|
|
220 }
|
|
221
|
|
222 // This operator is used to sort a vector of Locations.
|
|
223 // No specific order (attributes more important than others) is required. Any
|
|
224 // sort is enough, the order is only needed to call std::unique after sorting
|
|
225 // the vector.
|
|
226 bool operator<(const Location &Other) const {
|
|
227 return std::tie(LineNumber, Filename) <
|
|
228 std::tie(Other.LineNumber, Other.Filename);
|
|
229 }
|
|
230
|
|
231 int LineNumber; // Line number of this Location.
|
|
232 SmallString<32> Filename; // File for this Location.
|
|
233 bool IsFileInRootDir = false; // Indicates if file is inside root directory
|
|
234 };
|
|
235
|
|
236 /// A base struct for Infos.
|
|
237 struct Info {
|
|
238 Info() = default;
|
|
239 Info(InfoType IT) : IT(IT) {}
|
|
240 Info(InfoType IT, SymbolID USR) : USR(USR), IT(IT) {}
|
|
241 Info(InfoType IT, SymbolID USR, StringRef Name)
|
|
242 : USR(USR), IT(IT), Name(Name) {}
|
|
243 Info(InfoType IT, SymbolID USR, StringRef Name, StringRef Path)
|
|
244 : USR(USR), IT(IT), Name(Name), Path(Path) {}
|
|
245 Info(const Info &Other) = delete;
|
|
246 Info(Info &&Other) = default;
|
|
247
|
|
248 virtual ~Info() = default;
|
|
249
|
|
250 SymbolID USR =
|
|
251 SymbolID(); // Unique identifier for the decl described by this Info.
|
|
252 const InfoType IT = InfoType::IT_default; // InfoType of this particular Info.
|
|
253 SmallString<16> Name; // Unqualified name of the decl.
|
|
254 llvm::SmallVector<Reference, 4>
|
|
255 Namespace; // List of parent namespaces for this decl.
|
|
256 std::vector<CommentInfo> Description; // Comment description of this decl.
|
|
257 llvm::SmallString<128> Path; // Path of directory where the clang-doc
|
|
258 // generated file will be saved
|
|
259
|
|
260 void mergeBase(Info &&I);
|
|
261 bool mergeable(const Info &Other);
|
|
262
|
|
263 llvm::SmallString<16> extractName() const;
|
|
264
|
|
265 // Returns a reference to the parent scope (that is, the immediate parent
|
|
266 // namespace or class in which this decl resides).
|
|
267 llvm::Expected<Reference> getEnclosingScope();
|
|
268 };
|
|
269
|
|
270 // Info for namespaces.
|
|
271 struct NamespaceInfo : public Info {
|
|
272 NamespaceInfo() : Info(InfoType::IT_namespace) {}
|
|
273 NamespaceInfo(SymbolID USR) : Info(InfoType::IT_namespace, USR) {}
|
|
274 NamespaceInfo(SymbolID USR, StringRef Name)
|
|
275 : Info(InfoType::IT_namespace, USR, Name) {}
|
|
276 NamespaceInfo(SymbolID USR, StringRef Name, StringRef Path)
|
|
277 : Info(InfoType::IT_namespace, USR, Name, Path) {}
|
|
278
|
|
279 void merge(NamespaceInfo &&I);
|
|
280
|
|
281 // Namespaces and Records are references because they will be properly
|
|
282 // documented in their own info, while the entirety of Functions and Enums are
|
|
283 // included here because they should not have separate documentation from
|
|
284 // their scope.
|
|
285 std::vector<Reference> ChildNamespaces;
|
|
286 std::vector<Reference> ChildRecords;
|
|
287 std::vector<FunctionInfo> ChildFunctions;
|
|
288 std::vector<EnumInfo> ChildEnums;
|
|
289 };
|
|
290
|
|
291 // Info for symbols.
|
|
292 struct SymbolInfo : public Info {
|
|
293 SymbolInfo(InfoType IT) : Info(IT) {}
|
|
294 SymbolInfo(InfoType IT, SymbolID USR) : Info(IT, USR) {}
|
|
295 SymbolInfo(InfoType IT, SymbolID USR, StringRef Name) : Info(IT, USR, Name) {}
|
|
296 SymbolInfo(InfoType IT, SymbolID USR, StringRef Name, StringRef Path)
|
|
297 : Info(IT, USR, Name, Path) {}
|
|
298
|
|
299 void merge(SymbolInfo &&I);
|
|
300
|
|
301 llvm::Optional<Location> DefLoc; // Location where this decl is defined.
|
|
302 llvm::SmallVector<Location, 2> Loc; // Locations where this decl is declared.
|
|
303 };
|
|
304
|
|
305 // TODO: Expand to allow for documenting templating and default args.
|
|
306 // Info for functions.
|
|
307 struct FunctionInfo : public SymbolInfo {
|
|
308 FunctionInfo() : SymbolInfo(InfoType::IT_function) {}
|
|
309 FunctionInfo(SymbolID USR) : SymbolInfo(InfoType::IT_function, USR) {}
|
|
310
|
|
311 void merge(FunctionInfo &&I);
|
|
312
|
|
313 bool IsMethod = false; // Indicates whether this function is a class method.
|
|
314 Reference Parent; // Reference to the parent class decl for this method.
|
|
315 TypeInfo ReturnType; // Info about the return type of this function.
|
|
316 llvm::SmallVector<FieldTypeInfo, 4> Params; // List of parameters.
|
|
317 // Access level for this method (public, private, protected, none).
|
|
318 // AS_public is set as default because the bitcode writer requires the enum
|
|
319 // with value 0 to be used as the default.
|
|
320 // (AS_public = 0, AS_protected = 1, AS_private = 2, AS_none = 3)
|
|
321 AccessSpecifier Access = AccessSpecifier::AS_public;
|
|
322 };
|
|
323
|
|
324 // TODO: Expand to allow for documenting templating, inheritance access,
|
|
325 // friend classes
|
|
326 // Info for types.
|
|
327 struct RecordInfo : public SymbolInfo {
|
|
328 RecordInfo() : SymbolInfo(InfoType::IT_record) {}
|
|
329 RecordInfo(SymbolID USR) : SymbolInfo(InfoType::IT_record, USR) {}
|
|
330 RecordInfo(SymbolID USR, StringRef Name)
|
|
331 : SymbolInfo(InfoType::IT_record, USR, Name) {}
|
|
332 RecordInfo(SymbolID USR, StringRef Name, StringRef Path)
|
|
333 : SymbolInfo(InfoType::IT_record, USR, Name, Path) {}
|
|
334
|
|
335 void merge(RecordInfo &&I);
|
|
336
|
|
337 TagTypeKind TagType = TagTypeKind::TTK_Struct; // Type of this record
|
|
338 // (struct, class, union,
|
|
339 // interface).
|
|
340 bool IsTypeDef = false; // Indicates if record was declared using typedef
|
|
341 llvm::SmallVector<MemberTypeInfo, 4>
|
|
342 Members; // List of info about record members.
|
|
343 llvm::SmallVector<Reference, 4> Parents; // List of base/parent records
|
|
344 // (does not include virtual
|
|
345 // parents).
|
|
346 llvm::SmallVector<Reference, 4>
|
|
347 VirtualParents; // List of virtual base/parent records.
|
|
348
|
|
349 std::vector<BaseRecordInfo>
|
|
350 Bases; // List of base/parent records; this includes inherited methods and
|
|
351 // attributes
|
|
352
|
|
353 // Records are references because they will be properly documented in their
|
|
354 // own info, while the entirety of Functions and Enums are included here
|
|
355 // because they should not have separate documentation from their scope.
|
|
356 std::vector<Reference> ChildRecords;
|
|
357 std::vector<FunctionInfo> ChildFunctions;
|
|
358 std::vector<EnumInfo> ChildEnums;
|
|
359 };
|
|
360
|
|
361 struct BaseRecordInfo : public RecordInfo {
|
|
362 BaseRecordInfo() : RecordInfo() {}
|
|
363 BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path, bool IsVirtual,
|
|
364 AccessSpecifier Access, bool IsParent)
|
|
365 : RecordInfo(USR, Name, Path), IsVirtual(IsVirtual), Access(Access),
|
|
366 IsParent(IsParent) {}
|
|
367
|
|
368 // Indicates if base corresponds to a virtual inheritance
|
|
369 bool IsVirtual = false;
|
|
370 // Access level associated with this inherited info (public, protected,
|
|
371 // private).
|
|
372 AccessSpecifier Access = AccessSpecifier::AS_public;
|
|
373 bool IsParent = false; // Indicates if this base is a direct parent
|
|
374 };
|
|
375
|
|
376 // TODO: Expand to allow for documenting templating.
|
|
377 // Info for types.
|
|
378 struct EnumInfo : public SymbolInfo {
|
|
379 EnumInfo() : SymbolInfo(InfoType::IT_enum) {}
|
|
380 EnumInfo(SymbolID USR) : SymbolInfo(InfoType::IT_enum, USR) {}
|
|
381
|
|
382 void merge(EnumInfo &&I);
|
|
383
|
|
384 bool Scoped =
|
|
385 false; // Indicates whether this enum is scoped (e.g. enum class).
|
|
386 llvm::SmallVector<SmallString<16>, 4> Members; // List of enum members.
|
|
387 };
|
|
388
|
|
389 struct Index : public Reference {
|
|
390 Index() = default;
|
|
391 Index(StringRef Name) : Reference(Name) {}
|
|
392 Index(StringRef Name, StringRef JumpToSection)
|
|
393 : Reference(Name), JumpToSection(JumpToSection) {}
|
|
394 Index(SymbolID USR, StringRef Name, InfoType IT, StringRef Path)
|
|
395 : Reference(USR, Name, IT, Path) {}
|
|
396 // This is used to look for a USR in a vector of Indexes using std::find
|
|
397 bool operator==(const SymbolID &Other) const { return USR == Other; }
|
|
398 bool operator<(const Index &Other) const;
|
|
399
|
|
400 llvm::Optional<SmallString<16>> JumpToSection;
|
|
401 std::vector<Index> Children;
|
|
402
|
|
403 void sort();
|
|
404 };
|
|
405
|
|
406 // TODO: Add functionality to include separate markdown pages.
|
|
407
|
|
408 // A standalone function to call to merge a vector of infos into one.
|
|
409 // This assumes that all infos in the vector are of the same type, and will fail
|
|
410 // if they are different.
|
|
411 llvm::Expected<std::unique_ptr<Info>>
|
|
412 mergeInfos(std::vector<std::unique_ptr<Info>> &Values);
|
|
413
|
|
414 struct ClangDocContext {
|
|
415 ClangDocContext() = default;
|
|
416 ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName,
|
|
417 bool PublicOnly, StringRef OutDirectory, StringRef SourceRoot,
|
|
418 StringRef RepositoryUrl,
|
|
419 std::vector<std::string> UserStylesheets,
|
|
420 std::vector<std::string> JsScripts);
|
|
421 tooling::ExecutionContext *ECtx;
|
|
422 std::string ProjectName; // Name of project clang-doc is documenting.
|
|
423 bool PublicOnly; // Indicates if only public declarations are documented.
|
|
424 std::string OutDirectory; // Directory for outputting generated files.
|
|
425 std::string SourceRoot; // Directory where processed files are stored. Links
|
|
426 // to definition locations will only be generated if
|
|
427 // the file is in this dir.
|
|
428 // URL of repository that hosts code used for links to definition locations.
|
|
429 llvm::Optional<std::string> RepositoryUrl;
|
|
430 // Path of CSS stylesheets that will be copied to OutDirectory and used to
|
|
431 // style all HTML files.
|
|
432 std::vector<std::string> UserStylesheets;
|
|
433 // JavaScript files that will be imported in allHTML file.
|
|
434 std::vector<std::string> JsScripts;
|
|
435 // Other files that should be copied to OutDirectory, besides UserStylesheets.
|
|
436 std::vector<std::string> FilesToCopy;
|
|
437 Index Idx;
|
|
438 };
|
|
439
|
|
440 } // namespace doc
|
|
441 } // namespace clang
|
|
442
|
|
443 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H
|