1*89f6b26fSZixu Wang //===- ExtractAPI/Serialization/SymbolGraphSerializer.cpp -------*- C++ -*-===// 2*89f6b26fSZixu Wang // 3*89f6b26fSZixu Wang // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*89f6b26fSZixu Wang // See https://llvm.org/LICENSE.txt for license information. 5*89f6b26fSZixu Wang // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*89f6b26fSZixu Wang // 7*89f6b26fSZixu Wang //===----------------------------------------------------------------------===// 8*89f6b26fSZixu Wang /// 9*89f6b26fSZixu Wang /// \file 10*89f6b26fSZixu Wang /// This file implements the SymbolGraphSerializer. 11*89f6b26fSZixu Wang /// 12*89f6b26fSZixu Wang //===----------------------------------------------------------------------===// 13*89f6b26fSZixu Wang 14*89f6b26fSZixu Wang #include "clang/ExtractAPI/Serialization/SymbolGraphSerializer.h" 15*89f6b26fSZixu Wang #include "clang/Basic/Version.h" 16*89f6b26fSZixu Wang #include "clang/ExtractAPI/API.h" 17*89f6b26fSZixu Wang #include "llvm/Support/JSON.h" 18*89f6b26fSZixu Wang #include "llvm/Support/Path.h" 19*89f6b26fSZixu Wang #include "llvm/Support/VersionTuple.h" 20*89f6b26fSZixu Wang 21*89f6b26fSZixu Wang using namespace clang; 22*89f6b26fSZixu Wang using namespace clang::extractapi; 23*89f6b26fSZixu Wang using namespace llvm; 24*89f6b26fSZixu Wang using namespace llvm::json; 25*89f6b26fSZixu Wang 26*89f6b26fSZixu Wang namespace { 27*89f6b26fSZixu Wang 28*89f6b26fSZixu Wang /// Helper function to inject a JSON object \p Obj into another object \p Paren 29*89f6b26fSZixu Wang /// at position \p Key. 30*89f6b26fSZixu Wang void serializeObject(Object &Paren, StringRef Key, Optional<Object> Obj) { 31*89f6b26fSZixu Wang if (Obj) 32*89f6b26fSZixu Wang Paren[Key] = std::move(Obj.getValue()); 33*89f6b26fSZixu Wang } 34*89f6b26fSZixu Wang 35*89f6b26fSZixu Wang /// Helper function to inject a JSON array \p Array into object \p Paren at 36*89f6b26fSZixu Wang /// position \p Key. 37*89f6b26fSZixu Wang void serializeArray(Object &Paren, StringRef Key, Optional<Array> Array) { 38*89f6b26fSZixu Wang if (Array) 39*89f6b26fSZixu Wang Paren[Key] = std::move(Array.getValue()); 40*89f6b26fSZixu Wang } 41*89f6b26fSZixu Wang 42*89f6b26fSZixu Wang /// Serialize a \c VersionTuple \p V with the Symbol Graph semantic version 43*89f6b26fSZixu Wang /// format. 44*89f6b26fSZixu Wang /// 45*89f6b26fSZixu Wang /// A semantic version object contains three numeric fields, representing the 46*89f6b26fSZixu Wang /// \c major, \c minor, and \c patch parts of the version tuple. 47*89f6b26fSZixu Wang /// For example version tuple 1.0.3 is serialized as: 48*89f6b26fSZixu Wang /// \code 49*89f6b26fSZixu Wang /// { 50*89f6b26fSZixu Wang /// "major" : 1, 51*89f6b26fSZixu Wang /// "minor" : 0, 52*89f6b26fSZixu Wang /// "patch" : 3 53*89f6b26fSZixu Wang /// } 54*89f6b26fSZixu Wang /// \endcode 55*89f6b26fSZixu Wang /// 56*89f6b26fSZixu Wang /// \returns \c None if the version \p V is empty, or an \c Object containing 57*89f6b26fSZixu Wang /// the semantic version representation of \p V. 58*89f6b26fSZixu Wang Optional<Object> serializeSemanticVersion(const VersionTuple &V) { 59*89f6b26fSZixu Wang if (V.empty()) 60*89f6b26fSZixu Wang return None; 61*89f6b26fSZixu Wang 62*89f6b26fSZixu Wang Object Version; 63*89f6b26fSZixu Wang Version["major"] = V.getMajor(); 64*89f6b26fSZixu Wang Version["minor"] = V.getMinor().getValueOr(0); 65*89f6b26fSZixu Wang Version["patch"] = V.getSubminor().getValueOr(0); 66*89f6b26fSZixu Wang return Version; 67*89f6b26fSZixu Wang } 68*89f6b26fSZixu Wang 69*89f6b26fSZixu Wang /// Serialize the OS information in the Symbol Graph platform property. 70*89f6b26fSZixu Wang /// 71*89f6b26fSZixu Wang /// The OS information in Symbol Graph contains the \c name of the OS, and an 72*89f6b26fSZixu Wang /// optional \c minimumVersion semantic version field. 73*89f6b26fSZixu Wang Object serializeOperatingSystem(const Triple &T) { 74*89f6b26fSZixu Wang Object OS; 75*89f6b26fSZixu Wang OS["name"] = T.getOSTypeName(T.getOS()); 76*89f6b26fSZixu Wang serializeObject(OS, "minimumVersion", 77*89f6b26fSZixu Wang serializeSemanticVersion(T.getMinimumSupportedOSVersion())); 78*89f6b26fSZixu Wang return OS; 79*89f6b26fSZixu Wang } 80*89f6b26fSZixu Wang 81*89f6b26fSZixu Wang /// Serialize the platform information in the Symbol Graph module section. 82*89f6b26fSZixu Wang /// 83*89f6b26fSZixu Wang /// The platform object describes a target platform triple in corresponding 84*89f6b26fSZixu Wang /// three fields: \c architecture, \c vendor, and \c operatingSystem. 85*89f6b26fSZixu Wang Object serializePlatform(const Triple &T) { 86*89f6b26fSZixu Wang Object Platform; 87*89f6b26fSZixu Wang Platform["architecture"] = T.getArchName(); 88*89f6b26fSZixu Wang Platform["vendor"] = T.getVendorName(); 89*89f6b26fSZixu Wang Platform["operatingSystem"] = serializeOperatingSystem(T); 90*89f6b26fSZixu Wang return Platform; 91*89f6b26fSZixu Wang } 92*89f6b26fSZixu Wang 93*89f6b26fSZixu Wang /// Serialize a source location in file. 94*89f6b26fSZixu Wang /// 95*89f6b26fSZixu Wang /// \param Loc The presumed location to serialize. 96*89f6b26fSZixu Wang /// \param IncludeFileURI If true, include the file path of \p Loc as a URI. 97*89f6b26fSZixu Wang /// Defaults to false. 98*89f6b26fSZixu Wang Object serializeSourcePosition(const PresumedLoc &Loc, 99*89f6b26fSZixu Wang bool IncludeFileURI = false) { 100*89f6b26fSZixu Wang assert(Loc.isValid() && "invalid source position"); 101*89f6b26fSZixu Wang 102*89f6b26fSZixu Wang Object SourcePosition; 103*89f6b26fSZixu Wang SourcePosition["line"] = Loc.getLine(); 104*89f6b26fSZixu Wang SourcePosition["character"] = Loc.getColumn(); 105*89f6b26fSZixu Wang 106*89f6b26fSZixu Wang if (IncludeFileURI) { 107*89f6b26fSZixu Wang std::string FileURI = "file://"; 108*89f6b26fSZixu Wang // Normalize file path to use forward slashes for the URI. 109*89f6b26fSZixu Wang FileURI += sys::path::convert_to_slash(Loc.getFilename()); 110*89f6b26fSZixu Wang SourcePosition["uri"] = FileURI; 111*89f6b26fSZixu Wang } 112*89f6b26fSZixu Wang 113*89f6b26fSZixu Wang return SourcePosition; 114*89f6b26fSZixu Wang } 115*89f6b26fSZixu Wang 116*89f6b26fSZixu Wang /// Serialize a source range with begin and end locations. 117*89f6b26fSZixu Wang Object serializeSourceRange(const PresumedLoc &BeginLoc, 118*89f6b26fSZixu Wang const PresumedLoc &EndLoc) { 119*89f6b26fSZixu Wang Object SourceRange; 120*89f6b26fSZixu Wang serializeObject(SourceRange, "start", serializeSourcePosition(BeginLoc)); 121*89f6b26fSZixu Wang serializeObject(SourceRange, "end", serializeSourcePosition(EndLoc)); 122*89f6b26fSZixu Wang return SourceRange; 123*89f6b26fSZixu Wang } 124*89f6b26fSZixu Wang 125*89f6b26fSZixu Wang /// Serialize the availability attributes of a symbol. 126*89f6b26fSZixu Wang /// 127*89f6b26fSZixu Wang /// Availability information contains the introduced, deprecated, and obsoleted 128*89f6b26fSZixu Wang /// versions of the symbol as semantic versions, if not default. 129*89f6b26fSZixu Wang /// Availability information also contains flags to indicate if the symbol is 130*89f6b26fSZixu Wang /// unconditionally unavailable or deprecated, 131*89f6b26fSZixu Wang /// i.e. \c __attribute__((unavailable)) and \c __attribute__((deprecated)). 132*89f6b26fSZixu Wang /// 133*89f6b26fSZixu Wang /// \returns \c None if the symbol has default availability attributes, or 134*89f6b26fSZixu Wang /// an \c Object containing the formatted availability information. 135*89f6b26fSZixu Wang Optional<Object> serializeAvailability(const AvailabilityInfo &Avail) { 136*89f6b26fSZixu Wang if (Avail.isDefault()) 137*89f6b26fSZixu Wang return None; 138*89f6b26fSZixu Wang 139*89f6b26fSZixu Wang Object Availbility; 140*89f6b26fSZixu Wang serializeObject(Availbility, "introducedVersion", 141*89f6b26fSZixu Wang serializeSemanticVersion(Avail.Introduced)); 142*89f6b26fSZixu Wang serializeObject(Availbility, "deprecatedVersion", 143*89f6b26fSZixu Wang serializeSemanticVersion(Avail.Deprecated)); 144*89f6b26fSZixu Wang serializeObject(Availbility, "obsoletedVersion", 145*89f6b26fSZixu Wang serializeSemanticVersion(Avail.Obsoleted)); 146*89f6b26fSZixu Wang if (Avail.isUnavailable()) 147*89f6b26fSZixu Wang Availbility["isUnconditionallyUnavailable"] = true; 148*89f6b26fSZixu Wang if (Avail.isUnconditionallyDeprecated()) 149*89f6b26fSZixu Wang Availbility["isUnconditionallyDeprecated"] = true; 150*89f6b26fSZixu Wang 151*89f6b26fSZixu Wang return Availbility; 152*89f6b26fSZixu Wang } 153*89f6b26fSZixu Wang 154*89f6b26fSZixu Wang /// Get the short language name string for interface language references. 155*89f6b26fSZixu Wang StringRef getLanguageName(const LangOptions &LangOpts) { 156*89f6b26fSZixu Wang auto Language = 157*89f6b26fSZixu Wang LangStandard::getLangStandardForKind(LangOpts.LangStd).getLanguage(); 158*89f6b26fSZixu Wang switch (Language) { 159*89f6b26fSZixu Wang case Language::C: 160*89f6b26fSZixu Wang return "c"; 161*89f6b26fSZixu Wang case Language::ObjC: 162*89f6b26fSZixu Wang return "objc"; 163*89f6b26fSZixu Wang 164*89f6b26fSZixu Wang // Unsupported language currently 165*89f6b26fSZixu Wang case Language::CXX: 166*89f6b26fSZixu Wang case Language::ObjCXX: 167*89f6b26fSZixu Wang case Language::OpenCL: 168*89f6b26fSZixu Wang case Language::OpenCLCXX: 169*89f6b26fSZixu Wang case Language::CUDA: 170*89f6b26fSZixu Wang case Language::RenderScript: 171*89f6b26fSZixu Wang case Language::HIP: 172*89f6b26fSZixu Wang 173*89f6b26fSZixu Wang // Languages that the frontend cannot parse and compile 174*89f6b26fSZixu Wang case Language::Unknown: 175*89f6b26fSZixu Wang case Language::Asm: 176*89f6b26fSZixu Wang case Language::LLVM_IR: 177*89f6b26fSZixu Wang llvm_unreachable("Unsupported language kind"); 178*89f6b26fSZixu Wang } 179*89f6b26fSZixu Wang 180*89f6b26fSZixu Wang llvm_unreachable("Unhandled language kind"); 181*89f6b26fSZixu Wang } 182*89f6b26fSZixu Wang 183*89f6b26fSZixu Wang /// Serialize the identifier object as specified by the Symbol Graph format. 184*89f6b26fSZixu Wang /// 185*89f6b26fSZixu Wang /// The identifier property of a symbol contains the USR for precise and unique 186*89f6b26fSZixu Wang /// references, and the interface language name. 187*89f6b26fSZixu Wang Object serializeIdentifier(const APIRecord &Record, 188*89f6b26fSZixu Wang const LangOptions &LangOpts) { 189*89f6b26fSZixu Wang Object Identifier; 190*89f6b26fSZixu Wang Identifier["precise"] = Record.USR; 191*89f6b26fSZixu Wang Identifier["interfaceLanguage"] = getLanguageName(LangOpts); 192*89f6b26fSZixu Wang 193*89f6b26fSZixu Wang return Identifier; 194*89f6b26fSZixu Wang } 195*89f6b26fSZixu Wang 196*89f6b26fSZixu Wang /// Serialize the documentation comments attached to a symbol, as specified by 197*89f6b26fSZixu Wang /// the Symbol Graph format. 198*89f6b26fSZixu Wang /// 199*89f6b26fSZixu Wang /// The Symbol Graph \c docComment object contains an array of lines. Each line 200*89f6b26fSZixu Wang /// represents one line of striped documentation comment, with source range 201*89f6b26fSZixu Wang /// information. 202*89f6b26fSZixu Wang /// e.g. 203*89f6b26fSZixu Wang /// \code 204*89f6b26fSZixu Wang /// /// This is a documentation comment 205*89f6b26fSZixu Wang /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' First line. 206*89f6b26fSZixu Wang /// /// with multiple lines. 207*89f6b26fSZixu Wang /// ^~~~~~~~~~~~~~~~~~~~~~~' Second line. 208*89f6b26fSZixu Wang /// \endcode 209*89f6b26fSZixu Wang /// 210*89f6b26fSZixu Wang /// \returns \c None if \p Comment is empty, or an \c Object containing the 211*89f6b26fSZixu Wang /// formatted lines. 212*89f6b26fSZixu Wang Optional<Object> serializeDocComment(const DocComment &Comment) { 213*89f6b26fSZixu Wang if (Comment.empty()) 214*89f6b26fSZixu Wang return None; 215*89f6b26fSZixu Wang 216*89f6b26fSZixu Wang Object DocComment; 217*89f6b26fSZixu Wang Array LinesArray; 218*89f6b26fSZixu Wang for (const auto &CommentLine : Comment) { 219*89f6b26fSZixu Wang Object Line; 220*89f6b26fSZixu Wang Line["text"] = CommentLine.Text; 221*89f6b26fSZixu Wang serializeObject(Line, "range", 222*89f6b26fSZixu Wang serializeSourceRange(CommentLine.Begin, CommentLine.End)); 223*89f6b26fSZixu Wang LinesArray.emplace_back(std::move(Line)); 224*89f6b26fSZixu Wang } 225*89f6b26fSZixu Wang serializeArray(DocComment, "lines", LinesArray); 226*89f6b26fSZixu Wang 227*89f6b26fSZixu Wang return DocComment; 228*89f6b26fSZixu Wang } 229*89f6b26fSZixu Wang 230*89f6b26fSZixu Wang /// Serialize the declaration fragments of a symbol. 231*89f6b26fSZixu Wang /// 232*89f6b26fSZixu Wang /// The Symbol Graph declaration fragments is an array of tagged important 233*89f6b26fSZixu Wang /// parts of a symbol's declaration. The fragments sequence can be joined to 234*89f6b26fSZixu Wang /// form spans of declaration text, with attached information useful for 235*89f6b26fSZixu Wang /// purposes like syntax-highlighting etc. For example: 236*89f6b26fSZixu Wang /// \code 237*89f6b26fSZixu Wang /// const int pi; -> "declarationFragments" : [ 238*89f6b26fSZixu Wang /// { 239*89f6b26fSZixu Wang /// "kind" : "keyword", 240*89f6b26fSZixu Wang /// "spelling" : "const" 241*89f6b26fSZixu Wang /// }, 242*89f6b26fSZixu Wang /// { 243*89f6b26fSZixu Wang /// "kind" : "text", 244*89f6b26fSZixu Wang /// "spelling" : " " 245*89f6b26fSZixu Wang /// }, 246*89f6b26fSZixu Wang /// { 247*89f6b26fSZixu Wang /// "kind" : "typeIdentifier", 248*89f6b26fSZixu Wang /// "preciseIdentifier" : "c:I", 249*89f6b26fSZixu Wang /// "spelling" : "int" 250*89f6b26fSZixu Wang /// }, 251*89f6b26fSZixu Wang /// { 252*89f6b26fSZixu Wang /// "kind" : "text", 253*89f6b26fSZixu Wang /// "spelling" : " " 254*89f6b26fSZixu Wang /// }, 255*89f6b26fSZixu Wang /// { 256*89f6b26fSZixu Wang /// "kind" : "identifier", 257*89f6b26fSZixu Wang /// "spelling" : "pi" 258*89f6b26fSZixu Wang /// } 259*89f6b26fSZixu Wang /// ] 260*89f6b26fSZixu Wang /// \endcode 261*89f6b26fSZixu Wang /// 262*89f6b26fSZixu Wang /// \returns \c None if \p DF is empty, or an \c Array containing the formatted 263*89f6b26fSZixu Wang /// declaration fragments array. 264*89f6b26fSZixu Wang Optional<Array> serializeDeclarationFragments(const DeclarationFragments &DF) { 265*89f6b26fSZixu Wang if (DF.getFragments().empty()) 266*89f6b26fSZixu Wang return None; 267*89f6b26fSZixu Wang 268*89f6b26fSZixu Wang Array Fragments; 269*89f6b26fSZixu Wang for (const auto &F : DF.getFragments()) { 270*89f6b26fSZixu Wang Object Fragment; 271*89f6b26fSZixu Wang Fragment["spelling"] = F.Spelling; 272*89f6b26fSZixu Wang Fragment["kind"] = DeclarationFragments::getFragmentKindString(F.Kind); 273*89f6b26fSZixu Wang if (!F.PreciseIdentifier.empty()) 274*89f6b26fSZixu Wang Fragment["preciseIdentifier"] = F.PreciseIdentifier; 275*89f6b26fSZixu Wang Fragments.emplace_back(std::move(Fragment)); 276*89f6b26fSZixu Wang } 277*89f6b26fSZixu Wang 278*89f6b26fSZixu Wang return Fragments; 279*89f6b26fSZixu Wang } 280*89f6b26fSZixu Wang 281*89f6b26fSZixu Wang /// Serialize the function signature field of a function, as specified by the 282*89f6b26fSZixu Wang /// Symbol Graph format. 283*89f6b26fSZixu Wang /// 284*89f6b26fSZixu Wang /// The Symbol Graph function signature property contains two arrays. 285*89f6b26fSZixu Wang /// - The \c returns array is the declaration fragments of the return type; 286*89f6b26fSZixu Wang /// - The \c parameters array contains names and declaration fragments of the 287*89f6b26fSZixu Wang /// parameters. 288*89f6b26fSZixu Wang /// 289*89f6b26fSZixu Wang /// \returns \c None if \p FS is empty, or an \c Object containing the 290*89f6b26fSZixu Wang /// formatted function signature. 291*89f6b26fSZixu Wang Optional<Object> serializeFunctionSignature(const FunctionSignature &FS) { 292*89f6b26fSZixu Wang if (FS.empty()) 293*89f6b26fSZixu Wang return None; 294*89f6b26fSZixu Wang 295*89f6b26fSZixu Wang Object Signature; 296*89f6b26fSZixu Wang serializeArray(Signature, "returns", 297*89f6b26fSZixu Wang serializeDeclarationFragments(FS.getReturnType())); 298*89f6b26fSZixu Wang 299*89f6b26fSZixu Wang Array Parameters; 300*89f6b26fSZixu Wang for (const auto &P : FS.getParameters()) { 301*89f6b26fSZixu Wang Object Parameter; 302*89f6b26fSZixu Wang Parameter["name"] = P.Name; 303*89f6b26fSZixu Wang serializeArray(Parameter, "declarationFragments", 304*89f6b26fSZixu Wang serializeDeclarationFragments(P.Fragments)); 305*89f6b26fSZixu Wang Parameters.emplace_back(std::move(Parameter)); 306*89f6b26fSZixu Wang } 307*89f6b26fSZixu Wang 308*89f6b26fSZixu Wang if (!Parameters.empty()) 309*89f6b26fSZixu Wang Signature["parameters"] = std::move(Parameters); 310*89f6b26fSZixu Wang 311*89f6b26fSZixu Wang return Signature; 312*89f6b26fSZixu Wang } 313*89f6b26fSZixu Wang 314*89f6b26fSZixu Wang /// Serialize the \c names field of a symbol as specified by the Symbol Graph 315*89f6b26fSZixu Wang /// format. 316*89f6b26fSZixu Wang /// 317*89f6b26fSZixu Wang /// The Symbol Graph names field contains multiple representations of a symbol 318*89f6b26fSZixu Wang /// that can be used for different applications: 319*89f6b26fSZixu Wang /// - \c title : The simple declared name of the symbol; 320*89f6b26fSZixu Wang /// - \c subHeading : An array of declaration fragments that provides tags, 321*89f6b26fSZixu Wang /// and potentially more tokens (for example the \c +/- symbol for 322*89f6b26fSZixu Wang /// Objective-C methods). Can be used as sub-headings for documentation. 323*89f6b26fSZixu Wang Object serializeNames(const APIRecord &Record) { 324*89f6b26fSZixu Wang Object Names; 325*89f6b26fSZixu Wang Names["title"] = Record.Name; 326*89f6b26fSZixu Wang serializeArray(Names, "subHeading", 327*89f6b26fSZixu Wang serializeDeclarationFragments(Record.SubHeading)); 328*89f6b26fSZixu Wang 329*89f6b26fSZixu Wang return Names; 330*89f6b26fSZixu Wang } 331*89f6b26fSZixu Wang 332*89f6b26fSZixu Wang /// Serialize the symbol kind information. 333*89f6b26fSZixu Wang /// 334*89f6b26fSZixu Wang /// The Symbol Graph symbol kind property contains a shorthand \c identifier 335*89f6b26fSZixu Wang /// which is prefixed by the source language name, useful for tooling to parse 336*89f6b26fSZixu Wang /// the kind, and a \c displayName for rendering human-readable names. 337*89f6b26fSZixu Wang Object serializeSymbolKind(const APIRecord &Record, 338*89f6b26fSZixu Wang const LangOptions &LangOpts) { 339*89f6b26fSZixu Wang Object Kind; 340*89f6b26fSZixu Wang switch (Record.getKind()) { 341*89f6b26fSZixu Wang case APIRecord::RK_Global: 342*89f6b26fSZixu Wang auto *GR = dyn_cast<GlobalRecord>(&Record); 343*89f6b26fSZixu Wang switch (GR->GlobalKind) { 344*89f6b26fSZixu Wang case GVKind::Function: 345*89f6b26fSZixu Wang Kind["identifier"] = (getLanguageName(LangOpts) + ".func").str(); 346*89f6b26fSZixu Wang Kind["displayName"] = "Function"; 347*89f6b26fSZixu Wang break; 348*89f6b26fSZixu Wang case GVKind::Variable: 349*89f6b26fSZixu Wang Kind["identifier"] = (getLanguageName(LangOpts) + ".var").str(); 350*89f6b26fSZixu Wang Kind["displayName"] = "Global Variable"; 351*89f6b26fSZixu Wang break; 352*89f6b26fSZixu Wang case GVKind::Unknown: 353*89f6b26fSZixu Wang // Unknown global kind 354*89f6b26fSZixu Wang break; 355*89f6b26fSZixu Wang } 356*89f6b26fSZixu Wang break; 357*89f6b26fSZixu Wang } 358*89f6b26fSZixu Wang 359*89f6b26fSZixu Wang return Kind; 360*89f6b26fSZixu Wang } 361*89f6b26fSZixu Wang 362*89f6b26fSZixu Wang } // namespace 363*89f6b26fSZixu Wang 364*89f6b26fSZixu Wang void SymbolGraphSerializer::anchor() {} 365*89f6b26fSZixu Wang 366*89f6b26fSZixu Wang /// Defines the format version emitted by SymbolGraphSerializer. 367*89f6b26fSZixu Wang const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3}; 368*89f6b26fSZixu Wang 369*89f6b26fSZixu Wang Object SymbolGraphSerializer::serializeMetadata() const { 370*89f6b26fSZixu Wang Object Metadata; 371*89f6b26fSZixu Wang serializeObject(Metadata, "formatVersion", 372*89f6b26fSZixu Wang serializeSemanticVersion(FormatVersion)); 373*89f6b26fSZixu Wang Metadata["generator"] = clang::getClangFullVersion(); 374*89f6b26fSZixu Wang return Metadata; 375*89f6b26fSZixu Wang } 376*89f6b26fSZixu Wang 377*89f6b26fSZixu Wang Object SymbolGraphSerializer::serializeModule() const { 378*89f6b26fSZixu Wang Object Module; 379*89f6b26fSZixu Wang // FIXME: We might not be building a module, some Clang-based languages might 380*89f6b26fSZixu Wang // not have a "module" concept. Figure out a way to provide a name to 381*89f6b26fSZixu Wang // describe the API set. 382*89f6b26fSZixu Wang Module["name"] = ""; 383*89f6b26fSZixu Wang serializeObject(Module, "platform", serializePlatform(API.getTarget())); 384*89f6b26fSZixu Wang return Module; 385*89f6b26fSZixu Wang } 386*89f6b26fSZixu Wang 387*89f6b26fSZixu Wang bool SymbolGraphSerializer::shouldSkip(const APIRecord &Record) const { 388*89f6b26fSZixu Wang // Skip unconditionally unavailable symbols 389*89f6b26fSZixu Wang if (Record.Availability.isUnconditionallyUnavailable()) 390*89f6b26fSZixu Wang return true; 391*89f6b26fSZixu Wang 392*89f6b26fSZixu Wang return false; 393*89f6b26fSZixu Wang } 394*89f6b26fSZixu Wang 395*89f6b26fSZixu Wang Optional<Object> 396*89f6b26fSZixu Wang SymbolGraphSerializer::serializeAPIRecord(const APIRecord &Record) const { 397*89f6b26fSZixu Wang if (shouldSkip(Record)) 398*89f6b26fSZixu Wang return None; 399*89f6b26fSZixu Wang 400*89f6b26fSZixu Wang Object Obj; 401*89f6b26fSZixu Wang serializeObject(Obj, "identifier", 402*89f6b26fSZixu Wang serializeIdentifier(Record, API.getLangOpts())); 403*89f6b26fSZixu Wang serializeObject(Obj, "kind", serializeSymbolKind(Record, API.getLangOpts())); 404*89f6b26fSZixu Wang serializeObject(Obj, "names", serializeNames(Record)); 405*89f6b26fSZixu Wang serializeObject( 406*89f6b26fSZixu Wang Obj, "location", 407*89f6b26fSZixu Wang serializeSourcePosition(Record.Location, /*IncludeFileURI=*/true)); 408*89f6b26fSZixu Wang serializeObject(Obj, "availbility", 409*89f6b26fSZixu Wang serializeAvailability(Record.Availability)); 410*89f6b26fSZixu Wang serializeObject(Obj, "docComment", serializeDocComment(Record.Comment)); 411*89f6b26fSZixu Wang serializeArray(Obj, "declarationFragments", 412*89f6b26fSZixu Wang serializeDeclarationFragments(Record.Declaration)); 413*89f6b26fSZixu Wang 414*89f6b26fSZixu Wang return Obj; 415*89f6b26fSZixu Wang } 416*89f6b26fSZixu Wang 417*89f6b26fSZixu Wang void SymbolGraphSerializer::serializeGlobalRecord(const GlobalRecord &Record) { 418*89f6b26fSZixu Wang auto Obj = serializeAPIRecord(Record); 419*89f6b26fSZixu Wang if (!Obj) 420*89f6b26fSZixu Wang return; 421*89f6b26fSZixu Wang 422*89f6b26fSZixu Wang if (Record.GlobalKind == GVKind::Function) 423*89f6b26fSZixu Wang serializeObject(*Obj, "parameters", 424*89f6b26fSZixu Wang serializeFunctionSignature(Record.Signature)); 425*89f6b26fSZixu Wang 426*89f6b26fSZixu Wang Symbols.emplace_back(std::move(*Obj)); 427*89f6b26fSZixu Wang } 428*89f6b26fSZixu Wang 429*89f6b26fSZixu Wang Object SymbolGraphSerializer::serialize() { 430*89f6b26fSZixu Wang Object Root; 431*89f6b26fSZixu Wang serializeObject(Root, "metadata", serializeMetadata()); 432*89f6b26fSZixu Wang serializeObject(Root, "module", serializeModule()); 433*89f6b26fSZixu Wang 434*89f6b26fSZixu Wang // Serialize global records in the API set. 435*89f6b26fSZixu Wang for (const auto &Global : API.getGlobals()) 436*89f6b26fSZixu Wang serializeGlobalRecord(*Global.second); 437*89f6b26fSZixu Wang 438*89f6b26fSZixu Wang Root["symbols"] = std::move(Symbols); 439*89f6b26fSZixu Wang Root["relationhips"] = std::move(Relationships); 440*89f6b26fSZixu Wang 441*89f6b26fSZixu Wang return Root; 442*89f6b26fSZixu Wang } 443*89f6b26fSZixu Wang 444*89f6b26fSZixu Wang void SymbolGraphSerializer::serialize(raw_ostream &os) { 445*89f6b26fSZixu Wang Object root = serialize(); 446*89f6b26fSZixu Wang if (Options.Compact) 447*89f6b26fSZixu Wang os << formatv("{0}", Value(std::move(root))) << "\n"; 448*89f6b26fSZixu Wang else 449*89f6b26fSZixu Wang os << formatv("{0:2}", Value(std::move(root))) << "\n"; 450*89f6b26fSZixu Wang } 451