xref: /llvm-project/clang-tools-extra/clang-doc/YAMLGenerator.cpp (revision edd690b02e16e991393bf7f67631196942369aed)
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"
124a68babdSBrett Wilson #include "Representation.h"
13e78f3018SJulie Hockett #include "llvm/Support/YAMLTraits.h"
14e78f3018SJulie Hockett #include "llvm/Support/raw_ostream.h"
15c589730aSKrzysztof Parzyszek #include <optional>
16e78f3018SJulie Hockett 
17e78f3018SJulie Hockett using namespace clang::doc;
18e78f3018SJulie Hockett 
19eaa7b324SBrett Wilson // These define YAML traits for decoding the listed values within a vector.
20e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(FieldTypeInfo)
21e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(MemberTypeInfo)
22e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(Reference)
23e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(Location)
24e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(CommentInfo)
258899c29bSJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionInfo)
268899c29bSJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(EnumInfo)
27eaa7b324SBrett Wilson LLVM_YAML_IS_SEQUENCE_VECTOR(EnumValueInfo)
284a68babdSBrett Wilson LLVM_YAML_IS_SEQUENCE_VECTOR(TemplateParamInfo)
2921fb70c6SBrett Wilson LLVM_YAML_IS_SEQUENCE_VECTOR(TypedefInfo)
30ba3d595fSDiego Astiazaran LLVM_YAML_IS_SEQUENCE_VECTOR(BaseRecordInfo)
31e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<CommentInfo>)
32e78f3018SJulie Hockett LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::SmallString<16>)
33e78f3018SJulie Hockett 
34e78f3018SJulie Hockett namespace llvm {
35e78f3018SJulie Hockett namespace yaml {
36e78f3018SJulie Hockett 
37e78f3018SJulie Hockett // Enumerations to YAML output.
38e78f3018SJulie Hockett 
39e78f3018SJulie Hockett template <> struct ScalarEnumerationTraits<clang::AccessSpecifier> {
enumerationllvm::yaml::ScalarEnumerationTraits40e78f3018SJulie Hockett   static void enumeration(IO &IO, clang::AccessSpecifier &Value) {
41e78f3018SJulie Hockett     IO.enumCase(Value, "Public", clang::AccessSpecifier::AS_public);
42e78f3018SJulie Hockett     IO.enumCase(Value, "Protected", clang::AccessSpecifier::AS_protected);
43e78f3018SJulie Hockett     IO.enumCase(Value, "Private", clang::AccessSpecifier::AS_private);
44e78f3018SJulie Hockett     IO.enumCase(Value, "None", clang::AccessSpecifier::AS_none);
45e78f3018SJulie Hockett   }
46e78f3018SJulie Hockett };
47e78f3018SJulie Hockett 
48e78f3018SJulie Hockett template <> struct ScalarEnumerationTraits<clang::TagTypeKind> {
enumerationllvm::yaml::ScalarEnumerationTraits49e78f3018SJulie Hockett   static void enumeration(IO &IO, clang::TagTypeKind &Value) {
50*edd690b0SVlad Serebrennikov     IO.enumCase(Value, "Struct", clang::TagTypeKind::Struct);
51*edd690b0SVlad Serebrennikov     IO.enumCase(Value, "Interface", clang::TagTypeKind::Interface);
52*edd690b0SVlad Serebrennikov     IO.enumCase(Value, "Union", clang::TagTypeKind::Union);
53*edd690b0SVlad Serebrennikov     IO.enumCase(Value, "Class", clang::TagTypeKind::Class);
54*edd690b0SVlad Serebrennikov     IO.enumCase(Value, "Enum", clang::TagTypeKind::Enum);
55e78f3018SJulie Hockett   }
56e78f3018SJulie Hockett };
57e78f3018SJulie Hockett 
58e78f3018SJulie Hockett template <> struct ScalarEnumerationTraits<InfoType> {
enumerationllvm::yaml::ScalarEnumerationTraits59e78f3018SJulie Hockett   static void enumeration(IO &IO, InfoType &Value) {
60e78f3018SJulie Hockett     IO.enumCase(Value, "Namespace", InfoType::IT_namespace);
61e78f3018SJulie Hockett     IO.enumCase(Value, "Record", InfoType::IT_record);
62e78f3018SJulie Hockett     IO.enumCase(Value, "Function", InfoType::IT_function);
63e78f3018SJulie Hockett     IO.enumCase(Value, "Enum", InfoType::IT_enum);
64e78f3018SJulie Hockett     IO.enumCase(Value, "Default", InfoType::IT_default);
65e78f3018SJulie Hockett   }
66e78f3018SJulie Hockett };
67e78f3018SJulie Hockett 
68e78f3018SJulie Hockett // Scalars to YAML output.
69e78f3018SJulie Hockett template <unsigned U> struct ScalarTraits<SmallString<U>> {
70e78f3018SJulie Hockett 
outputllvm::yaml::ScalarTraits71e78f3018SJulie Hockett   static void output(const SmallString<U> &S, void *, llvm::raw_ostream &OS) {
72e78f3018SJulie Hockett     for (const auto &C : S)
73e78f3018SJulie Hockett       OS << C;
74e78f3018SJulie Hockett   }
75e78f3018SJulie Hockett 
inputllvm::yaml::ScalarTraits76e78f3018SJulie Hockett   static StringRef input(StringRef Scalar, void *, SmallString<U> &Value) {
77e78f3018SJulie Hockett     Value.assign(Scalar.begin(), Scalar.end());
78e78f3018SJulie Hockett     return StringRef();
79e78f3018SJulie Hockett   }
80e78f3018SJulie Hockett 
mustQuotellvm::yaml::ScalarTraits81e78f3018SJulie Hockett   static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
82e78f3018SJulie Hockett };
83e78f3018SJulie Hockett 
84e78f3018SJulie Hockett template <> struct ScalarTraits<std::array<unsigned char, 20>> {
85e78f3018SJulie Hockett 
outputllvm::yaml::ScalarTraits86e78f3018SJulie Hockett   static void output(const std::array<unsigned char, 20> &S, void *,
87e78f3018SJulie Hockett                      llvm::raw_ostream &OS) {
88e78f3018SJulie Hockett     OS << toHex(toStringRef(S));
89e78f3018SJulie Hockett   }
90e78f3018SJulie Hockett 
inputllvm::yaml::ScalarTraits91e78f3018SJulie Hockett   static StringRef input(StringRef Scalar, void *,
92e78f3018SJulie Hockett                          std::array<unsigned char, 20> &Value) {
93e78f3018SJulie Hockett     if (Scalar.size() != 40)
94e78f3018SJulie Hockett       return "Error: Incorrect scalar size for USR.";
95e78f3018SJulie Hockett     Value = StringToSymbol(Scalar);
96e78f3018SJulie Hockett     return StringRef();
97e78f3018SJulie Hockett   }
98e78f3018SJulie Hockett 
StringToSymbolllvm::yaml::ScalarTraits99e78f3018SJulie Hockett   static SymbolID StringToSymbol(llvm::StringRef Value) {
100e78f3018SJulie Hockett     SymbolID USR;
101e78f3018SJulie Hockett     std::string HexString = fromHex(Value);
102e78f3018SJulie Hockett     std::copy(HexString.begin(), HexString.end(), USR.begin());
103e78f3018SJulie Hockett     return SymbolID(USR);
104e78f3018SJulie Hockett   }
105e78f3018SJulie Hockett 
mustQuotellvm::yaml::ScalarTraits106e78f3018SJulie Hockett   static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
107e78f3018SJulie Hockett };
108e78f3018SJulie Hockett 
109e78f3018SJulie Hockett // Helper functions to map infos to YAML.
110e78f3018SJulie Hockett 
TypeInfoMapping(IO & IO,TypeInfo & I)111e78f3018SJulie Hockett static void TypeInfoMapping(IO &IO, TypeInfo &I) {
112e78f3018SJulie Hockett   IO.mapOptional("Type", I.Type, Reference());
113e78f3018SJulie Hockett }
114e78f3018SJulie Hockett 
FieldTypeInfoMapping(IO & IO,FieldTypeInfo & I)115e78f3018SJulie Hockett static void FieldTypeInfoMapping(IO &IO, FieldTypeInfo &I) {
116e78f3018SJulie Hockett   TypeInfoMapping(IO, I);
117e78f3018SJulie Hockett   IO.mapOptional("Name", I.Name, SmallString<16>());
118e191086bSBrett Wilson   IO.mapOptional("DefaultValue", I.DefaultValue, SmallString<16>());
119e78f3018SJulie Hockett }
120e78f3018SJulie Hockett 
InfoMapping(IO & IO,Info & I)121e78f3018SJulie Hockett static void InfoMapping(IO &IO, Info &I) {
122e78f3018SJulie Hockett   IO.mapRequired("USR", I.USR);
123e78f3018SJulie Hockett   IO.mapOptional("Name", I.Name, SmallString<16>());
1242c1c9a24SJulie Hockett   IO.mapOptional("Path", I.Path, SmallString<128>());
125e78f3018SJulie Hockett   IO.mapOptional("Namespace", I.Namespace, llvm::SmallVector<Reference, 4>());
126e78f3018SJulie Hockett   IO.mapOptional("Description", I.Description);
127e78f3018SJulie Hockett }
128e78f3018SJulie Hockett 
SymbolInfoMapping(IO & IO,SymbolInfo & I)129e78f3018SJulie Hockett static void SymbolInfoMapping(IO &IO, SymbolInfo &I) {
130e78f3018SJulie Hockett   InfoMapping(IO, I);
131c589730aSKrzysztof Parzyszek   IO.mapOptional("DefLocation", I.DefLoc, std::optional<Location>());
132e78f3018SJulie Hockett   IO.mapOptional("Location", I.Loc, llvm::SmallVector<Location, 2>());
133e78f3018SJulie Hockett }
134e78f3018SJulie Hockett 
RecordInfoMapping(IO & IO,RecordInfo & I)135ba3d595fSDiego Astiazaran static void RecordInfoMapping(IO &IO, RecordInfo &I) {
136ba3d595fSDiego Astiazaran   SymbolInfoMapping(IO, I);
13768266828SBrett Wilson   IO.mapOptional("TagType", I.TagType);
13868266828SBrett Wilson   IO.mapOptional("IsTypeDef", I.IsTypeDef, false);
139ba3d595fSDiego Astiazaran   IO.mapOptional("Members", I.Members);
140ba3d595fSDiego Astiazaran   IO.mapOptional("Bases", I.Bases);
141ba3d595fSDiego Astiazaran   IO.mapOptional("Parents", I.Parents, llvm::SmallVector<Reference, 4>());
142ba3d595fSDiego Astiazaran   IO.mapOptional("VirtualParents", I.VirtualParents,
143ba3d595fSDiego Astiazaran                  llvm::SmallVector<Reference, 4>());
14421fb70c6SBrett Wilson   IO.mapOptional("ChildRecords", I.Children.Records, std::vector<Reference>());
14521fb70c6SBrett Wilson   IO.mapOptional("ChildFunctions", I.Children.Functions);
14621fb70c6SBrett Wilson   IO.mapOptional("ChildEnums", I.Children.Enums);
14721fb70c6SBrett Wilson   IO.mapOptional("ChildTypedefs", I.Children.Typedefs);
1484a68babdSBrett Wilson   IO.mapOptional("Template", I.Template);
149ba3d595fSDiego Astiazaran }
150ba3d595fSDiego Astiazaran 
CommentInfoMapping(IO & IO,CommentInfo & I)151e78f3018SJulie Hockett static void CommentInfoMapping(IO &IO, CommentInfo &I) {
152e78f3018SJulie Hockett   IO.mapOptional("Kind", I.Kind, SmallString<16>());
153e78f3018SJulie Hockett   IO.mapOptional("Text", I.Text, SmallString<64>());
154e78f3018SJulie Hockett   IO.mapOptional("Name", I.Name, SmallString<16>());
155e78f3018SJulie Hockett   IO.mapOptional("Direction", I.Direction, SmallString<8>());
156e78f3018SJulie Hockett   IO.mapOptional("ParamName", I.ParamName, SmallString<16>());
157e78f3018SJulie Hockett   IO.mapOptional("CloseName", I.CloseName, SmallString<16>());
158e78f3018SJulie Hockett   IO.mapOptional("SelfClosing", I.SelfClosing, false);
159e78f3018SJulie Hockett   IO.mapOptional("Explicit", I.Explicit, false);
160e78f3018SJulie Hockett   IO.mapOptional("Args", I.Args, llvm::SmallVector<SmallString<16>, 4>());
161e78f3018SJulie Hockett   IO.mapOptional("AttrKeys", I.AttrKeys,
162e78f3018SJulie Hockett                  llvm::SmallVector<SmallString<16>, 4>());
163e78f3018SJulie Hockett   IO.mapOptional("AttrValues", I.AttrValues,
164e78f3018SJulie Hockett                  llvm::SmallVector<SmallString<16>, 4>());
165e78f3018SJulie Hockett   IO.mapOptional("Children", I.Children);
166e78f3018SJulie Hockett }
167e78f3018SJulie Hockett 
168e78f3018SJulie Hockett // Template specialization to YAML traits for Infos.
169e78f3018SJulie Hockett 
170e78f3018SJulie Hockett template <> struct MappingTraits<Location> {
mappingllvm::yaml::MappingTraits171e78f3018SJulie Hockett   static void mapping(IO &IO, Location &Loc) {
172e78f3018SJulie Hockett     IO.mapOptional("LineNumber", Loc.LineNumber, 0);
173e78f3018SJulie Hockett     IO.mapOptional("Filename", Loc.Filename, SmallString<32>());
174e78f3018SJulie Hockett   }
175e78f3018SJulie Hockett };
176e78f3018SJulie Hockett 
177e78f3018SJulie Hockett template <> struct MappingTraits<Reference> {
mappingllvm::yaml::MappingTraits178e78f3018SJulie Hockett   static void mapping(IO &IO, Reference &Ref) {
179e78f3018SJulie Hockett     IO.mapOptional("Type", Ref.RefType, InfoType::IT_default);
180e78f3018SJulie Hockett     IO.mapOptional("Name", Ref.Name, SmallString<16>());
1814a68babdSBrett Wilson     IO.mapOptional("QualName", Ref.QualName, SmallString<16>());
182e78f3018SJulie Hockett     IO.mapOptional("USR", Ref.USR, SymbolID());
1832c1c9a24SJulie Hockett     IO.mapOptional("Path", Ref.Path, SmallString<128>());
184e78f3018SJulie Hockett   }
185e78f3018SJulie Hockett };
186e78f3018SJulie Hockett 
187e78f3018SJulie Hockett template <> struct MappingTraits<TypeInfo> {
mappingllvm::yaml::MappingTraits188e78f3018SJulie Hockett   static void mapping(IO &IO, TypeInfo &I) { TypeInfoMapping(IO, I); }
189e78f3018SJulie Hockett };
190e78f3018SJulie Hockett 
191e78f3018SJulie Hockett template <> struct MappingTraits<FieldTypeInfo> {
mappingllvm::yaml::MappingTraits192e78f3018SJulie Hockett   static void mapping(IO &IO, FieldTypeInfo &I) {
193e78f3018SJulie Hockett     TypeInfoMapping(IO, I);
194e78f3018SJulie Hockett     IO.mapOptional("Name", I.Name, SmallString<16>());
195e191086bSBrett Wilson     IO.mapOptional("DefaultValue", I.DefaultValue, SmallString<16>());
196e78f3018SJulie Hockett   }
197e78f3018SJulie Hockett };
198e78f3018SJulie Hockett 
199e78f3018SJulie Hockett template <> struct MappingTraits<MemberTypeInfo> {
mappingllvm::yaml::MappingTraits200e78f3018SJulie Hockett   static void mapping(IO &IO, MemberTypeInfo &I) {
201e78f3018SJulie Hockett     FieldTypeInfoMapping(IO, I);
2026a29ae4bSDiego Astiazaran     // clang::AccessSpecifier::AS_none is used as the default here because it's
2036a29ae4bSDiego Astiazaran     // the AS that shouldn't be part of the output. Even though AS_public is the
2046a29ae4bSDiego Astiazaran     // default in the struct, it should be displayed in the YAML output.
205e78f3018SJulie Hockett     IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
20699baa10fSBrett Wilson     IO.mapOptional("Description", I.Description);
207e78f3018SJulie Hockett   }
208e78f3018SJulie Hockett };
209e78f3018SJulie Hockett 
210e78f3018SJulie Hockett template <> struct MappingTraits<NamespaceInfo> {
mappingllvm::yaml::MappingTraits2118899c29bSJulie Hockett   static void mapping(IO &IO, NamespaceInfo &I) {
2128899c29bSJulie Hockett     InfoMapping(IO, I);
21321fb70c6SBrett Wilson     IO.mapOptional("ChildNamespaces", I.Children.Namespaces,
2148899c29bSJulie Hockett                    std::vector<Reference>());
21521fb70c6SBrett Wilson     IO.mapOptional("ChildRecords", I.Children.Records,
21621fb70c6SBrett Wilson                    std::vector<Reference>());
21721fb70c6SBrett Wilson     IO.mapOptional("ChildFunctions", I.Children.Functions);
21821fb70c6SBrett Wilson     IO.mapOptional("ChildEnums", I.Children.Enums);
21921fb70c6SBrett Wilson     IO.mapOptional("ChildTypedefs", I.Children.Typedefs);
2208899c29bSJulie Hockett   }
221e78f3018SJulie Hockett };
222e78f3018SJulie Hockett 
223e78f3018SJulie Hockett template <> struct MappingTraits<RecordInfo> {
mappingllvm::yaml::MappingTraits224ba3d595fSDiego Astiazaran   static void mapping(IO &IO, RecordInfo &I) { RecordInfoMapping(IO, I); }
225ba3d595fSDiego Astiazaran };
226ba3d595fSDiego Astiazaran 
227ba3d595fSDiego Astiazaran template <> struct MappingTraits<BaseRecordInfo> {
mappingllvm::yaml::MappingTraits228ba3d595fSDiego Astiazaran   static void mapping(IO &IO, BaseRecordInfo &I) {
229ba3d595fSDiego Astiazaran     RecordInfoMapping(IO, I);
230ba3d595fSDiego Astiazaran     IO.mapOptional("IsVirtual", I.IsVirtual, false);
231ba3d595fSDiego Astiazaran     // clang::AccessSpecifier::AS_none is used as the default here because it's
232ba3d595fSDiego Astiazaran     // the AS that shouldn't be part of the output. Even though AS_public is the
233ba3d595fSDiego Astiazaran     // default in the struct, it should be displayed in the YAML output.
234ba3d595fSDiego Astiazaran     IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
235ba3d595fSDiego Astiazaran     IO.mapOptional("IsParent", I.IsParent, false);
236e78f3018SJulie Hockett   }
237e78f3018SJulie Hockett };
238e78f3018SJulie Hockett 
239eaa7b324SBrett Wilson template <> struct MappingTraits<EnumValueInfo> {
mappingllvm::yaml::MappingTraits240eaa7b324SBrett Wilson   static void mapping(IO &IO, EnumValueInfo &I) {
241eaa7b324SBrett Wilson     IO.mapOptional("Name", I.Name);
242eaa7b324SBrett Wilson     IO.mapOptional("Value", I.Value);
243eaa7b324SBrett Wilson     IO.mapOptional("Expr", I.ValueExpr, SmallString<16>());
244eaa7b324SBrett Wilson   }
245eaa7b324SBrett Wilson };
246eaa7b324SBrett Wilson 
247e78f3018SJulie Hockett template <> struct MappingTraits<EnumInfo> {
mappingllvm::yaml::MappingTraits248e78f3018SJulie Hockett   static void mapping(IO &IO, EnumInfo &I) {
249e78f3018SJulie Hockett     SymbolInfoMapping(IO, I);
250e78f3018SJulie Hockett     IO.mapOptional("Scoped", I.Scoped, false);
251eaa7b324SBrett Wilson     IO.mapOptional("BaseType", I.BaseType);
252e78f3018SJulie Hockett     IO.mapOptional("Members", I.Members);
253e78f3018SJulie Hockett   }
254e78f3018SJulie Hockett };
255e78f3018SJulie Hockett 
25621fb70c6SBrett Wilson template <> struct MappingTraits<TypedefInfo> {
mappingllvm::yaml::MappingTraits25721fb70c6SBrett Wilson   static void mapping(IO &IO, TypedefInfo &I) {
25821fb70c6SBrett Wilson     SymbolInfoMapping(IO, I);
25921fb70c6SBrett Wilson     IO.mapOptional("Underlying", I.Underlying.Type);
26021fb70c6SBrett Wilson     IO.mapOptional("IsUsing", I.IsUsing, false);
26121fb70c6SBrett Wilson   }
26221fb70c6SBrett Wilson };
26321fb70c6SBrett Wilson 
264e78f3018SJulie Hockett template <> struct MappingTraits<FunctionInfo> {
mappingllvm::yaml::MappingTraits265e78f3018SJulie Hockett   static void mapping(IO &IO, FunctionInfo &I) {
266e78f3018SJulie Hockett     SymbolInfoMapping(IO, I);
267e78f3018SJulie Hockett     IO.mapOptional("IsMethod", I.IsMethod, false);
268e78f3018SJulie Hockett     IO.mapOptional("Parent", I.Parent, Reference());
269e78f3018SJulie Hockett     IO.mapOptional("Params", I.Params);
270e78f3018SJulie Hockett     IO.mapOptional("ReturnType", I.ReturnType);
2716a29ae4bSDiego Astiazaran     // clang::AccessSpecifier::AS_none is used as the default here because it's
2726a29ae4bSDiego Astiazaran     // the AS that shouldn't be part of the output. Even though AS_public is the
2736a29ae4bSDiego Astiazaran     // default in the struct, it should be displayed in the YAML output.
274e78f3018SJulie Hockett     IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
2754a68babdSBrett Wilson     IO.mapOptional("Template", I.Template);
2764a68babdSBrett Wilson   }
2774a68babdSBrett Wilson };
2784a68babdSBrett Wilson 
2794a68babdSBrett Wilson template <> struct MappingTraits<TemplateParamInfo> {
mappingllvm::yaml::MappingTraits2804a68babdSBrett Wilson   static void mapping(IO &IO, TemplateParamInfo &I) {
2814a68babdSBrett Wilson     IO.mapOptional("Contents", I.Contents);
2824a68babdSBrett Wilson   }
2834a68babdSBrett Wilson };
2844a68babdSBrett Wilson 
2854a68babdSBrett Wilson template <> struct MappingTraits<TemplateSpecializationInfo> {
mappingllvm::yaml::MappingTraits2864a68babdSBrett Wilson   static void mapping(IO &IO, TemplateSpecializationInfo &I) {
2874a68babdSBrett Wilson     IO.mapOptional("SpecializationOf", I.SpecializationOf);
2884a68babdSBrett Wilson     IO.mapOptional("Params", I.Params);
2894a68babdSBrett Wilson   }
2904a68babdSBrett Wilson };
2914a68babdSBrett Wilson 
2924a68babdSBrett Wilson template <> struct MappingTraits<TemplateInfo> {
mappingllvm::yaml::MappingTraits2934a68babdSBrett Wilson   static void mapping(IO &IO, TemplateInfo &I) {
2944a68babdSBrett Wilson     IO.mapOptional("Params", I.Params);
2954a68babdSBrett Wilson     IO.mapOptional("Specialization", I.Specialization,
2964a68babdSBrett Wilson                    std::optional<TemplateSpecializationInfo>());
297e78f3018SJulie Hockett   }
298e78f3018SJulie Hockett };
299e78f3018SJulie Hockett 
300e78f3018SJulie Hockett template <> struct MappingTraits<CommentInfo> {
mappingllvm::yaml::MappingTraits301e78f3018SJulie Hockett   static void mapping(IO &IO, CommentInfo &I) { CommentInfoMapping(IO, I); }
302e78f3018SJulie Hockett };
303e78f3018SJulie Hockett 
304e78f3018SJulie Hockett template <> struct MappingTraits<std::unique_ptr<CommentInfo>> {
mappingllvm::yaml::MappingTraits305e78f3018SJulie Hockett   static void mapping(IO &IO, std::unique_ptr<CommentInfo> &I) {
306e78f3018SJulie Hockett     if (I)
307e78f3018SJulie Hockett       CommentInfoMapping(IO, *I);
308e78f3018SJulie Hockett   }
309e78f3018SJulie Hockett };
310e78f3018SJulie Hockett 
311e78f3018SJulie Hockett } // end namespace yaml
312e78f3018SJulie Hockett } // end namespace llvm
313e78f3018SJulie Hockett 
314e78f3018SJulie Hockett namespace clang {
315e78f3018SJulie Hockett namespace doc {
316e78f3018SJulie Hockett 
317e78f3018SJulie Hockett /// Generator for YAML documentation.
318e78f3018SJulie Hockett class YAMLGenerator : public Generator {
319e78f3018SJulie Hockett public:
320e78f3018SJulie Hockett   static const char *Format;
321e78f3018SJulie Hockett 
3227b8c7e02SBrett Wilson   llvm::Error generateDocs(StringRef RootDir,
3237b8c7e02SBrett Wilson                            llvm::StringMap<std::unique_ptr<doc::Info>> Infos,
3247b8c7e02SBrett Wilson                            const ClangDocContext &CDCtx) override;
325acd35f6cSDiego Astiazaran   llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS,
326acd35f6cSDiego Astiazaran                                  const ClangDocContext &CDCtx) override;
327e78f3018SJulie Hockett };
328e78f3018SJulie Hockett 
329e78f3018SJulie Hockett const char *YAMLGenerator::Format = "yaml";
330e78f3018SJulie Hockett 
3317b8c7e02SBrett Wilson llvm::Error
generateDocs(StringRef RootDir,llvm::StringMap<std::unique_ptr<doc::Info>> Infos,const ClangDocContext & CDCtx)3327b8c7e02SBrett Wilson YAMLGenerator::generateDocs(StringRef RootDir,
3337b8c7e02SBrett Wilson                             llvm::StringMap<std::unique_ptr<doc::Info>> Infos,
3347b8c7e02SBrett Wilson                             const ClangDocContext &CDCtx) {
3357b8c7e02SBrett Wilson   for (const auto &Group : Infos) {
3367b8c7e02SBrett Wilson     doc::Info *Info = Group.getValue().get();
3377b8c7e02SBrett Wilson 
3387b8c7e02SBrett Wilson     // Output file names according to the USR except the global namesapce.
3397b8c7e02SBrett Wilson     // Anonymous namespaces are taken care of in serialization, so here we can
3407b8c7e02SBrett Wilson     // safely assume an unnamed namespace is the global one.
3417b8c7e02SBrett Wilson     llvm::SmallString<128> Path;
3427b8c7e02SBrett Wilson     llvm::sys::path::native(RootDir, Path);
3437b8c7e02SBrett Wilson     if (Info->IT == InfoType::IT_namespace && Info->Name.empty()) {
3447b8c7e02SBrett Wilson       llvm::sys::path::append(Path, "index.yaml");
3457b8c7e02SBrett Wilson     } else {
3467b8c7e02SBrett Wilson       llvm::sys::path::append(Path, Group.getKey() + ".yaml");
3477b8c7e02SBrett Wilson     }
3487b8c7e02SBrett Wilson 
3497b8c7e02SBrett Wilson     std::error_code FileErr;
3507b8c7e02SBrett Wilson     llvm::raw_fd_ostream InfoOS(Path, FileErr, llvm::sys::fs::OF_None);
3517b8c7e02SBrett Wilson     if (FileErr) {
3527b8c7e02SBrett Wilson       return llvm::createStringError(FileErr, "Error opening file '%s'",
3537b8c7e02SBrett Wilson                                      Path.c_str());
3547b8c7e02SBrett Wilson     }
3557b8c7e02SBrett Wilson 
3567b8c7e02SBrett Wilson     if (llvm::Error Err = generateDocForInfo(Info, InfoOS, CDCtx)) {
3577b8c7e02SBrett Wilson       return Err;
3587b8c7e02SBrett Wilson     }
3597b8c7e02SBrett Wilson   }
3607b8c7e02SBrett Wilson 
3617b8c7e02SBrett Wilson   return llvm::Error::success();
3627b8c7e02SBrett Wilson }
3637b8c7e02SBrett Wilson 
generateDocForInfo(Info * I,llvm::raw_ostream & OS,const ClangDocContext & CDCtx)364acd35f6cSDiego Astiazaran llvm::Error YAMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
365acd35f6cSDiego Astiazaran                                               const ClangDocContext &CDCtx) {
366e78f3018SJulie Hockett   llvm::yaml::Output InfoYAML(OS);
367e78f3018SJulie Hockett   switch (I->IT) {
368e78f3018SJulie Hockett   case InfoType::IT_namespace:
369e78f3018SJulie Hockett     InfoYAML << *static_cast<clang::doc::NamespaceInfo *>(I);
370e78f3018SJulie Hockett     break;
371e78f3018SJulie Hockett   case InfoType::IT_record:
372e78f3018SJulie Hockett     InfoYAML << *static_cast<clang::doc::RecordInfo *>(I);
373e78f3018SJulie Hockett     break;
374e78f3018SJulie Hockett   case InfoType::IT_enum:
375e78f3018SJulie Hockett     InfoYAML << *static_cast<clang::doc::EnumInfo *>(I);
376e78f3018SJulie Hockett     break;
377e78f3018SJulie Hockett   case InfoType::IT_function:
378e78f3018SJulie Hockett     InfoYAML << *static_cast<clang::doc::FunctionInfo *>(I);
379e78f3018SJulie Hockett     break;
38021fb70c6SBrett Wilson   case InfoType::IT_typedef:
38121fb70c6SBrett Wilson     InfoYAML << *static_cast<clang::doc::TypedefInfo *>(I);
38221fb70c6SBrett Wilson     break;
383e78f3018SJulie Hockett   case InfoType::IT_default:
38418038065SFangrui Song     return llvm::createStringError(llvm::inconvertibleErrorCode(),
38518038065SFangrui Song                                    "unexpected InfoType");
386e78f3018SJulie Hockett   }
387ac68cab9SJulie Hockett   return llvm::Error::success();
388e78f3018SJulie Hockett }
389e78f3018SJulie Hockett 
390e78f3018SJulie Hockett static GeneratorRegistry::Add<YAMLGenerator> YAML(YAMLGenerator::Format,
391e78f3018SJulie Hockett                                                   "Generator for YAML output.");
392e78f3018SJulie Hockett 
393e78f3018SJulie Hockett // This anchor is used to force the linker to link in the generated object file
394e78f3018SJulie Hockett // and thus register the generator.
395e78f3018SJulie Hockett volatile int YAMLGeneratorAnchorSource = 0;
396e78f3018SJulie Hockett 
397e78f3018SJulie Hockett } // namespace doc
398e78f3018SJulie Hockett } // namespace clang
399