[LoongArch] Use getLoc() directly to construct error message
[llvm-project.git] / clang-tools-extra / clang-doc / YAMLGenerator.cpp
blob764784c55a183c7793bb4088d96002d0b0198ad8
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 //===----------------------------------------------------------------------===//
11 #include "Generators.h"
12 #include "llvm/Support/YAMLTraits.h"
13 #include "llvm/Support/raw_ostream.h"
15 using namespace clang::doc;
17 LLVM_YAML_IS_SEQUENCE_VECTOR(FieldTypeInfo)
18 LLVM_YAML_IS_SEQUENCE_VECTOR(MemberTypeInfo)
19 LLVM_YAML_IS_SEQUENCE_VECTOR(Reference)
20 LLVM_YAML_IS_SEQUENCE_VECTOR(Location)
21 LLVM_YAML_IS_SEQUENCE_VECTOR(CommentInfo)
22 LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionInfo)
23 LLVM_YAML_IS_SEQUENCE_VECTOR(EnumInfo)
24 LLVM_YAML_IS_SEQUENCE_VECTOR(BaseRecordInfo)
25 LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<CommentInfo>)
26 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::SmallString<16>)
28 namespace llvm {
29 namespace yaml {
31 // Enumerations to YAML output.
33 template <> struct ScalarEnumerationTraits<clang::AccessSpecifier> {
34 static void enumeration(IO &IO, clang::AccessSpecifier &Value) {
35 IO.enumCase(Value, "Public", clang::AccessSpecifier::AS_public);
36 IO.enumCase(Value, "Protected", clang::AccessSpecifier::AS_protected);
37 IO.enumCase(Value, "Private", clang::AccessSpecifier::AS_private);
38 IO.enumCase(Value, "None", clang::AccessSpecifier::AS_none);
42 template <> struct ScalarEnumerationTraits<clang::TagTypeKind> {
43 static void enumeration(IO &IO, clang::TagTypeKind &Value) {
44 IO.enumCase(Value, "Struct", clang::TagTypeKind::TTK_Struct);
45 IO.enumCase(Value, "Interface", clang::TagTypeKind::TTK_Interface);
46 IO.enumCase(Value, "Union", clang::TagTypeKind::TTK_Union);
47 IO.enumCase(Value, "Class", clang::TagTypeKind::TTK_Class);
48 IO.enumCase(Value, "Enum", clang::TagTypeKind::TTK_Enum);
52 template <> struct ScalarEnumerationTraits<InfoType> {
53 static void enumeration(IO &IO, InfoType &Value) {
54 IO.enumCase(Value, "Namespace", InfoType::IT_namespace);
55 IO.enumCase(Value, "Record", InfoType::IT_record);
56 IO.enumCase(Value, "Function", InfoType::IT_function);
57 IO.enumCase(Value, "Enum", InfoType::IT_enum);
58 IO.enumCase(Value, "Default", InfoType::IT_default);
62 // Scalars to YAML output.
63 template <unsigned U> struct ScalarTraits<SmallString<U>> {
65 static void output(const SmallString<U> &S, void *, llvm::raw_ostream &OS) {
66 for (const auto &C : S)
67 OS << C;
70 static StringRef input(StringRef Scalar, void *, SmallString<U> &Value) {
71 Value.assign(Scalar.begin(), Scalar.end());
72 return StringRef();
75 static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
78 template <> struct ScalarTraits<std::array<unsigned char, 20>> {
80 static void output(const std::array<unsigned char, 20> &S, void *,
81 llvm::raw_ostream &OS) {
82 OS << toHex(toStringRef(S));
85 static StringRef input(StringRef Scalar, void *,
86 std::array<unsigned char, 20> &Value) {
87 if (Scalar.size() != 40)
88 return "Error: Incorrect scalar size for USR.";
89 Value = StringToSymbol(Scalar);
90 return StringRef();
93 static SymbolID StringToSymbol(llvm::StringRef Value) {
94 SymbolID USR;
95 std::string HexString = fromHex(Value);
96 std::copy(HexString.begin(), HexString.end(), USR.begin());
97 return SymbolID(USR);
100 static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
103 // Helper functions to map infos to YAML.
105 static void TypeInfoMapping(IO &IO, TypeInfo &I) {
106 IO.mapOptional("Type", I.Type, Reference());
109 static void FieldTypeInfoMapping(IO &IO, FieldTypeInfo &I) {
110 TypeInfoMapping(IO, I);
111 IO.mapOptional("Name", I.Name, SmallString<16>());
114 static void InfoMapping(IO &IO, Info &I) {
115 IO.mapRequired("USR", I.USR);
116 IO.mapOptional("Name", I.Name, SmallString<16>());
117 IO.mapOptional("Path", I.Path, SmallString<128>());
118 IO.mapOptional("Namespace", I.Namespace, llvm::SmallVector<Reference, 4>());
119 IO.mapOptional("Description", I.Description);
122 static void SymbolInfoMapping(IO &IO, SymbolInfo &I) {
123 InfoMapping(IO, I);
124 IO.mapOptional("DefLocation", I.DefLoc, Optional<Location>());
125 IO.mapOptional("Location", I.Loc, llvm::SmallVector<Location, 2>());
128 static void RecordInfoMapping(IO &IO, RecordInfo &I) {
129 SymbolInfoMapping(IO, I);
130 IO.mapOptional("TagType", I.TagType, clang::TagTypeKind::TTK_Struct);
131 IO.mapOptional("Members", I.Members);
132 IO.mapOptional("Bases", I.Bases);
133 IO.mapOptional("Parents", I.Parents, llvm::SmallVector<Reference, 4>());
134 IO.mapOptional("VirtualParents", I.VirtualParents,
135 llvm::SmallVector<Reference, 4>());
136 IO.mapOptional("ChildRecords", I.ChildRecords, std::vector<Reference>());
137 IO.mapOptional("ChildFunctions", I.ChildFunctions);
138 IO.mapOptional("ChildEnums", I.ChildEnums);
141 static void CommentInfoMapping(IO &IO, CommentInfo &I) {
142 IO.mapOptional("Kind", I.Kind, SmallString<16>());
143 IO.mapOptional("Text", I.Text, SmallString<64>());
144 IO.mapOptional("Name", I.Name, SmallString<16>());
145 IO.mapOptional("Direction", I.Direction, SmallString<8>());
146 IO.mapOptional("ParamName", I.ParamName, SmallString<16>());
147 IO.mapOptional("CloseName", I.CloseName, SmallString<16>());
148 IO.mapOptional("SelfClosing", I.SelfClosing, false);
149 IO.mapOptional("Explicit", I.Explicit, false);
150 IO.mapOptional("Args", I.Args, llvm::SmallVector<SmallString<16>, 4>());
151 IO.mapOptional("AttrKeys", I.AttrKeys,
152 llvm::SmallVector<SmallString<16>, 4>());
153 IO.mapOptional("AttrValues", I.AttrValues,
154 llvm::SmallVector<SmallString<16>, 4>());
155 IO.mapOptional("Children", I.Children);
158 // Template specialization to YAML traits for Infos.
160 template <> struct MappingTraits<Location> {
161 static void mapping(IO &IO, Location &Loc) {
162 IO.mapOptional("LineNumber", Loc.LineNumber, 0);
163 IO.mapOptional("Filename", Loc.Filename, SmallString<32>());
167 template <> struct MappingTraits<Reference> {
168 static void mapping(IO &IO, Reference &Ref) {
169 IO.mapOptional("Type", Ref.RefType, InfoType::IT_default);
170 IO.mapOptional("Name", Ref.Name, SmallString<16>());
171 IO.mapOptional("USR", Ref.USR, SymbolID());
172 IO.mapOptional("Path", Ref.Path, SmallString<128>());
173 IO.mapOptional("IsInGlobalNamespace", Ref.IsInGlobalNamespace, false);
177 template <> struct MappingTraits<TypeInfo> {
178 static void mapping(IO &IO, TypeInfo &I) { TypeInfoMapping(IO, I); }
181 template <> struct MappingTraits<FieldTypeInfo> {
182 static void mapping(IO &IO, FieldTypeInfo &I) {
183 TypeInfoMapping(IO, I);
184 IO.mapOptional("Name", I.Name, SmallString<16>());
188 template <> struct MappingTraits<MemberTypeInfo> {
189 static void mapping(IO &IO, MemberTypeInfo &I) {
190 FieldTypeInfoMapping(IO, I);
191 // clang::AccessSpecifier::AS_none is used as the default here because it's
192 // the AS that shouldn't be part of the output. Even though AS_public is the
193 // default in the struct, it should be displayed in the YAML output.
194 IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
198 template <> struct MappingTraits<NamespaceInfo> {
199 static void mapping(IO &IO, NamespaceInfo &I) {
200 InfoMapping(IO, I);
201 IO.mapOptional("ChildNamespaces", I.ChildNamespaces,
202 std::vector<Reference>());
203 IO.mapOptional("ChildRecords", I.ChildRecords, std::vector<Reference>());
204 IO.mapOptional("ChildFunctions", I.ChildFunctions);
205 IO.mapOptional("ChildEnums", I.ChildEnums);
209 template <> struct MappingTraits<RecordInfo> {
210 static void mapping(IO &IO, RecordInfo &I) { RecordInfoMapping(IO, I); }
213 template <> struct MappingTraits<BaseRecordInfo> {
214 static void mapping(IO &IO, BaseRecordInfo &I) {
215 RecordInfoMapping(IO, I);
216 IO.mapOptional("IsVirtual", I.IsVirtual, false);
217 // clang::AccessSpecifier::AS_none is used as the default here because it's
218 // the AS that shouldn't be part of the output. Even though AS_public is the
219 // default in the struct, it should be displayed in the YAML output.
220 IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
221 IO.mapOptional("IsParent", I.IsParent, false);
225 template <> struct MappingTraits<EnumInfo> {
226 static void mapping(IO &IO, EnumInfo &I) {
227 SymbolInfoMapping(IO, I);
228 IO.mapOptional("Scoped", I.Scoped, false);
229 IO.mapOptional("Members", I.Members);
233 template <> struct MappingTraits<FunctionInfo> {
234 static void mapping(IO &IO, FunctionInfo &I) {
235 SymbolInfoMapping(IO, I);
236 IO.mapOptional("IsMethod", I.IsMethod, false);
237 IO.mapOptional("Parent", I.Parent, Reference());
238 IO.mapOptional("Params", I.Params);
239 IO.mapOptional("ReturnType", I.ReturnType);
240 // clang::AccessSpecifier::AS_none is used as the default here because it's
241 // the AS that shouldn't be part of the output. Even though AS_public is the
242 // default in the struct, it should be displayed in the YAML output.
243 IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
247 template <> struct MappingTraits<CommentInfo> {
248 static void mapping(IO &IO, CommentInfo &I) { CommentInfoMapping(IO, I); }
251 template <> struct MappingTraits<std::unique_ptr<CommentInfo>> {
252 static void mapping(IO &IO, std::unique_ptr<CommentInfo> &I) {
253 if (I)
254 CommentInfoMapping(IO, *I);
258 } // end namespace yaml
259 } // end namespace llvm
261 namespace clang {
262 namespace doc {
264 /// Generator for YAML documentation.
265 class YAMLGenerator : public Generator {
266 public:
267 static const char *Format;
269 llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS,
270 const ClangDocContext &CDCtx) override;
273 const char *YAMLGenerator::Format = "yaml";
275 llvm::Error YAMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
276 const ClangDocContext &CDCtx) {
277 llvm::yaml::Output InfoYAML(OS);
278 switch (I->IT) {
279 case InfoType::IT_namespace:
280 InfoYAML << *static_cast<clang::doc::NamespaceInfo *>(I);
281 break;
282 case InfoType::IT_record:
283 InfoYAML << *static_cast<clang::doc::RecordInfo *>(I);
284 break;
285 case InfoType::IT_enum:
286 InfoYAML << *static_cast<clang::doc::EnumInfo *>(I);
287 break;
288 case InfoType::IT_function:
289 InfoYAML << *static_cast<clang::doc::FunctionInfo *>(I);
290 break;
291 case InfoType::IT_default:
292 return llvm::createStringError(llvm::inconvertibleErrorCode(),
293 "unexpected InfoType");
295 return llvm::Error::success();
298 static GeneratorRegistry::Add<YAMLGenerator> YAML(YAMLGenerator::Format,
299 "Generator for YAML output.");
301 // This anchor is used to force the linker to link in the generated object file
302 // and thus register the generator.
303 volatile int YAMLGeneratorAnchorSource = 0;
305 } // namespace doc
306 } // namespace clang