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