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