YAMLGenerator.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. //===-- YAMLGenerator.cpp - ClangDoc YAML -----------------------*- 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. // Implementation of the YAML generator, converting decl info into YAML output.
  9. //===----------------------------------------------------------------------===//
  10. #include "Generators.h"
  11. #include "llvm/Support/YAMLTraits.h"
  12. #include "llvm/Support/raw_ostream.h"
  13. using namespace clang::doc;
  14. LLVM_YAML_IS_SEQUENCE_VECTOR(FieldTypeInfo)
  15. LLVM_YAML_IS_SEQUENCE_VECTOR(MemberTypeInfo)
  16. LLVM_YAML_IS_SEQUENCE_VECTOR(Reference)
  17. LLVM_YAML_IS_SEQUENCE_VECTOR(Location)
  18. LLVM_YAML_IS_SEQUENCE_VECTOR(CommentInfo)
  19. LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionInfo)
  20. LLVM_YAML_IS_SEQUENCE_VECTOR(EnumInfo)
  21. LLVM_YAML_IS_SEQUENCE_VECTOR(BaseRecordInfo)
  22. LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<CommentInfo>)
  23. LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::SmallString<16>)
  24. namespace llvm {
  25. namespace yaml {
  26. // Enumerations to YAML output.
  27. template <> struct ScalarEnumerationTraits<clang::AccessSpecifier> {
  28. static void enumeration(IO &IO, clang::AccessSpecifier &Value) {
  29. IO.enumCase(Value, "Public", clang::AccessSpecifier::AS_public);
  30. IO.enumCase(Value, "Protected", clang::AccessSpecifier::AS_protected);
  31. IO.enumCase(Value, "Private", clang::AccessSpecifier::AS_private);
  32. IO.enumCase(Value, "None", clang::AccessSpecifier::AS_none);
  33. }
  34. };
  35. template <> struct ScalarEnumerationTraits<clang::TagTypeKind> {
  36. static void enumeration(IO &IO, clang::TagTypeKind &Value) {
  37. IO.enumCase(Value, "Struct", clang::TagTypeKind::TTK_Struct);
  38. IO.enumCase(Value, "Interface", clang::TagTypeKind::TTK_Interface);
  39. IO.enumCase(Value, "Union", clang::TagTypeKind::TTK_Union);
  40. IO.enumCase(Value, "Class", clang::TagTypeKind::TTK_Class);
  41. IO.enumCase(Value, "Enum", clang::TagTypeKind::TTK_Enum);
  42. }
  43. };
  44. template <> struct ScalarEnumerationTraits<InfoType> {
  45. static void enumeration(IO &IO, InfoType &Value) {
  46. IO.enumCase(Value, "Namespace", InfoType::IT_namespace);
  47. IO.enumCase(Value, "Record", InfoType::IT_record);
  48. IO.enumCase(Value, "Function", InfoType::IT_function);
  49. IO.enumCase(Value, "Enum", InfoType::IT_enum);
  50. IO.enumCase(Value, "Default", InfoType::IT_default);
  51. }
  52. };
  53. // Scalars to YAML output.
  54. template <unsigned U> struct ScalarTraits<SmallString<U>> {
  55. static void output(const SmallString<U> &S, void *, llvm::raw_ostream &OS) {
  56. for (const auto &C : S)
  57. OS << C;
  58. }
  59. static StringRef input(StringRef Scalar, void *, SmallString<U> &Value) {
  60. Value.assign(Scalar.begin(), Scalar.end());
  61. return StringRef();
  62. }
  63. static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
  64. };
  65. template <> struct ScalarTraits<std::array<unsigned char, 20>> {
  66. static void output(const std::array<unsigned char, 20> &S, void *,
  67. llvm::raw_ostream &OS) {
  68. OS << toHex(toStringRef(S));
  69. }
  70. static StringRef input(StringRef Scalar, void *,
  71. std::array<unsigned char, 20> &Value) {
  72. if (Scalar.size() != 40)
  73. return "Error: Incorrect scalar size for USR.";
  74. Value = StringToSymbol(Scalar);
  75. return StringRef();
  76. }
  77. static SymbolID StringToSymbol(llvm::StringRef Value) {
  78. SymbolID USR;
  79. std::string HexString = fromHex(Value);
  80. std::copy(HexString.begin(), HexString.end(), USR.begin());
  81. return SymbolID(USR);
  82. }
  83. static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
  84. };
  85. // Helper functions to map infos to YAML.
  86. static void TypeInfoMapping(IO &IO, TypeInfo &I) {
  87. IO.mapOptional("Type", I.Type, Reference());
  88. }
  89. static void FieldTypeInfoMapping(IO &IO, FieldTypeInfo &I) {
  90. TypeInfoMapping(IO, I);
  91. IO.mapOptional("Name", I.Name, SmallString<16>());
  92. }
  93. static void InfoMapping(IO &IO, Info &I) {
  94. IO.mapRequired("USR", I.USR);
  95. IO.mapOptional("Name", I.Name, SmallString<16>());
  96. IO.mapOptional("Path", I.Path, SmallString<128>());
  97. IO.mapOptional("Namespace", I.Namespace, llvm::SmallVector<Reference, 4>());
  98. IO.mapOptional("Description", I.Description);
  99. }
  100. static void SymbolInfoMapping(IO &IO, SymbolInfo &I) {
  101. InfoMapping(IO, I);
  102. IO.mapOptional("DefLocation", I.DefLoc, Optional<Location>());
  103. IO.mapOptional("Location", I.Loc, llvm::SmallVector<Location, 2>());
  104. }
  105. static void RecordInfoMapping(IO &IO, RecordInfo &I) {
  106. SymbolInfoMapping(IO, I);
  107. IO.mapOptional("TagType", I.TagType, clang::TagTypeKind::TTK_Struct);
  108. IO.mapOptional("Members", I.Members);
  109. IO.mapOptional("Bases", I.Bases);
  110. IO.mapOptional("Parents", I.Parents, llvm::SmallVector<Reference, 4>());
  111. IO.mapOptional("VirtualParents", I.VirtualParents,
  112. llvm::SmallVector<Reference, 4>());
  113. IO.mapOptional("ChildRecords", I.ChildRecords, std::vector<Reference>());
  114. IO.mapOptional("ChildFunctions", I.ChildFunctions);
  115. IO.mapOptional("ChildEnums", I.ChildEnums);
  116. }
  117. static void CommentInfoMapping(IO &IO, CommentInfo &I) {
  118. IO.mapOptional("Kind", I.Kind, SmallString<16>());
  119. IO.mapOptional("Text", I.Text, SmallString<64>());
  120. IO.mapOptional("Name", I.Name, SmallString<16>());
  121. IO.mapOptional("Direction", I.Direction, SmallString<8>());
  122. IO.mapOptional("ParamName", I.ParamName, SmallString<16>());
  123. IO.mapOptional("CloseName", I.CloseName, SmallString<16>());
  124. IO.mapOptional("SelfClosing", I.SelfClosing, false);
  125. IO.mapOptional("Explicit", I.Explicit, false);
  126. IO.mapOptional("Args", I.Args, llvm::SmallVector<SmallString<16>, 4>());
  127. IO.mapOptional("AttrKeys", I.AttrKeys,
  128. llvm::SmallVector<SmallString<16>, 4>());
  129. IO.mapOptional("AttrValues", I.AttrValues,
  130. llvm::SmallVector<SmallString<16>, 4>());
  131. IO.mapOptional("Children", I.Children);
  132. }
  133. // Template specialization to YAML traits for Infos.
  134. template <> struct MappingTraits<Location> {
  135. static void mapping(IO &IO, Location &Loc) {
  136. IO.mapOptional("LineNumber", Loc.LineNumber, 0);
  137. IO.mapOptional("Filename", Loc.Filename, SmallString<32>());
  138. }
  139. };
  140. template <> struct MappingTraits<Reference> {
  141. static void mapping(IO &IO, Reference &Ref) {
  142. IO.mapOptional("Type", Ref.RefType, InfoType::IT_default);
  143. IO.mapOptional("Name", Ref.Name, SmallString<16>());
  144. IO.mapOptional("USR", Ref.USR, SymbolID());
  145. IO.mapOptional("Path", Ref.Path, SmallString<128>());
  146. IO.mapOptional("IsInGlobalNamespace", Ref.IsInGlobalNamespace, false);
  147. }
  148. };
  149. template <> struct MappingTraits<TypeInfo> {
  150. static void mapping(IO &IO, TypeInfo &I) { TypeInfoMapping(IO, I); }
  151. };
  152. template <> struct MappingTraits<FieldTypeInfo> {
  153. static void mapping(IO &IO, FieldTypeInfo &I) {
  154. TypeInfoMapping(IO, I);
  155. IO.mapOptional("Name", I.Name, SmallString<16>());
  156. }
  157. };
  158. template <> struct MappingTraits<MemberTypeInfo> {
  159. static void mapping(IO &IO, MemberTypeInfo &I) {
  160. FieldTypeInfoMapping(IO, I);
  161. // clang::AccessSpecifier::AS_none is used as the default here because it's
  162. // the AS that shouldn't be part of the output. Even though AS_public is the
  163. // default in the struct, it should be displayed in the YAML output.
  164. IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
  165. }
  166. };
  167. template <> struct MappingTraits<NamespaceInfo> {
  168. static void mapping(IO &IO, NamespaceInfo &I) {
  169. InfoMapping(IO, I);
  170. IO.mapOptional("ChildNamespaces", I.ChildNamespaces,
  171. std::vector<Reference>());
  172. IO.mapOptional("ChildRecords", I.ChildRecords, std::vector<Reference>());
  173. IO.mapOptional("ChildFunctions", I.ChildFunctions);
  174. IO.mapOptional("ChildEnums", I.ChildEnums);
  175. }
  176. };
  177. template <> struct MappingTraits<RecordInfo> {
  178. static void mapping(IO &IO, RecordInfo &I) { RecordInfoMapping(IO, I); }
  179. };
  180. template <> struct MappingTraits<BaseRecordInfo> {
  181. static void mapping(IO &IO, BaseRecordInfo &I) {
  182. RecordInfoMapping(IO, I);
  183. IO.mapOptional("IsVirtual", I.IsVirtual, false);
  184. // clang::AccessSpecifier::AS_none is used as the default here because it's
  185. // the AS that shouldn't be part of the output. Even though AS_public is the
  186. // default in the struct, it should be displayed in the YAML output.
  187. IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
  188. IO.mapOptional("IsParent", I.IsParent, false);
  189. }
  190. };
  191. template <> struct MappingTraits<EnumInfo> {
  192. static void mapping(IO &IO, EnumInfo &I) {
  193. SymbolInfoMapping(IO, I);
  194. IO.mapOptional("Scoped", I.Scoped, false);
  195. IO.mapOptional("Members", I.Members);
  196. }
  197. };
  198. template <> struct MappingTraits<FunctionInfo> {
  199. static void mapping(IO &IO, FunctionInfo &I) {
  200. SymbolInfoMapping(IO, I);
  201. IO.mapOptional("IsMethod", I.IsMethod, false);
  202. IO.mapOptional("Parent", I.Parent, Reference());
  203. IO.mapOptional("Params", I.Params);
  204. IO.mapOptional("ReturnType", I.ReturnType);
  205. // clang::AccessSpecifier::AS_none is used as the default here because it's
  206. // the AS that shouldn't be part of the output. Even though AS_public is the
  207. // default in the struct, it should be displayed in the YAML output.
  208. IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
  209. }
  210. };
  211. template <> struct MappingTraits<CommentInfo> {
  212. static void mapping(IO &IO, CommentInfo &I) { CommentInfoMapping(IO, I); }
  213. };
  214. template <> struct MappingTraits<std::unique_ptr<CommentInfo>> {
  215. static void mapping(IO &IO, std::unique_ptr<CommentInfo> &I) {
  216. if (I)
  217. CommentInfoMapping(IO, *I);
  218. }
  219. };
  220. } // end namespace yaml
  221. } // end namespace llvm
  222. namespace clang {
  223. namespace doc {
  224. /// Generator for YAML documentation.
  225. class YAMLGenerator : public Generator {
  226. public:
  227. static const char *Format;
  228. llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS,
  229. const ClangDocContext &CDCtx) override;
  230. };
  231. const char *YAMLGenerator::Format = "yaml";
  232. llvm::Error YAMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
  233. const ClangDocContext &CDCtx) {
  234. llvm::yaml::Output InfoYAML(OS);
  235. switch (I->IT) {
  236. case InfoType::IT_namespace:
  237. InfoYAML << *static_cast<clang::doc::NamespaceInfo *>(I);
  238. break;
  239. case InfoType::IT_record:
  240. InfoYAML << *static_cast<clang::doc::RecordInfo *>(I);
  241. break;
  242. case InfoType::IT_enum:
  243. InfoYAML << *static_cast<clang::doc::EnumInfo *>(I);
  244. break;
  245. case InfoType::IT_function:
  246. InfoYAML << *static_cast<clang::doc::FunctionInfo *>(I);
  247. break;
  248. case InfoType::IT_default:
  249. return llvm::createStringError(llvm::inconvertibleErrorCode(),
  250. "unexpected InfoType");
  251. }
  252. return llvm::Error::success();
  253. }
  254. static GeneratorRegistry::Add<YAMLGenerator> YAML(YAMLGenerator::Format,
  255. "Generator for YAML output.");
  256. // This anchor is used to force the linker to link in the generated object file
  257. // and thus register the generator.
  258. volatile int YAMLGeneratorAnchorSource = 0;
  259. } // namespace doc
  260. } // namespace clang