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 |
19 | |
20 | #include "clang/Basic/Module.h" |
21 | #include "clang/ExtractAPI/API.h" |
22 | #include "clang/ExtractAPI/APIIgnoresList.h" |
23 | #include "clang/ExtractAPI/Serialization/APISetVisitor.h" |
24 | #include "llvm/ADT/DenseMap.h" |
25 | #include "llvm/ADT/SmallString.h" |
26 | #include "llvm/ADT/SmallVector.h" |
27 | #include "llvm/ADT/StringMap.h" |
28 | #include "llvm/ADT/StringRef.h" |
29 | #include "llvm/ADT/StringSet.h" |
30 | #include "llvm/ADT/Twine.h" |
31 | #include "llvm/Support/JSON.h" |
32 | #include "llvm/Support/VersionTuple.h" |
33 | #include "llvm/Support/raw_ostream.h" |
34 | #include <optional> |
35 | |
36 | namespace clang { |
37 | namespace extractapi { |
38 | |
39 | using namespace llvm::json; |
40 | |
41 | /// Common options to customize the visitor output. |
42 | struct { |
43 | /// Do not include unnecessary whitespaces to save space. |
44 | bool = true; |
45 | bool = false; |
46 | }; |
47 | |
48 | /// A representation of the contents of a given module symbol graph |
49 | struct { |
50 | () = default; |
51 | (ExtendedModule &&EM) = default; |
52 | ExtendedModule &(ExtendedModule &&EM) = default; |
53 | // Copies are expensive so disable them. |
54 | (const ExtendedModule &EM) = delete; |
55 | ExtendedModule &(const ExtendedModule &EM) = delete; |
56 | |
57 | /// Add a symbol to the module, do not store the resulting pointer or use it |
58 | /// across insertions. |
59 | Object *(Object &&Symbol); |
60 | |
61 | void (Object &&Relationship); |
62 | |
63 | /// A JSON array of formatted symbols from an \c APISet. |
64 | Array ; |
65 | |
66 | /// A JSON array of formatted symbol relationships from an \c APISet. |
67 | Array ; |
68 | }; |
69 | |
70 | /// The visitor that organizes API information in the Symbol Graph format. |
71 | /// |
72 | /// The Symbol Graph format (https://github.com/apple/swift-docc-symbolkit) |
73 | /// models an API set as a directed graph, where nodes are symbol declarations, |
74 | /// and edges are relationships between the connected symbols. |
75 | class : public APISetVisitor<SymbolGraphSerializer> { |
76 | private: |
77 | using = APISetVisitor<SymbolGraphSerializer>; |
78 | /// The main symbol graph that contains symbols that are either top-level or a |
79 | /// are related to symbols defined in this product/module. |
80 | ExtendedModule MainModule; |
81 | |
82 | /// Additional symbol graphs that contain symbols that are related to symbols |
83 | /// defined in another product/module. The key of this map is the module name |
84 | /// of the extended module. |
85 | llvm::StringMap<ExtendedModule> ; |
86 | |
87 | /// The Symbol Graph format version used by this serializer. |
88 | static const VersionTuple ; |
89 | |
90 | /// Indicates whether to take into account the extended module. This is only |
91 | /// useful for \c serializeSingleSymbolSGF. |
92 | bool ForceEmitToMainModule; |
93 | |
94 | // Stores the references required to construct path components for the |
95 | // currently visited APIRecord. |
96 | llvm::SmallVector<SymbolReference, 8> ; |
97 | |
98 | /// The list of symbols to ignore. |
99 | /// |
100 | /// Note: This should be consulted before emitting a symbol. |
101 | const APIIgnoresList &; |
102 | |
103 | const bool = false; |
104 | |
105 | /// The object instantiated by the last call to serializeAPIRecord. |
106 | Object * = nullptr; |
107 | |
108 | /// The module to which \p CurrentSymbol belongs too. |
109 | ExtendedModule * = nullptr; |
110 | |
111 | public: |
112 | static void |
113 | serializeMainSymbolGraph(raw_ostream &OS, const APISet &API, |
114 | const APIIgnoresList &IgnoresList, |
115 | SymbolGraphSerializerOption Options = {}); |
116 | |
117 | static void ( |
118 | raw_ostream &MainOutput, const APISet &API, |
119 | const APIIgnoresList &IgnoresList, |
120 | llvm::function_ref< |
121 | std::unique_ptr<llvm::raw_pwrite_stream>(llvm::Twine BaseFileName)> |
122 | CreateOutputStream, |
123 | SymbolGraphSerializerOption Options = {}); |
124 | |
125 | /// Serialize a single symbol SGF. This is primarily used for libclang. |
126 | /// |
127 | /// \returns an optional JSON Object representing the payload that libclang |
128 | /// expects for providing symbol information for a single symbol. If this is |
129 | /// not a known symbol returns \c std::nullopt. |
130 | static std::optional<Object> (StringRef USR, |
131 | const APISet &API); |
132 | |
133 | private: |
134 | /// The kind of a relationship between two symbols. |
135 | enum { |
136 | /// The source symbol is a member of the target symbol. |
137 | /// For example enum constants are members of the enum, class/instance |
138 | /// methods are members of the class, etc. |
139 | , |
140 | |
141 | /// The source symbol is inherited from the target symbol. |
142 | , |
143 | |
144 | /// The source symbol conforms to the target symbol. |
145 | /// For example Objective-C protocol conformances. |
146 | , |
147 | |
148 | /// The source symbol is an extension to the target symbol. |
149 | /// For example Objective-C categories extending an external type. |
150 | , |
151 | }; |
152 | |
153 | /// Serialize a single record. |
154 | void (const APIRecord *Record); |
155 | |
156 | /// Get the string representation of the relationship kind. |
157 | static StringRef (RelationshipKind Kind); |
158 | |
159 | void (RelationshipKind Kind, |
160 | const SymbolReference &Source, |
161 | const SymbolReference &Target, |
162 | ExtendedModule &Into); |
163 | |
164 | enum { , }; |
165 | |
166 | static StringRef (ConstraintKind Kind); |
167 | |
168 | /// Serialize the APIs in \c ExtendedModule. |
169 | /// |
170 | /// \returns a JSON object that contains the root of the formatted |
171 | /// Symbol Graph. |
172 | Object (StringRef ModuleName, ExtendedModule &&EM); |
173 | |
174 | /// Serialize the APIs in \c ExtendedModule in the Symbol Graph format and |
175 | /// write them to the provide stream. |
176 | void (raw_ostream &OS, |
177 | SymbolGraphSerializerOption Options, |
178 | StringRef ModuleName, ExtendedModule &&EM); |
179 | |
180 | /// Synthesize the metadata section of the Symbol Graph format. |
181 | /// |
182 | /// The metadata section describes information about the Symbol Graph itself, |
183 | /// including the format version and the generator information. |
184 | Object () const; |
185 | |
186 | /// Synthesize the module section of the Symbol Graph format. |
187 | /// |
188 | /// The module section contains information about the product that is defined |
189 | /// by the given API set. |
190 | /// Note that "module" here is not to be confused with the Clang/C++ module |
191 | /// concept. |
192 | Object (StringRef ModuleName) const; |
193 | |
194 | Array (const APIRecord *Record) const; |
195 | |
196 | /// Determine if the given \p Record should be skipped during serialization. |
197 | bool (const APIRecord *Record) const; |
198 | |
199 | ExtendedModule &(); |
200 | |
201 | /// Format the common API information for \p Record. |
202 | /// |
203 | /// This handles the shared information of all kinds of API records, |
204 | /// for example identifier, source location and path components. The resulting |
205 | /// object is then augmented with kind-specific symbol information in |
206 | /// subsequent visit* methods by accessing the \p State member variable. This |
207 | /// method also checks if the given \p Record should be skipped during |
208 | /// serialization. This should be called only once per concrete APIRecord |
209 | /// instance and the first visit* method to be called is responsible for |
210 | /// calling this. This is normally visitAPIRecord unless a walkUpFromFoo |
211 | /// method is implemented along the inheritance hierarchy in which case the |
212 | /// visitFoo method needs to call this. |
213 | /// |
214 | /// \returns \c nullptr if this \p Record should be skipped, or a pointer to |
215 | /// JSON object containing common symbol information of \p Record. Do not |
216 | /// store the returned pointer only use it to augment the object with record |
217 | /// specific information as it directly points to the object in the |
218 | /// \p ExtendedModule, the pointer won't be valid as soon as another object is |
219 | /// inserted into the module. |
220 | void (const APIRecord *Record); |
221 | |
222 | public: |
223 | // Handle if records should be skipped at this level of the traversal to |
224 | // ensure that children of skipped records aren't serialized. |
225 | bool (const APIRecord *Record); |
226 | |
227 | bool (const APIRecord *Record); |
228 | |
229 | /// Visit a global function record. |
230 | bool (const GlobalFunctionRecord *Record); |
231 | |
232 | bool (const CXXClassRecord *Record); |
233 | |
234 | bool (const ClassTemplateRecord *Record); |
235 | |
236 | bool ( |
237 | const ClassTemplatePartialSpecializationRecord *Record); |
238 | |
239 | bool (const CXXMethodRecord *Record); |
240 | |
241 | bool (const CXXMethodTemplateRecord *Record); |
242 | |
243 | bool (const CXXFieldTemplateRecord *Record); |
244 | |
245 | bool (const ConceptRecord *Record); |
246 | |
247 | bool |
248 | (const GlobalVariableTemplateRecord *Record); |
249 | |
250 | bool ( |
251 | const GlobalVariableTemplatePartialSpecializationRecord *Record); |
252 | |
253 | bool |
254 | (const GlobalFunctionTemplateRecord *Record); |
255 | |
256 | bool (const ObjCContainerRecord *Record); |
257 | |
258 | bool (const ObjCInterfaceRecord *Record); |
259 | |
260 | bool (const ObjCCategoryRecord *Record); |
261 | bool (const ObjCCategoryRecord *Record); |
262 | bool (const ObjCCategoryRecord *Record); |
263 | |
264 | bool (const ObjCMethodRecord *Record); |
265 | |
266 | bool |
267 | (const ObjCInstanceVariableRecord *Record); |
268 | |
269 | bool (const TypedefRecord *Record); |
270 | bool (const TypedefRecord *Record); |
271 | |
272 | (const APISet &API, const APIIgnoresList &IgnoresList, |
273 | bool EmitSymbolLabelsForTesting = false, |
274 | bool ForceEmitToMainModule = false) |
275 | : Base(API), ForceEmitToMainModule(ForceEmitToMainModule), |
276 | IgnoresList(IgnoresList), |
277 | EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting) {} |
278 | }; |
279 | |
280 | } // namespace extractapi |
281 | } // namespace clang |
282 | |
283 | #endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H |
284 | |