Representation.h 18 KB

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