1 | //===- ExtractAPI/DeclarationFragments.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 Declaration Fragments related classes. |
11 | /// |
12 | /// Declaration Fragments represent parts of a symbol declaration tagged with |
13 | /// syntactic/semantic information. |
14 | /// See https://github.com/apple/swift-docc-symbolkit |
15 | /// |
16 | //===----------------------------------------------------------------------===// |
17 | |
18 | #ifndef LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H |
19 | #define |
20 | |
21 | #include "clang/AST/ASTContext.h" |
22 | #include "clang/AST/Decl.h" |
23 | #include "clang/AST/DeclCXX.h" |
24 | #include "clang/AST/DeclObjC.h" |
25 | #include "clang/AST/DeclTemplate.h" |
26 | #include "clang/AST/ExprCXX.h" |
27 | #include "clang/AST/TypeLoc.h" |
28 | #include "clang/Basic/Specifiers.h" |
29 | #include "clang/Lex/MacroInfo.h" |
30 | #include "llvm/ADT/SmallVector.h" |
31 | #include "llvm/ADT/StringRef.h" |
32 | #include <vector> |
33 | |
34 | namespace clang { |
35 | namespace extractapi { |
36 | |
37 | /// DeclarationFragments is a vector of tagged important parts of a symbol's |
38 | /// declaration. |
39 | /// |
40 | /// The fragments sequence can be joined to form spans of declaration text, with |
41 | /// attached information useful for purposes like syntax-highlighting etc. |
42 | /// For example: |
43 | /// \code |
44 | /// const -> keyword "const" |
45 | /// int -> type "int" |
46 | /// pi; -> identifier "pi" |
47 | /// \endcode |
48 | class { |
49 | public: |
50 | () = default; |
51 | |
52 | /// The kind of a fragment. |
53 | enum class { |
54 | /// Unknown fragment kind. |
55 | , |
56 | |
57 | , |
58 | , |
59 | , |
60 | , |
61 | , |
62 | |
63 | /// Identifier that refers to a type in the context. |
64 | , |
65 | |
66 | /// Parameter that's used as generics in the context. For example template |
67 | /// parameters. |
68 | , |
69 | |
70 | /// External parameters in Objective-C methods. |
71 | /// For example, \c forKey in |
72 | /// \code{.m} |
73 | /// - (void) setValue:(Value)value forKey(Key)key |
74 | /// \endcode |
75 | , |
76 | |
77 | /// Internal/local parameters in Objective-C methods. |
78 | /// For example, \c key in |
79 | /// \code{.m} |
80 | /// - (void) setValue:(Value)value forKey(Key)key |
81 | /// \endcode |
82 | , |
83 | |
84 | , |
85 | }; |
86 | |
87 | /// Fragment holds information of a single fragment. |
88 | struct { |
89 | std::string ; |
90 | FragmentKind ; |
91 | |
92 | /// The USR of the fragment symbol, if applicable. |
93 | std::string ; |
94 | |
95 | /// The associated declaration, if applicable. This is not intended to be |
96 | /// used outside of libclang. |
97 | const Decl *; |
98 | |
99 | (StringRef Spelling, FragmentKind Kind, StringRef PreciseIdentifier, |
100 | const Decl *Declaration) |
101 | : Spelling(Spelling), Kind(Kind), PreciseIdentifier(PreciseIdentifier), |
102 | Declaration(Declaration) {} |
103 | }; |
104 | |
105 | using = std::vector<Fragment>::iterator; |
106 | using = std::vector<Fragment>::const_iterator; |
107 | |
108 | const std::vector<Fragment> &() const { return Fragments; } |
109 | |
110 | FragmentIterator () { return Fragments.begin(); } |
111 | |
112 | FragmentIterator () { return Fragments.end(); } |
113 | |
114 | ConstFragmentIterator () const { return Fragments.cbegin(); } |
115 | |
116 | ConstFragmentIterator () const { return Fragments.cend(); } |
117 | |
118 | // Add a new Fragment at an arbitrary offset. |
119 | DeclarationFragments &(FragmentIterator It, StringRef Spelling, |
120 | FragmentKind Kind, |
121 | StringRef PreciseIdentifier = "" , |
122 | const Decl *Declaration = nullptr) { |
123 | Fragments.insert(position: It, |
124 | x: Fragment(Spelling, Kind, PreciseIdentifier, Declaration)); |
125 | return *this; |
126 | } |
127 | |
128 | DeclarationFragments &(FragmentIterator It, |
129 | DeclarationFragments &&Other) { |
130 | Fragments.insert(position: It, first: std::make_move_iterator(i: Other.Fragments.begin()), |
131 | last: std::make_move_iterator(i: Other.Fragments.end())); |
132 | Other.Fragments.clear(); |
133 | return *this; |
134 | } |
135 | |
136 | /// Append a new Fragment to the end of the Fragments. |
137 | /// |
138 | /// \returns a reference to the DeclarationFragments object itself after |
139 | /// appending to chain up consecutive appends. |
140 | DeclarationFragments &(StringRef Spelling, FragmentKind Kind, |
141 | StringRef PreciseIdentifier = "" , |
142 | const Decl *Declaration = nullptr) { |
143 | if (Kind == FragmentKind::Text && !Fragments.empty() && |
144 | Fragments.back().Kind == FragmentKind::Text) { |
145 | // If appending a text fragment, and the last fragment is also text, |
146 | // merge into the last fragment. |
147 | Fragments.back().Spelling.append(s: Spelling.data(), n: Spelling.size()); |
148 | } else { |
149 | Fragments.emplace_back(args&: Spelling, args&: Kind, args&: PreciseIdentifier, args&: Declaration); |
150 | } |
151 | return *this; |
152 | } |
153 | |
154 | /// Append another DeclarationFragments to the end. |
155 | /// |
156 | /// Note: \p Other is moved from and cannot be used after a call to this |
157 | /// method. |
158 | /// |
159 | /// \returns a reference to the DeclarationFragments object itself after |
160 | /// appending to chain up consecutive appends. |
161 | DeclarationFragments &(DeclarationFragments &&Other) { |
162 | Fragments.insert(position: Fragments.end(), |
163 | first: std::make_move_iterator(i: Other.Fragments.begin()), |
164 | last: std::make_move_iterator(i: Other.Fragments.end())); |
165 | Other.Fragments.clear(); |
166 | return *this; |
167 | } |
168 | |
169 | DeclarationFragments &() { |
170 | Fragments.pop_back(); |
171 | return *this; |
172 | } |
173 | |
174 | DeclarationFragments &(std::string NewSpelling, unsigned Position) { |
175 | Fragments.at(n: Position).Spelling = NewSpelling; |
176 | return *this; |
177 | } |
178 | |
179 | /// Append a text Fragment of a space character. |
180 | /// |
181 | /// \returns a reference to the DeclarationFragments object itself after |
182 | /// appending to chain up consecutive appends. |
183 | DeclarationFragments &(); |
184 | |
185 | /// Get the string description of a FragmentKind \p Kind. |
186 | static StringRef (FragmentKind Kind); |
187 | |
188 | /// Get the corresponding FragmentKind from string \p S. |
189 | static FragmentKind (StringRef S); |
190 | |
191 | static DeclarationFragments |
192 | (ExceptionSpecificationType ExceptionSpec); |
193 | |
194 | static DeclarationFragments (const RecordDecl *Decl); |
195 | |
196 | private: |
197 | std::vector<Fragment> ; |
198 | }; |
199 | |
200 | class { |
201 | public: |
202 | (std::string Access) : Access(Access) {} |
203 | |
204 | const std::string &() const { return Access; } |
205 | |
206 | bool () const { return Access.empty(); } |
207 | |
208 | private: |
209 | std::string ; |
210 | }; |
211 | |
212 | /// Store function signature information with DeclarationFragments of the |
213 | /// return type and parameters. |
214 | class { |
215 | public: |
216 | () = default; |
217 | |
218 | /// Parameter holds the name and DeclarationFragments of a single parameter. |
219 | struct { |
220 | std::string ; |
221 | DeclarationFragments ; |
222 | |
223 | (StringRef Name, DeclarationFragments Fragments) |
224 | : Name(Name), Fragments(Fragments) {} |
225 | }; |
226 | |
227 | const std::vector<Parameter> &() const { return Parameters; } |
228 | const DeclarationFragments &() const { return ReturnType; } |
229 | |
230 | FunctionSignature &(StringRef Name, |
231 | DeclarationFragments Fragments) { |
232 | Parameters.emplace_back(args&: Name, args&: Fragments); |
233 | return *this; |
234 | } |
235 | |
236 | void (DeclarationFragments RT) { ReturnType = RT; } |
237 | |
238 | /// Determine if the FunctionSignature is empty. |
239 | /// |
240 | /// \returns true if the return type DeclarationFragments is empty and there |
241 | /// is no parameter, otherwise false. |
242 | bool () const { |
243 | return Parameters.empty() && ReturnType.getFragments().empty(); |
244 | } |
245 | |
246 | private: |
247 | std::vector<Parameter> ; |
248 | DeclarationFragments ; |
249 | }; |
250 | |
251 | /// A factory class to build DeclarationFragments for different kinds of Decl. |
252 | class { |
253 | public: |
254 | /// Build FunctionSignature for a function-like declaration \c FunctionT like |
255 | /// FunctionDecl, ObjCMethodDecl, or CXXMethodDecl. |
256 | /// |
257 | /// The logic and implementation of building a signature for a FunctionDecl, |
258 | /// CXXMethodDecl, and ObjCMethodDecl are exactly the same, but they do not |
259 | /// share a common base. This template helps reuse the code. |
260 | template <typename FunctionT> |
261 | static FunctionSignature getFunctionSignature(const FunctionT *Function); |
262 | |
263 | static AccessControl (const Decl *Decl) { |
264 | switch (Decl->getAccess()) { |
265 | case AS_public: |
266 | case AS_none: |
267 | return AccessControl("public" ); |
268 | case AS_private: |
269 | return AccessControl("private" ); |
270 | case AS_protected: |
271 | return AccessControl("protected" ); |
272 | } |
273 | llvm_unreachable("Unhandled access control" ); |
274 | } |
275 | |
276 | static DeclarationFragments |
277 | (const NamespaceDecl *Decl); |
278 | |
279 | /// Build DeclarationFragments for a variable declaration VarDecl. |
280 | static DeclarationFragments (const VarDecl *); |
281 | |
282 | static DeclarationFragments (const VarDecl *); |
283 | |
284 | /// Build DeclarationFragments for a function declaration FunctionDecl. |
285 | static DeclarationFragments (const FunctionDecl *); |
286 | |
287 | /// Build DeclarationFragments for an enum constant declaration |
288 | /// EnumConstantDecl. |
289 | static DeclarationFragments |
290 | (const EnumConstantDecl *); |
291 | |
292 | /// Build DeclarationFragments for an enum declaration EnumDecl. |
293 | static DeclarationFragments (const EnumDecl *); |
294 | |
295 | /// Build DeclarationFragments for a field declaration FieldDecl. |
296 | static DeclarationFragments (const FieldDecl *); |
297 | |
298 | /// Build DeclarationFragments for a struct/union record declaration |
299 | /// RecordDecl. |
300 | static DeclarationFragments (const RecordDecl *); |
301 | |
302 | static DeclarationFragments (const CXXRecordDecl *); |
303 | |
304 | static DeclarationFragments |
305 | (const CXXMethodDecl *); |
306 | |
307 | static DeclarationFragments (const CXXMethodDecl *); |
308 | |
309 | static DeclarationFragments |
310 | (const CXXConversionDecl *); |
311 | |
312 | static DeclarationFragments |
313 | (const CXXMethodDecl *); |
314 | |
315 | static DeclarationFragments |
316 | (ArrayRef<NamedDecl *>); |
317 | |
318 | static std::string |
319 | (const ArrayRef<NamedDecl *>, std::string); |
320 | |
321 | static DeclarationFragments |
322 | (const ArrayRef<TemplateArgument>, |
323 | ASTContext &, |
324 | const std::optional<ArrayRef<NamedDecl *>>); |
325 | |
326 | static DeclarationFragments (const ConceptDecl *); |
327 | |
328 | static DeclarationFragments |
329 | (const RedeclarableTemplateDecl *); |
330 | |
331 | static DeclarationFragments ( |
332 | const ClassTemplateSpecializationDecl *); |
333 | |
334 | static DeclarationFragments ( |
335 | const ClassTemplatePartialSpecializationDecl *); |
336 | |
337 | static DeclarationFragments ( |
338 | const VarTemplateSpecializationDecl *); |
339 | |
340 | static DeclarationFragments ( |
341 | const VarTemplatePartialSpecializationDecl *); |
342 | |
343 | static DeclarationFragments |
344 | (const FunctionTemplateDecl *Decl); |
345 | |
346 | static DeclarationFragments |
347 | (const FunctionDecl *Decl); |
348 | |
349 | /// Build DeclarationFragments for an Objective-C category declaration |
350 | /// ObjCCategoryDecl. |
351 | static DeclarationFragments |
352 | (const ObjCCategoryDecl *); |
353 | |
354 | /// Build DeclarationFragments for an Objective-C interface declaration |
355 | /// ObjCInterfaceDecl. |
356 | static DeclarationFragments |
357 | (const ObjCInterfaceDecl *); |
358 | |
359 | /// Build DeclarationFragments for an Objective-C method declaration |
360 | /// ObjCMethodDecl. |
361 | static DeclarationFragments (const ObjCMethodDecl *); |
362 | |
363 | /// Build DeclarationFragments for an Objective-C property declaration |
364 | /// ObjCPropertyDecl. |
365 | static DeclarationFragments |
366 | (const ObjCPropertyDecl *); |
367 | |
368 | /// Build DeclarationFragments for an Objective-C protocol declaration |
369 | /// ObjCProtocolDecl. |
370 | static DeclarationFragments |
371 | (const ObjCProtocolDecl *); |
372 | |
373 | /// Build DeclarationFragments for a macro. |
374 | /// |
375 | /// \param Name name of the macro. |
376 | /// \param MD the associated MacroDirective. |
377 | static DeclarationFragments (StringRef Name, |
378 | const MacroDirective *MD); |
379 | |
380 | /// Build DeclarationFragments for a typedef \p TypedefNameDecl. |
381 | static DeclarationFragments |
382 | (const TypedefNameDecl *Decl); |
383 | |
384 | /// Build sub-heading fragments for a NamedDecl. |
385 | static DeclarationFragments (const NamedDecl *); |
386 | |
387 | /// Build sub-heading fragments for an Objective-C method. |
388 | static DeclarationFragments (const ObjCMethodDecl *); |
389 | |
390 | /// Build a sub-heading for macro \p Name. |
391 | static DeclarationFragments (StringRef Name); |
392 | |
393 | private: |
394 | () = delete; |
395 | |
396 | /// Build DeclarationFragments for a QualType. |
397 | static DeclarationFragments (const QualType, ASTContext &, |
398 | DeclarationFragments &); |
399 | |
400 | /// Build DeclarationFragments for a Type. |
401 | static DeclarationFragments (const Type *, ASTContext &, |
402 | DeclarationFragments &); |
403 | |
404 | /// Build DeclarationFragments for a NestedNameSpecifier. |
405 | static DeclarationFragments (const NestedNameSpecifier *, |
406 | ASTContext &, |
407 | DeclarationFragments &); |
408 | |
409 | /// Build DeclarationFragments for Qualifiers. |
410 | static DeclarationFragments (const Qualifiers quals); |
411 | |
412 | /// Build DeclarationFragments for a parameter variable declaration |
413 | /// ParmVarDecl. |
414 | static DeclarationFragments (const ParmVarDecl *); |
415 | |
416 | static DeclarationFragments |
417 | (const NamedDecl *BlockDecl, FunctionTypeLoc &Block, |
418 | FunctionProtoTypeLoc &BlockProto, |
419 | DeclarationFragments &After); |
420 | }; |
421 | |
422 | template <typename FunctionT> |
423 | FunctionSignature |
424 | DeclarationFragmentsBuilder::(const FunctionT *Function) { |
425 | FunctionSignature Signature; |
426 | |
427 | DeclarationFragments ReturnType, After; |
428 | ReturnType = getFragmentsForType(Function->getReturnType(), |
429 | Function->getASTContext(), After); |
430 | if (isa<FunctionDecl>(Function) && |
431 | dyn_cast<FunctionDecl>(Function)->getDescribedFunctionTemplate() && |
432 | StringRef(ReturnType.begin()->Spelling).starts_with(Prefix: "type-parameter" )) { |
433 | std::string ProperArgName = |
434 | getNameForTemplateArgument(dyn_cast<FunctionDecl>(Function) |
435 | ->getDescribedFunctionTemplate() |
436 | ->getTemplateParameters() |
437 | ->asArray(), |
438 | ReturnType.begin()->Spelling); |
439 | ReturnType.begin()->Spelling.swap(s&: ProperArgName); |
440 | } |
441 | ReturnType.append(Other: std::move(After)); |
442 | Signature.setReturnType(ReturnType); |
443 | |
444 | for (const auto *Param : Function->parameters()) |
445 | Signature.addParameter(Name: Param->getName(), Fragments: getFragmentsForParam(Param)); |
446 | |
447 | return Signature; |
448 | } |
449 | |
450 | } // namespace extractapi |
451 | } // namespace clang |
452 | |
453 | #endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H |
454 | |