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 <iterator> |
31 | #include <utility> |
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 | /// Prepend another DeclarationFragments to the beginning. |
119 | /// |
120 | /// \returns a reference to the DeclarationFragments object itself after |
121 | /// appending to chain up consecutive operations. |
122 | DeclarationFragments &(DeclarationFragments Other) { |
123 | return insert(It: begin(), Other: std::move(Other)); |
124 | } |
125 | |
126 | /// Append another DeclarationFragments to the end. |
127 | /// |
128 | /// \returns a reference to the DeclarationFragments object itself after |
129 | /// appending to chain up consecutive operations. |
130 | DeclarationFragments &(DeclarationFragments Other) { |
131 | return insert(It: end(), Other: std::move(Other)); |
132 | } |
133 | |
134 | /// Append a new Fragment to the end of the Fragments. |
135 | /// |
136 | /// \returns a reference to the DeclarationFragments object itself after |
137 | /// appending to chain up consecutive operations. |
138 | DeclarationFragments &(StringRef Spelling, FragmentKind Kind, |
139 | StringRef PreciseIdentifier = "" , |
140 | const Decl *Declaration = nullptr) { |
141 | if (Kind == FragmentKind::Text && !Fragments.empty() && |
142 | Fragments.back().Kind == FragmentKind::Text) { |
143 | // If appending a text fragment, and the last fragment is also text, |
144 | // merge into the last fragment. |
145 | Fragments.back().Spelling.append(s: Spelling.data(), n: Spelling.size()); |
146 | } else { |
147 | Fragments.emplace_back(args&: Spelling, args&: Kind, args&: PreciseIdentifier, args&: Declaration); |
148 | } |
149 | return *this; |
150 | } |
151 | |
152 | /// Inserts another DeclarationFragments at \p It. |
153 | /// |
154 | /// \returns a reference to the DeclarationFragments object itself after |
155 | /// appending to chain up consecutive operations. |
156 | DeclarationFragments &(FragmentIterator It, |
157 | DeclarationFragments Other) { |
158 | if (Other.Fragments.empty()) |
159 | return *this; |
160 | |
161 | if (Fragments.empty()) { |
162 | Fragments = std::move(Other.Fragments); |
163 | return *this; |
164 | } |
165 | |
166 | const auto &OtherFrags = Other.Fragments; |
167 | auto ToInsertBegin = std::make_move_iterator(i: Other.begin()); |
168 | auto ToInsertEnd = std::make_move_iterator(i: Other.end()); |
169 | |
170 | // If we aren't inserting at the end let's make sure that we merge their |
171 | // last fragment with It if both are text fragments. |
172 | if (It != end() && It->Kind == FragmentKind::Text && |
173 | OtherFrags.back().Kind == FragmentKind::Text) { |
174 | auto &TheirBackSpelling = OtherFrags.back().Spelling; |
175 | It->Spelling.reserve(res: It->Spelling.size() + TheirBackSpelling.size()); |
176 | It->Spelling.insert(p: It->Spelling.begin(), beg: TheirBackSpelling.begin(), |
177 | end: TheirBackSpelling.end()); |
178 | --ToInsertEnd; |
179 | } |
180 | |
181 | // If we aren't inserting at the beginning we want to merge their first |
182 | // fragment with the fragment before It if both are text fragments. |
183 | if (It != begin() && std::prev(x: It)->Kind == FragmentKind::Text && |
184 | OtherFrags.front().Kind == FragmentKind::Text) { |
185 | auto PrevIt = std::prev(x: It); |
186 | auto &TheirFrontSpelling = OtherFrags.front().Spelling; |
187 | PrevIt->Spelling.reserve(res: PrevIt->Spelling.size() + |
188 | TheirFrontSpelling.size()); |
189 | PrevIt->Spelling.append(str: TheirFrontSpelling); |
190 | ++ToInsertBegin; |
191 | } |
192 | |
193 | Fragments.insert(position: It, first: ToInsertBegin, last: ToInsertEnd); |
194 | return *this; |
195 | } |
196 | |
197 | DeclarationFragments &() { |
198 | Fragments.pop_back(); |
199 | return *this; |
200 | } |
201 | |
202 | DeclarationFragments &(std::string NewSpelling, unsigned Position) { |
203 | Fragments.at(n: Position).Spelling = NewSpelling; |
204 | return *this; |
205 | } |
206 | |
207 | /// Append a text Fragment of a space character. |
208 | /// |
209 | /// \returns a reference to the DeclarationFragments object itself after |
210 | /// appending to chain up consecutive operations. |
211 | DeclarationFragments &(); |
212 | |
213 | /// Append a text Fragment of a semicolon character. |
214 | /// |
215 | /// \returns a reference to the DeclarationFragments object itself after |
216 | /// appending to chain up consecutive operations. |
217 | DeclarationFragments &(); |
218 | |
219 | /// Removes a trailing semicolon character if present. |
220 | /// |
221 | /// \returns a reference to the DeclarationFragments object itself after |
222 | /// removing to chain up consecutive operations. |
223 | DeclarationFragments &(); |
224 | |
225 | /// Get the string description of a FragmentKind \p Kind. |
226 | static StringRef (FragmentKind Kind); |
227 | |
228 | /// Get the corresponding FragmentKind from string \p S. |
229 | static FragmentKind (StringRef S); |
230 | |
231 | static DeclarationFragments |
232 | (ExceptionSpecificationType ExceptionSpec); |
233 | |
234 | static DeclarationFragments (const RecordDecl *Decl); |
235 | |
236 | private: |
237 | DeclarationFragments &(char Character); |
238 | std::vector<Fragment> ; |
239 | }; |
240 | |
241 | class { |
242 | public: |
243 | (std::string Access) : Access(Access) {} |
244 | () : Access("public" ) {} |
245 | |
246 | const std::string &() const { return Access; } |
247 | |
248 | bool () const { return Access.empty(); } |
249 | |
250 | private: |
251 | std::string ; |
252 | }; |
253 | |
254 | /// Store function signature information with DeclarationFragments of the |
255 | /// return type and parameters. |
256 | class { |
257 | public: |
258 | () = default; |
259 | |
260 | /// Parameter holds the name and DeclarationFragments of a single parameter. |
261 | struct { |
262 | std::string ; |
263 | DeclarationFragments ; |
264 | |
265 | (StringRef Name, DeclarationFragments Fragments) |
266 | : Name(Name), Fragments(Fragments) {} |
267 | }; |
268 | |
269 | const std::vector<Parameter> &() const { return Parameters; } |
270 | const DeclarationFragments &() const { return ReturnType; } |
271 | |
272 | FunctionSignature &(StringRef Name, |
273 | DeclarationFragments Fragments) { |
274 | Parameters.emplace_back(args&: Name, args&: Fragments); |
275 | return *this; |
276 | } |
277 | |
278 | void (DeclarationFragments RT) { ReturnType = RT; } |
279 | |
280 | /// Determine if the FunctionSignature is empty. |
281 | /// |
282 | /// \returns true if the return type DeclarationFragments is empty and there |
283 | /// is no parameter, otherwise false. |
284 | bool () const { |
285 | return Parameters.empty() && ReturnType.getFragments().empty(); |
286 | } |
287 | |
288 | private: |
289 | std::vector<Parameter> ; |
290 | DeclarationFragments ; |
291 | }; |
292 | |
293 | /// A factory class to build DeclarationFragments for different kinds of Decl. |
294 | class { |
295 | public: |
296 | /// Build FunctionSignature for a function-like declaration \c FunctionT like |
297 | /// FunctionDecl, ObjCMethodDecl, or CXXMethodDecl. |
298 | /// |
299 | /// The logic and implementation of building a signature for a FunctionDecl, |
300 | /// CXXMethodDecl, and ObjCMethodDecl are exactly the same, but they do not |
301 | /// share a common base. This template helps reuse the code. |
302 | template <typename FunctionT> |
303 | static FunctionSignature getFunctionSignature(const FunctionT *Function); |
304 | |
305 | static AccessControl (const Decl *Decl) { |
306 | switch (Decl->getAccess()) { |
307 | case AS_public: |
308 | case AS_none: |
309 | return AccessControl("public" ); |
310 | case AS_private: |
311 | return AccessControl("private" ); |
312 | case AS_protected: |
313 | return AccessControl("protected" ); |
314 | } |
315 | llvm_unreachable("Unhandled access control" ); |
316 | } |
317 | |
318 | static DeclarationFragments |
319 | (const NamespaceDecl *Decl); |
320 | |
321 | /// Build DeclarationFragments for a variable declaration VarDecl. |
322 | static DeclarationFragments (const VarDecl *); |
323 | |
324 | static DeclarationFragments (const VarDecl *); |
325 | |
326 | /// Build DeclarationFragments for a function declaration FunctionDecl. |
327 | static DeclarationFragments (const FunctionDecl *); |
328 | |
329 | /// Build DeclarationFragments for an enum constant declaration |
330 | /// EnumConstantDecl. |
331 | static DeclarationFragments |
332 | (const EnumConstantDecl *); |
333 | |
334 | /// Build DeclarationFragments for an enum declaration EnumDecl. |
335 | static DeclarationFragments (const EnumDecl *); |
336 | |
337 | /// Build DeclarationFragments for a field declaration FieldDecl. |
338 | static DeclarationFragments (const FieldDecl *); |
339 | |
340 | /// Build DeclarationFragments for a struct/union record declaration |
341 | /// RecordDecl. |
342 | static DeclarationFragments (const RecordDecl *); |
343 | |
344 | static DeclarationFragments (const CXXRecordDecl *); |
345 | |
346 | static DeclarationFragments |
347 | (const CXXMethodDecl *); |
348 | |
349 | static DeclarationFragments (const CXXMethodDecl *); |
350 | |
351 | static DeclarationFragments |
352 | (const CXXConversionDecl *); |
353 | |
354 | static DeclarationFragments |
355 | (const CXXMethodDecl *); |
356 | |
357 | static DeclarationFragments |
358 | (ArrayRef<NamedDecl *>); |
359 | |
360 | static DeclarationFragments ( |
361 | const ArrayRef<TemplateArgument>, ASTContext &, |
362 | const std::optional<ArrayRef<TemplateArgumentLoc>>); |
363 | |
364 | static DeclarationFragments (const ConceptDecl *); |
365 | |
366 | static DeclarationFragments |
367 | (const RedeclarableTemplateDecl *); |
368 | |
369 | static DeclarationFragments ( |
370 | const ClassTemplateSpecializationDecl *); |
371 | |
372 | static DeclarationFragments ( |
373 | const ClassTemplatePartialSpecializationDecl *); |
374 | |
375 | static DeclarationFragments ( |
376 | const VarTemplateSpecializationDecl *); |
377 | |
378 | static DeclarationFragments ( |
379 | const VarTemplatePartialSpecializationDecl *); |
380 | |
381 | static DeclarationFragments |
382 | (const FunctionTemplateDecl *Decl); |
383 | |
384 | static DeclarationFragments |
385 | (const FunctionDecl *Decl); |
386 | |
387 | /// Build DeclarationFragments for an Objective-C category declaration |
388 | /// ObjCCategoryDecl. |
389 | static DeclarationFragments |
390 | (const ObjCCategoryDecl *); |
391 | |
392 | /// Build DeclarationFragments for an Objective-C interface declaration |
393 | /// ObjCInterfaceDecl. |
394 | static DeclarationFragments |
395 | (const ObjCInterfaceDecl *); |
396 | |
397 | /// Build DeclarationFragments for an Objective-C method declaration |
398 | /// ObjCMethodDecl. |
399 | static DeclarationFragments (const ObjCMethodDecl *); |
400 | |
401 | /// Build DeclarationFragments for an Objective-C property declaration |
402 | /// ObjCPropertyDecl. |
403 | static DeclarationFragments |
404 | (const ObjCPropertyDecl *); |
405 | |
406 | /// Build DeclarationFragments for an Objective-C protocol declaration |
407 | /// ObjCProtocolDecl. |
408 | static DeclarationFragments |
409 | (const ObjCProtocolDecl *); |
410 | |
411 | /// Build DeclarationFragments for a macro. |
412 | /// |
413 | /// \param Name name of the macro. |
414 | /// \param MD the associated MacroDirective. |
415 | static DeclarationFragments (StringRef Name, |
416 | const MacroDirective *MD); |
417 | |
418 | /// Build DeclarationFragments for a typedef \p TypedefNameDecl. |
419 | static DeclarationFragments |
420 | (const TypedefNameDecl *Decl); |
421 | |
422 | /// Build sub-heading fragments for a NamedDecl. |
423 | static DeclarationFragments (const NamedDecl *); |
424 | |
425 | /// Build sub-heading fragments for an Objective-C method. |
426 | static DeclarationFragments (const ObjCMethodDecl *); |
427 | |
428 | /// Build a sub-heading for macro \p Name. |
429 | static DeclarationFragments (StringRef Name); |
430 | |
431 | private: |
432 | () = delete; |
433 | |
434 | /// Build DeclarationFragments for a QualType. |
435 | static DeclarationFragments (const QualType, ASTContext &, |
436 | DeclarationFragments &); |
437 | |
438 | /// Build DeclarationFragments for a Type. |
439 | static DeclarationFragments (const Type *, ASTContext &, |
440 | DeclarationFragments &); |
441 | |
442 | /// Build DeclarationFragments for a NestedNameSpecifier. |
443 | static DeclarationFragments (const NestedNameSpecifier *, |
444 | ASTContext &, |
445 | DeclarationFragments &); |
446 | |
447 | /// Build DeclarationFragments for Qualifiers. |
448 | static DeclarationFragments (const Qualifiers quals); |
449 | |
450 | /// Build DeclarationFragments for a parameter variable declaration |
451 | /// ParmVarDecl. |
452 | static DeclarationFragments (const ParmVarDecl *); |
453 | |
454 | static DeclarationFragments |
455 | (const NamedDecl *BlockDecl, FunctionTypeLoc &Block, |
456 | FunctionProtoTypeLoc &BlockProto, |
457 | DeclarationFragments &After); |
458 | }; |
459 | |
460 | template <typename FunctionT> |
461 | FunctionSignature |
462 | DeclarationFragmentsBuilder::(const FunctionT *Function) { |
463 | FunctionSignature Signature; |
464 | |
465 | DeclarationFragments ReturnType, After; |
466 | ReturnType = getFragmentsForType(Function->getReturnType(), |
467 | Function->getASTContext(), After); |
468 | if (isa<FunctionDecl>(Function) && |
469 | dyn_cast<FunctionDecl>(Function)->getDescribedFunctionTemplate() && |
470 | StringRef(ReturnType.begin()->Spelling).starts_with(Prefix: "type-parameter" )) { |
471 | std::string ProperArgName = Function->getReturnType().getAsString(); |
472 | ReturnType.begin()->Spelling.swap(s&: ProperArgName); |
473 | } |
474 | ReturnType.append(Other: std::move(After)); |
475 | Signature.setReturnType(ReturnType); |
476 | |
477 | for (const auto *Param : Function->parameters()) |
478 | Signature.addParameter(Name: Param->getName(), Fragments: getFragmentsForParam(Param)); |
479 | |
480 | return Signature; |
481 | } |
482 | |
483 | } // namespace extractapi |
484 | } // namespace clang |
485 | |
486 | #endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H |
487 | |