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 APISetVisitor to serialize the APISet into the Symbol Graph 13 /// format for ExtractAPI. 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/ADT/StringSet.h" 25 #include "llvm/Support/JSON.h" 26 #include "llvm/Support/VersionTuple.h" 27 #include "llvm/Support/raw_ostream.h" 28 #include <optional> 29 30 namespace clang { 31 namespace extractapi { 32 33 using namespace llvm::json; 34 35 /// Common options to customize the visitor output. 36 struct SymbolGraphSerializerOption { 37 /// Do not include unnecessary whitespaces to save space. 38 bool Compact; 39 }; 40 41 /// The visitor that organizes API information in the Symbol Graph format. 42 /// 43 /// The Symbol Graph format (https://github.com/apple/swift-docc-symbolkit) 44 /// models an API set as a directed graph, where nodes are symbol declarations, 45 /// and edges are relationships between the connected symbols. 46 class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> { 47 /// A JSON array of formatted symbols in \c APISet. 48 Array Symbols; 49 50 /// A JSON array of formatted symbol relationships in \c APISet. 51 Array Relationships; 52 53 /// The Symbol Graph format version used by this serializer. 54 static const VersionTuple FormatVersion; 55 56 /// Indicates whether child symbols should be visited. This is mainly 57 /// useful for \c serializeSingleSymbolSGF. 58 bool ShouldRecurse; 59 60 public: 61 /// Serialize the APIs in \c APISet in the Symbol Graph format. 62 /// 63 /// \returns a JSON object that contains the root of the formatted 64 /// Symbol Graph. 65 Object serialize(); 66 67 /// Wrap serialize(void) and write out the serialized JSON object to \p os. 68 void serialize(raw_ostream &os); 69 70 /// Serialize a single symbol SGF. This is primarily used for libclang. 71 /// 72 /// \returns an optional JSON Object representing the payload that libclang 73 /// expects for providing symbol information for a single symbol. If this is 74 /// not a known symbol returns \c std::nullopt. 75 static std::optional<Object> serializeSingleSymbolSGF(StringRef USR, 76 const APISet &API); 77 78 /// The kind of a relationship between two symbols. 79 enum RelationshipKind { 80 /// The source symbol is a member of the target symbol. 81 /// For example enum constants are members of the enum, class/instance 82 /// methods are members of the class, etc. 83 MemberOf, 84 85 /// The source symbol is inherited from the target symbol. 86 InheritsFrom, 87 88 /// The source symbol conforms to the target symbol. 89 /// For example Objective-C protocol conformances. 90 ConformsTo, 91 92 /// The source symbol is an extension to the target symbol. 93 /// For example Objective-C categories extending an external type. 94 ExtensionTo, 95 }; 96 97 /// Get the string representation of the relationship kind. 98 static StringRef getRelationshipString(RelationshipKind Kind); 99 100 enum ConstraintKind { Conformance, ConditionalConformance }; 101 102 static StringRef getConstraintString(ConstraintKind Kind); 103 104 private: 105 /// Just serialize the currently recorded objects in Symbol Graph format. 106 Object serializeCurrentGraph(); 107 108 /// Synthesize the metadata section of the Symbol Graph format. 109 /// 110 /// The metadata section describes information about the Symbol Graph itself, 111 /// including the format version and the generator information. 112 Object serializeMetadata() const; 113 114 /// Synthesize the module section of the Symbol Graph format. 115 /// 116 /// The module section contains information about the product that is defined 117 /// by the given API set. 118 /// Note that "module" here is not to be confused with the Clang/C++ module 119 /// concept. 120 Object serializeModule() const; 121 122 /// Determine if the given \p Record should be skipped during serialization. 123 bool shouldSkip(const APIRecord &Record) const; 124 125 /// Format the common API information for \p Record. 126 /// 127 /// This handles the shared information of all kinds of API records, 128 /// for example identifier and source location. The resulting object is then 129 /// augmented with kind-specific symbol information by the caller. 130 /// This method also checks if the given \p Record should be skipped during 131 /// serialization. 132 /// 133 /// \returns \c std::nullopt if this \p Record should be skipped, or a JSON 134 /// object containing common symbol information of \p Record. 135 template <typename RecordTy> 136 std::optional<Object> serializeAPIRecord(const RecordTy &Record) const; 137 138 /// Helper method to serialize second-level member records of \p Record and 139 /// the member-of relationships. 140 template <typename MemberTy> 141 void serializeMembers(const APIRecord &Record, 142 const SmallVector<std::unique_ptr<MemberTy>> &Members); 143 144 /// Serialize the \p Kind relationship between \p Source and \p Target. 145 /// 146 /// Record the relationship between the two symbols in 147 /// SymbolGraphSerializer::Relationships. 148 void serializeRelationship(RelationshipKind Kind, SymbolReference Source, 149 SymbolReference Target); 150 151 protected: 152 /// The list of symbols to ignore. 153 /// 154 /// Note: This should be consulted before emitting a symbol. 155 const APIIgnoresList &IgnoresList; 156 157 SymbolGraphSerializerOption Options; 158 159 llvm::StringSet<> visitedCategories; 160 161 public: 162 void visitNamespaceRecord(const NamespaceRecord &Record); 163 164 /// Visit a global function record. 165 void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record); 166 167 /// Visit a global variable record. 168 void visitGlobalVariableRecord(const GlobalVariableRecord &Record); 169 170 /// Visit an enum record. 171 void visitEnumRecord(const EnumRecord &Record); 172 173 /// Visit a record record. 174 void visitRecordRecord(const RecordRecord &Record); 175 176 void visitStaticFieldRecord(const StaticFieldRecord &Record); 177 178 void visitCXXClassRecord(const CXXClassRecord &Record); 179 180 void visitClassTemplateRecord(const ClassTemplateRecord &Record); 181 182 void visitClassTemplateSpecializationRecord( 183 const ClassTemplateSpecializationRecord &Record); 184 185 void visitClassTemplatePartialSpecializationRecord( 186 const ClassTemplatePartialSpecializationRecord &Record); 187 188 void visitCXXInstanceMethodRecord(const CXXInstanceMethodRecord &Record); 189 190 void visitCXXStaticMethodRecord(const CXXStaticMethodRecord &Record); 191 192 void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record); 193 194 void visitMethodTemplateSpecializationRecord( 195 const CXXMethodTemplateSpecializationRecord &Record); 196 197 void visitCXXFieldRecord(const CXXFieldRecord &Record); 198 199 void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record); 200 201 void visitConceptRecord(const ConceptRecord &Record); 202 203 void 204 visitGlobalVariableTemplateRecord(const GlobalVariableTemplateRecord &Record); 205 206 void visitGlobalVariableTemplateSpecializationRecord( 207 const GlobalVariableTemplateSpecializationRecord &Record); 208 209 void visitGlobalVariableTemplatePartialSpecializationRecord( 210 const GlobalVariableTemplatePartialSpecializationRecord &Record); 211 212 void 213 visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord &Record); 214 215 void visitGlobalFunctionTemplateSpecializationRecord( 216 const GlobalFunctionTemplateSpecializationRecord &Record); 217 218 /// Visit an Objective-C container record. 219 void visitObjCContainerRecord(const ObjCContainerRecord &Record); 220 221 /// Visit an Objective-C category record. 222 void visitObjCCategoryRecord(const ObjCCategoryRecord &Record); 223 224 /// Visit a macro definition record. 225 void visitMacroDefinitionRecord(const MacroDefinitionRecord &Record); 226 227 /// Visit a typedef record. 228 void visitTypedefRecord(const TypedefRecord &Record); 229 230 /// Serialize a single record. 231 void serializeSingleRecord(const APIRecord *Record); 232 233 SymbolGraphSerializer(const APISet &API, const APIIgnoresList &IgnoresList, 234 SymbolGraphSerializerOption Options = {}, 235 bool ShouldRecurse = true) APISetVisitor(API)236 : APISetVisitor(API), ShouldRecurse(ShouldRecurse), 237 IgnoresList(IgnoresList), Options(Options) {} 238 }; 239 240 } // namespace extractapi 241 } // namespace clang 242 243 #endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H 244