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