1 //===- ExtractAPI/Serialization/SymbolGraphSerializer.h ---------*- 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 /// 9 /// \file 10 /// This file defines the SymbolGraphSerializer class. 11 /// 12 /// Implement an APISerializer for the Symbol Graph format for ExtractAPI. 13 /// See https://github.com/apple/swift-docc-symbolkit. 14 /// 15 //===----------------------------------------------------------------------===// 16 17 #ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H 18 #define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H 19 20 #include "clang/ExtractAPI/API.h" 21 #include "clang/ExtractAPI/APIIgnoresList.h" 22 #include "clang/ExtractAPI/Serialization/SerializerBase.h" 23 #include "llvm/ADT/SmallVector.h" 24 #include "llvm/Support/JSON.h" 25 #include "llvm/Support/VersionTuple.h" 26 #include "llvm/Support/raw_ostream.h" 27 #include <optional> 28 29 namespace clang { 30 namespace extractapi { 31 32 using namespace llvm::json; 33 34 /// The serializer that organizes API information in the Symbol Graph format. 35 /// 36 /// The Symbol Graph format (https://github.com/apple/swift-docc-symbolkit) 37 /// models an API set as a directed graph, where nodes are symbol declarations, 38 /// and edges are relationships between the connected symbols. 39 class SymbolGraphSerializer : public APISerializer { 40 virtual void anchor(); 41 42 /// A JSON array of formatted symbols in \c APISet. 43 Array Symbols; 44 45 /// A JSON array of formatted symbol relationships in \c APISet. 46 Array Relationships; 47 48 /// The Symbol Graph format version used by this serializer. 49 static const VersionTuple FormatVersion; 50 51 /// Indicates whether child symbols should be serialized. This is mainly 52 /// useful for \c serializeSingleSymbolSGF. 53 bool ShouldRecurse; 54 55 public: 56 /// Serialize the APIs in \c APISet in the Symbol Graph format. 57 /// 58 /// \returns a JSON object that contains the root of the formatted 59 /// Symbol Graph. 60 Object serialize(); 61 62 /// Implement the APISerializer::serialize interface. Wrap serialize(void) and 63 /// write out the serialized JSON object to \p os. 64 void serialize(raw_ostream &os) override; 65 66 /// Serialize a single symbol SGF. This is primarily used for libclang. 67 /// 68 /// \returns an optional JSON Object representing the payload that libclang 69 /// expects for providing symbol information for a single symbol. If this is 70 /// not a known symbol returns \c None. 71 static std::optional<Object> serializeSingleSymbolSGF(StringRef USR, 72 const APISet &API); 73 74 /// The kind of a relationship between two symbols. 75 enum RelationshipKind { 76 /// The source symbol is a member of the target symbol. 77 /// For example enum constants are members of the enum, class/instance 78 /// methods are members of the class, etc. 79 MemberOf, 80 81 /// The source symbol is inherited from the target symbol. 82 InheritsFrom, 83 84 /// The source symbol conforms to the target symbol. 85 /// For example Objective-C protocol conformances. 86 ConformsTo, 87 }; 88 89 /// Get the string representation of the relationship kind. 90 static StringRef getRelationshipString(RelationshipKind Kind); 91 92 private: 93 /// Just serialize the currently recorded objects in Symbol Graph format. 94 Object serializeCurrentGraph(); 95 96 /// Synthesize the metadata section of the Symbol Graph format. 97 /// 98 /// The metadata section describes information about the Symbol Graph itself, 99 /// including the format version and the generator information. 100 Object serializeMetadata() const; 101 102 /// Synthesize the module section of the Symbol Graph format. 103 /// 104 /// The module section contains information about the product that is defined 105 /// by the given API set. 106 /// Note that "module" here is not to be confused with the Clang/C++ module 107 /// concept. 108 Object serializeModule() const; 109 110 /// Determine if the given \p Record should be skipped during serialization. 111 bool shouldSkip(const APIRecord &Record) const; 112 113 /// Format the common API information for \p Record. 114 /// 115 /// This handles the shared information of all kinds of API records, 116 /// for example identifier and source location. The resulting object is then 117 /// augmented with kind-specific symbol information by the caller. 118 /// This method also checks if the given \p Record should be skipped during 119 /// serialization. 120 /// 121 /// \returns \c std::nullopt if this \p Record should be skipped, or a JSON 122 /// object containing common symbol information of \p Record. 123 template <typename RecordTy> 124 std::optional<Object> serializeAPIRecord(const RecordTy &Record) const; 125 126 /// Helper method to serialize second-level member records of \p Record and 127 /// the member-of relationships. 128 template <typename MemberTy> 129 void serializeMembers(const APIRecord &Record, 130 const SmallVector<std::unique_ptr<MemberTy>> &Members); 131 132 /// Serialize the \p Kind relationship between \p Source and \p Target. 133 /// 134 /// Record the relationship between the two symbols in 135 /// SymbolGraphSerializer::Relationships. 136 void serializeRelationship(RelationshipKind Kind, SymbolReference Source, 137 SymbolReference Target); 138 139 /// Serialize a global function record. 140 void serializeGlobalFunctionRecord(const GlobalFunctionRecord &Record); 141 142 /// Serialize a global variable record. 143 void serializeGlobalVariableRecord(const GlobalVariableRecord &Record); 144 145 /// Serialize an enum record. 146 void serializeEnumRecord(const EnumRecord &Record); 147 148 /// Serialize a struct record. 149 void serializeStructRecord(const StructRecord &Record); 150 151 /// Serialize an Objective-C container record. 152 void serializeObjCContainerRecord(const ObjCContainerRecord &Record); 153 154 /// Serialize a macro definition record. 155 void serializeMacroDefinitionRecord(const MacroDefinitionRecord &Record); 156 157 /// Serialize a typedef record. 158 void serializeTypedefRecord(const TypedefRecord &Record); 159 160 void serializeSingleRecord(const APIRecord *Record); 161 162 public: 163 SymbolGraphSerializer(const APISet &API, const APIIgnoresList &IgnoresList, 164 APISerializerOption Options = {}, 165 bool ShouldRecurse = true) 166 : APISerializer(API, IgnoresList, Options), ShouldRecurse(ShouldRecurse) { 167 } 168 }; 169 170 } // namespace extractapi 171 } // namespace clang 172 173 #endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H 174