xref: /llvm-project/clang-tools-extra/clang-doc/YAMLGenerator.cpp (revision 2c1c9a240776e5ccfb29b8a22bb32bb7e87ac2dd)
1ffe9f00cSFangrui Song //===-- YAMLGenerator.cpp - ClangDoc YAML -----------------------*- C++ -*-===//
2e78f3018SJulie Hockett //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e78f3018SJulie Hockett //
7e78f3018SJulie Hockett //===----------------------------------------------------------------------===//
8e78f3018SJulie Hockett // Implementation of the YAML generator, converting decl info into YAML output.
9e78f3018SJulie Hockett //===----------------------------------------------------------------------===//
10e78f3018SJulie Hockett 
11e78f3018SJulie Hockett #include "Generators.h"
12e78f3018SJulie Hockett #include "llvm/Support/YAMLTraits.h"
13e78f3018SJulie Hockett #include "llvm/Support/raw_ostream.h"
14e78f3018SJulie Hockett 
15e78f3018SJulie Hockett using namespace clang::doc;
16e78f3018SJulie Hockett 
17e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(FieldTypeInfo)
18e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(MemberTypeInfo)
19e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(Reference)
20e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(Location)
21e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(CommentInfo)
228899c29bSJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionInfo)
238899c29bSJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(EnumInfo)
24e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<CommentInfo>)
25e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::SmallString<16>)
26e78f3018SJulie Hockett 
27e78f3018SJulie Hockett namespace llvm {
28e78f3018SJulie Hockett namespace yaml {
29e78f3018SJulie Hockett 
30e78f3018SJulie Hockett // Enumerations to YAML output.
31e78f3018SJulie Hockett 
32e78f3018SJulie Hockett template <> struct ScalarEnumerationTraits<clang::AccessSpecifier> {
33e78f3018SJulie Hockett   static void enumeration(IO &IO, clang::AccessSpecifier &Value) {
34e78f3018SJulie Hockett     IO.enumCase(Value, "Public", clang::AccessSpecifier::AS_public);
35e78f3018SJulie Hockett     IO.enumCase(Value, "Protected", clang::AccessSpecifier::AS_protected);
36e78f3018SJulie Hockett     IO.enumCase(Value, "Private", clang::AccessSpecifier::AS_private);
37e78f3018SJulie Hockett     IO.enumCase(Value, "None", clang::AccessSpecifier::AS_none);
38e78f3018SJulie Hockett   }
39e78f3018SJulie Hockett };
40e78f3018SJulie Hockett 
41e78f3018SJulie Hockett template <> struct ScalarEnumerationTraits<clang::TagTypeKind> {
42e78f3018SJulie Hockett   static void enumeration(IO &IO, clang::TagTypeKind &Value) {
43e78f3018SJulie Hockett     IO.enumCase(Value, "Struct", clang::TagTypeKind::TTK_Struct);
44e78f3018SJulie Hockett     IO.enumCase(Value, "Interface", clang::TagTypeKind::TTK_Interface);
45e78f3018SJulie Hockett     IO.enumCase(Value, "Union", clang::TagTypeKind::TTK_Union);
46e78f3018SJulie Hockett     IO.enumCase(Value, "Class", clang::TagTypeKind::TTK_Class);
47e78f3018SJulie Hockett     IO.enumCase(Value, "Enum", clang::TagTypeKind::TTK_Enum);
48e78f3018SJulie Hockett   }
49e78f3018SJulie Hockett };
50e78f3018SJulie Hockett 
51e78f3018SJulie Hockett template <> struct ScalarEnumerationTraits<InfoType> {
52e78f3018SJulie Hockett   static void enumeration(IO &IO, InfoType &Value) {
53e78f3018SJulie Hockett     IO.enumCase(Value, "Namespace", InfoType::IT_namespace);
54e78f3018SJulie Hockett     IO.enumCase(Value, "Record", InfoType::IT_record);
55e78f3018SJulie Hockett     IO.enumCase(Value, "Function", InfoType::IT_function);
56e78f3018SJulie Hockett     IO.enumCase(Value, "Enum", InfoType::IT_enum);
57e78f3018SJulie Hockett     IO.enumCase(Value, "Default", InfoType::IT_default);
58e78f3018SJulie Hockett   }
59e78f3018SJulie Hockett };
60e78f3018SJulie Hockett 
61e78f3018SJulie Hockett // Scalars to YAML output.
62e78f3018SJulie Hockett template <unsigned U> struct ScalarTraits<SmallString<U>> {
63e78f3018SJulie Hockett 
64e78f3018SJulie Hockett   static void output(const SmallString<U> &S, void *, llvm::raw_ostream &OS) {
65e78f3018SJulie Hockett     for (const auto &C : S)
66e78f3018SJulie Hockett       OS << C;
67e78f3018SJulie Hockett   }
68e78f3018SJulie Hockett 
69e78f3018SJulie Hockett   static StringRef input(StringRef Scalar, void *, SmallString<U> &Value) {
70e78f3018SJulie Hockett     Value.assign(Scalar.begin(), Scalar.end());
71e78f3018SJulie Hockett     return StringRef();
72e78f3018SJulie Hockett   }
73e78f3018SJulie Hockett 
74e78f3018SJulie Hockett   static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
75e78f3018SJulie Hockett };
76e78f3018SJulie Hockett 
77e78f3018SJulie Hockett template <> struct ScalarTraits<std::array<unsigned char, 20>> {
78e78f3018SJulie Hockett 
79e78f3018SJulie Hockett   static void output(const std::array<unsigned char, 20> &S, void *,
80e78f3018SJulie Hockett                      llvm::raw_ostream &OS) {
81e78f3018SJulie Hockett     OS << toHex(toStringRef(S));
82e78f3018SJulie Hockett   }
83e78f3018SJulie Hockett 
84e78f3018SJulie Hockett   static StringRef input(StringRef Scalar, void *,
85e78f3018SJulie Hockett                          std::array<unsigned char, 20> &Value) {
86e78f3018SJulie Hockett     if (Scalar.size() != 40)
87e78f3018SJulie Hockett       return "Error: Incorrect scalar size for USR.";
88e78f3018SJulie Hockett     Value = StringToSymbol(Scalar);
89e78f3018SJulie Hockett     return StringRef();
90e78f3018SJulie Hockett   }
91e78f3018SJulie Hockett 
92e78f3018SJulie Hockett   static SymbolID StringToSymbol(llvm::StringRef Value) {
93e78f3018SJulie Hockett     SymbolID USR;
94e78f3018SJulie Hockett     std::string HexString = fromHex(Value);
95e78f3018SJulie Hockett     std::copy(HexString.begin(), HexString.end(), USR.begin());
96e78f3018SJulie Hockett     return SymbolID(USR);
97e78f3018SJulie Hockett   }
98e78f3018SJulie Hockett 
99e78f3018SJulie Hockett   static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
100e78f3018SJulie Hockett };
101e78f3018SJulie Hockett 
102e78f3018SJulie Hockett // Helper functions to map infos to YAML.
103e78f3018SJulie Hockett 
104e78f3018SJulie Hockett static void TypeInfoMapping(IO &IO, TypeInfo &I) {
105e78f3018SJulie Hockett   IO.mapOptional("Type", I.Type, Reference());
106e78f3018SJulie Hockett }
107e78f3018SJulie Hockett 
108e78f3018SJulie Hockett static void FieldTypeInfoMapping(IO &IO, FieldTypeInfo &I) {
109e78f3018SJulie Hockett   TypeInfoMapping(IO, I);
110e78f3018SJulie Hockett   IO.mapOptional("Name", I.Name, SmallString<16>());
111e78f3018SJulie Hockett }
112e78f3018SJulie Hockett 
113e78f3018SJulie Hockett static void InfoMapping(IO &IO, Info &I) {
114e78f3018SJulie Hockett   IO.mapRequired("USR", I.USR);
115e78f3018SJulie Hockett   IO.mapOptional("Name", I.Name, SmallString<16>());
116*2c1c9a24SJulie Hockett   IO.mapOptional("Path", I.Path, SmallString<128>());
117e78f3018SJulie Hockett   IO.mapOptional("Namespace", I.Namespace, llvm::SmallVector<Reference, 4>());
118e78f3018SJulie Hockett   IO.mapOptional("Description", I.Description);
119e78f3018SJulie Hockett }
120e78f3018SJulie Hockett 
121e78f3018SJulie Hockett static void SymbolInfoMapping(IO &IO, SymbolInfo &I) {
122e78f3018SJulie Hockett   InfoMapping(IO, I);
123e78f3018SJulie Hockett   IO.mapOptional("DefLocation", I.DefLoc, Optional<Location>());
124e78f3018SJulie Hockett   IO.mapOptional("Location", I.Loc, llvm::SmallVector<Location, 2>());
125e78f3018SJulie Hockett }
126e78f3018SJulie Hockett 
127e78f3018SJulie Hockett static void CommentInfoMapping(IO &IO, CommentInfo &I) {
128e78f3018SJulie Hockett   IO.mapOptional("Kind", I.Kind, SmallString<16>());
129e78f3018SJulie Hockett   IO.mapOptional("Text", I.Text, SmallString<64>());
130e78f3018SJulie Hockett   IO.mapOptional("Name", I.Name, SmallString<16>());
131e78f3018SJulie Hockett   IO.mapOptional("Direction", I.Direction, SmallString<8>());
132e78f3018SJulie Hockett   IO.mapOptional("ParamName", I.ParamName, SmallString<16>());
133e78f3018SJulie Hockett   IO.mapOptional("CloseName", I.CloseName, SmallString<16>());
134e78f3018SJulie Hockett   IO.mapOptional("SelfClosing", I.SelfClosing, false);
135e78f3018SJulie Hockett   IO.mapOptional("Explicit", I.Explicit, false);
136e78f3018SJulie Hockett   IO.mapOptional("Args", I.Args, llvm::SmallVector<SmallString<16>, 4>());
137e78f3018SJulie Hockett   IO.mapOptional("AttrKeys", I.AttrKeys,
138e78f3018SJulie Hockett                  llvm::SmallVector<SmallString<16>, 4>());
139e78f3018SJulie Hockett   IO.mapOptional("AttrValues", I.AttrValues,
140e78f3018SJulie Hockett                  llvm::SmallVector<SmallString<16>, 4>());
141e78f3018SJulie Hockett   IO.mapOptional("Children", I.Children);
142e78f3018SJulie Hockett }
143e78f3018SJulie Hockett 
144e78f3018SJulie Hockett // Template specialization to YAML traits for Infos.
145e78f3018SJulie Hockett 
146e78f3018SJulie Hockett template <> struct MappingTraits<Location> {
147e78f3018SJulie Hockett   static void mapping(IO &IO, Location &Loc) {
148e78f3018SJulie Hockett     IO.mapOptional("LineNumber", Loc.LineNumber, 0);
149e78f3018SJulie Hockett     IO.mapOptional("Filename", Loc.Filename, SmallString<32>());
150e78f3018SJulie Hockett   }
151e78f3018SJulie Hockett };
152e78f3018SJulie Hockett 
153e78f3018SJulie Hockett template <> struct MappingTraits<Reference> {
154e78f3018SJulie Hockett   static void mapping(IO &IO, Reference &Ref) {
155e78f3018SJulie Hockett     IO.mapOptional("Type", Ref.RefType, InfoType::IT_default);
156e78f3018SJulie Hockett     IO.mapOptional("Name", Ref.Name, SmallString<16>());
157e78f3018SJulie Hockett     IO.mapOptional("USR", Ref.USR, SymbolID());
158*2c1c9a24SJulie Hockett     IO.mapOptional("Path", Ref.Path, SmallString<128>());
159e78f3018SJulie Hockett   }
160e78f3018SJulie Hockett };
161e78f3018SJulie Hockett 
162e78f3018SJulie Hockett template <> struct MappingTraits<TypeInfo> {
163e78f3018SJulie Hockett   static void mapping(IO &IO, TypeInfo &I) { TypeInfoMapping(IO, I); }
164e78f3018SJulie Hockett };
165e78f3018SJulie Hockett 
166e78f3018SJulie Hockett template <> struct MappingTraits<FieldTypeInfo> {
167e78f3018SJulie Hockett   static void mapping(IO &IO, FieldTypeInfo &I) {
168e78f3018SJulie Hockett     TypeInfoMapping(IO, I);
169e78f3018SJulie Hockett     IO.mapOptional("Name", I.Name, SmallString<16>());
170e78f3018SJulie Hockett   }
171e78f3018SJulie Hockett };
172e78f3018SJulie Hockett 
173e78f3018SJulie Hockett template <> struct MappingTraits<MemberTypeInfo> {
174e78f3018SJulie Hockett   static void mapping(IO &IO, MemberTypeInfo &I) {
175e78f3018SJulie Hockett     FieldTypeInfoMapping(IO, I);
176e78f3018SJulie Hockett     IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
177e78f3018SJulie Hockett   }
178e78f3018SJulie Hockett };
179e78f3018SJulie Hockett 
180e78f3018SJulie Hockett template <> struct MappingTraits<NamespaceInfo> {
1818899c29bSJulie Hockett   static void mapping(IO &IO, NamespaceInfo &I) {
1828899c29bSJulie Hockett     InfoMapping(IO, I);
1838899c29bSJulie Hockett     IO.mapOptional("ChildNamespaces", I.ChildNamespaces,
1848899c29bSJulie Hockett                    std::vector<Reference>());
1858899c29bSJulie Hockett     IO.mapOptional("ChildRecords", I.ChildRecords, std::vector<Reference>());
1868899c29bSJulie Hockett     IO.mapOptional("ChildFunctions", I.ChildFunctions);
1878899c29bSJulie Hockett     IO.mapOptional("ChildEnums", I.ChildEnums);
1888899c29bSJulie Hockett   }
189e78f3018SJulie Hockett };
190e78f3018SJulie Hockett 
191e78f3018SJulie Hockett template <> struct MappingTraits<RecordInfo> {
192e78f3018SJulie Hockett   static void mapping(IO &IO, RecordInfo &I) {
193e78f3018SJulie Hockett     SymbolInfoMapping(IO, I);
194e78f3018SJulie Hockett     IO.mapOptional("TagType", I.TagType, clang::TagTypeKind::TTK_Struct);
195e78f3018SJulie Hockett     IO.mapOptional("Members", I.Members);
196e78f3018SJulie Hockett     IO.mapOptional("Parents", I.Parents, llvm::SmallVector<Reference, 4>());
197e78f3018SJulie Hockett     IO.mapOptional("VirtualParents", I.VirtualParents,
198e78f3018SJulie Hockett                    llvm::SmallVector<Reference, 4>());
1998899c29bSJulie Hockett     IO.mapOptional("ChildRecords", I.ChildRecords, std::vector<Reference>());
2008899c29bSJulie Hockett     IO.mapOptional("ChildFunctions", I.ChildFunctions);
2018899c29bSJulie Hockett     IO.mapOptional("ChildEnums", I.ChildEnums);
202e78f3018SJulie Hockett   }
203e78f3018SJulie Hockett };
204e78f3018SJulie Hockett 
205e78f3018SJulie Hockett template <> struct MappingTraits<EnumInfo> {
206e78f3018SJulie Hockett   static void mapping(IO &IO, EnumInfo &I) {
207e78f3018SJulie Hockett     SymbolInfoMapping(IO, I);
208e78f3018SJulie Hockett     IO.mapOptional("Scoped", I.Scoped, false);
209e78f3018SJulie Hockett     IO.mapOptional("Members", I.Members);
210e78f3018SJulie Hockett   }
211e78f3018SJulie Hockett };
212e78f3018SJulie Hockett 
213e78f3018SJulie Hockett template <> struct MappingTraits<FunctionInfo> {
214e78f3018SJulie Hockett   static void mapping(IO &IO, FunctionInfo &I) {
215e78f3018SJulie Hockett     SymbolInfoMapping(IO, I);
216e78f3018SJulie Hockett     IO.mapOptional("IsMethod", I.IsMethod, false);
217e78f3018SJulie Hockett     IO.mapOptional("Parent", I.Parent, Reference());
218e78f3018SJulie Hockett     IO.mapOptional("Params", I.Params);
219e78f3018SJulie Hockett     IO.mapOptional("ReturnType", I.ReturnType);
220e78f3018SJulie Hockett     IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
221e78f3018SJulie Hockett   }
222e78f3018SJulie Hockett };
223e78f3018SJulie Hockett 
224e78f3018SJulie Hockett template <> struct MappingTraits<CommentInfo> {
225e78f3018SJulie Hockett   static void mapping(IO &IO, CommentInfo &I) { CommentInfoMapping(IO, I); }
226e78f3018SJulie Hockett };
227e78f3018SJulie Hockett 
228e78f3018SJulie Hockett template <> struct MappingTraits<std::unique_ptr<CommentInfo>> {
229e78f3018SJulie Hockett   static void mapping(IO &IO, std::unique_ptr<CommentInfo> &I) {
230e78f3018SJulie Hockett     if (I)
231e78f3018SJulie Hockett       CommentInfoMapping(IO, *I);
232e78f3018SJulie Hockett   }
233e78f3018SJulie Hockett };
234e78f3018SJulie Hockett 
235e78f3018SJulie Hockett } // end namespace yaml
236e78f3018SJulie Hockett } // end namespace llvm
237e78f3018SJulie Hockett 
238e78f3018SJulie Hockett namespace clang {
239e78f3018SJulie Hockett namespace doc {
240e78f3018SJulie Hockett 
241e78f3018SJulie Hockett /// Generator for YAML documentation.
242e78f3018SJulie Hockett class YAMLGenerator : public Generator {
243e78f3018SJulie Hockett public:
244e78f3018SJulie Hockett   static const char *Format;
245e78f3018SJulie Hockett 
246ac68cab9SJulie Hockett   llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS) override;
247e78f3018SJulie Hockett };
248e78f3018SJulie Hockett 
249e78f3018SJulie Hockett const char *YAMLGenerator::Format = "yaml";
250e78f3018SJulie Hockett 
251ac68cab9SJulie Hockett llvm::Error YAMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS) {
252e78f3018SJulie Hockett   llvm::yaml::Output InfoYAML(OS);
253e78f3018SJulie Hockett   switch (I->IT) {
254e78f3018SJulie Hockett   case InfoType::IT_namespace:
255e78f3018SJulie Hockett     InfoYAML << *static_cast<clang::doc::NamespaceInfo *>(I);
256e78f3018SJulie Hockett     break;
257e78f3018SJulie Hockett   case InfoType::IT_record:
258e78f3018SJulie Hockett     InfoYAML << *static_cast<clang::doc::RecordInfo *>(I);
259e78f3018SJulie Hockett     break;
260e78f3018SJulie Hockett   case InfoType::IT_enum:
261e78f3018SJulie Hockett     InfoYAML << *static_cast<clang::doc::EnumInfo *>(I);
262e78f3018SJulie Hockett     break;
263e78f3018SJulie Hockett   case InfoType::IT_function:
264e78f3018SJulie Hockett     InfoYAML << *static_cast<clang::doc::FunctionInfo *>(I);
265e78f3018SJulie Hockett     break;
266e78f3018SJulie Hockett   case InfoType::IT_default:
267ac68cab9SJulie Hockett     return llvm::make_error<llvm::StringError>("Unexpected info type.\n",
268ac68cab9SJulie Hockett                                                llvm::inconvertibleErrorCode());
269e78f3018SJulie Hockett   }
270ac68cab9SJulie Hockett   return llvm::Error::success();
271e78f3018SJulie Hockett }
272e78f3018SJulie Hockett 
273e78f3018SJulie Hockett static GeneratorRegistry::Add<YAMLGenerator> YAML(YAMLGenerator::Format,
274e78f3018SJulie Hockett                                                   "Generator for YAML output.");
275e78f3018SJulie Hockett 
276e78f3018SJulie Hockett // This anchor is used to force the linker to link in the generated object file
277e78f3018SJulie Hockett // and thus register the generator.
278e78f3018SJulie Hockett volatile int YAMLGeneratorAnchorSource = 0;
279e78f3018SJulie Hockett 
280e78f3018SJulie Hockett } // namespace doc
281e78f3018SJulie Hockett } // namespace clang
282