1 | //===- ExtractAPI/DeclarationFragments.cpp ----------------------*- 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 implements Declaration Fragments related classes. |
11 | /// |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "clang/ExtractAPI/DeclarationFragments.h" |
15 | #include "clang/AST/Decl.h" |
16 | #include "clang/AST/DeclCXX.h" |
17 | #include "clang/AST/Type.h" |
18 | #include "clang/AST/TypeLoc.h" |
19 | #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" |
20 | #include "clang/Index/USRGeneration.h" |
21 | #include "llvm/ADT/StringSwitch.h" |
22 | |
23 | using namespace clang::extractapi; |
24 | using namespace llvm; |
25 | |
26 | namespace { |
27 | |
28 | void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo, |
29 | clang::FunctionTypeLoc &Block, |
30 | clang::FunctionProtoTypeLoc &BlockProto) { |
31 | if (!TSInfo) |
32 | return; |
33 | |
34 | clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc(); |
35 | while (true) { |
36 | // Look through qualified types |
37 | if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) { |
38 | TL = QualifiedTL.getUnqualifiedLoc(); |
39 | continue; |
40 | } |
41 | |
42 | if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) { |
43 | TL = AttrTL.getModifiedLoc(); |
44 | continue; |
45 | } |
46 | |
47 | // Try to get the function prototype behind the block pointer type, |
48 | // then we're done. |
49 | if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) { |
50 | TL = BlockPtr.getPointeeLoc().IgnoreParens(); |
51 | Block = TL.getAs<clang::FunctionTypeLoc>(); |
52 | BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>(); |
53 | } |
54 | break; |
55 | } |
56 | } |
57 | |
58 | } // namespace |
59 | |
60 | DeclarationFragments & |
61 | DeclarationFragments::(char Character) { |
62 | if (!Fragments.empty()) { |
63 | Fragment &Last = Fragments.back(); |
64 | if (Last.Kind == FragmentKind::Text) { |
65 | // Merge the extra space into the last fragment if the last fragment is |
66 | // also text. |
67 | if (Last.Spelling.back() != Character) { // avoid duplicates at end |
68 | Last.Spelling.push_back(c: Character); |
69 | } |
70 | } else { |
71 | append(Spelling: "" , Kind: FragmentKind::Text); |
72 | Fragments.back().Spelling.push_back(c: Character); |
73 | } |
74 | } |
75 | |
76 | return *this; |
77 | } |
78 | |
79 | DeclarationFragments &DeclarationFragments::() { |
80 | return appendUnduplicatedTextCharacter(Character: ' '); |
81 | } |
82 | |
83 | DeclarationFragments &DeclarationFragments::() { |
84 | return appendUnduplicatedTextCharacter(Character: ';'); |
85 | } |
86 | |
87 | DeclarationFragments &DeclarationFragments::() { |
88 | if (Fragments.empty()) |
89 | return *this; |
90 | |
91 | Fragment &Last = Fragments.back(); |
92 | if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';') |
93 | Last.Spelling.pop_back(); |
94 | |
95 | return *this; |
96 | } |
97 | |
98 | StringRef DeclarationFragments::( |
99 | DeclarationFragments::FragmentKind Kind) { |
100 | switch (Kind) { |
101 | case DeclarationFragments::FragmentKind::None: |
102 | return "none" ; |
103 | case DeclarationFragments::FragmentKind::Keyword: |
104 | return "keyword" ; |
105 | case DeclarationFragments::FragmentKind::Attribute: |
106 | return "attribute" ; |
107 | case DeclarationFragments::FragmentKind::NumberLiteral: |
108 | return "number" ; |
109 | case DeclarationFragments::FragmentKind::StringLiteral: |
110 | return "string" ; |
111 | case DeclarationFragments::FragmentKind::Identifier: |
112 | return "identifier" ; |
113 | case DeclarationFragments::FragmentKind::TypeIdentifier: |
114 | return "typeIdentifier" ; |
115 | case DeclarationFragments::FragmentKind::GenericParameter: |
116 | return "genericParameter" ; |
117 | case DeclarationFragments::FragmentKind::ExternalParam: |
118 | return "externalParam" ; |
119 | case DeclarationFragments::FragmentKind::InternalParam: |
120 | return "internalParam" ; |
121 | case DeclarationFragments::FragmentKind::Text: |
122 | return "text" ; |
123 | } |
124 | |
125 | llvm_unreachable("Unhandled FragmentKind" ); |
126 | } |
127 | |
128 | DeclarationFragments::FragmentKind |
129 | DeclarationFragments::(StringRef S) { |
130 | return llvm::StringSwitch<FragmentKind>(S) |
131 | .Case(S: "keyword" , Value: DeclarationFragments::FragmentKind::Keyword) |
132 | .Case(S: "attribute" , Value: DeclarationFragments::FragmentKind::Attribute) |
133 | .Case(S: "number" , Value: DeclarationFragments::FragmentKind::NumberLiteral) |
134 | .Case(S: "string" , Value: DeclarationFragments::FragmentKind::StringLiteral) |
135 | .Case(S: "identifier" , Value: DeclarationFragments::FragmentKind::Identifier) |
136 | .Case(S: "typeIdentifier" , |
137 | Value: DeclarationFragments::FragmentKind::TypeIdentifier) |
138 | .Case(S: "genericParameter" , |
139 | Value: DeclarationFragments::FragmentKind::GenericParameter) |
140 | .Case(S: "internalParam" , Value: DeclarationFragments::FragmentKind::InternalParam) |
141 | .Case(S: "externalParam" , Value: DeclarationFragments::FragmentKind::ExternalParam) |
142 | .Case(S: "text" , Value: DeclarationFragments::FragmentKind::Text) |
143 | .Default(Value: DeclarationFragments::FragmentKind::None); |
144 | } |
145 | |
146 | DeclarationFragments DeclarationFragments::( |
147 | ExceptionSpecificationType ExceptionSpec) { |
148 | DeclarationFragments Fragments; |
149 | switch (ExceptionSpec) { |
150 | case ExceptionSpecificationType::EST_None: |
151 | return Fragments; |
152 | case ExceptionSpecificationType::EST_DynamicNone: |
153 | return Fragments.append(Spelling: " " , Kind: DeclarationFragments::FragmentKind::Text) |
154 | .append(Spelling: "throw" , Kind: DeclarationFragments::FragmentKind::Keyword) |
155 | .append(Spelling: "(" , Kind: DeclarationFragments::FragmentKind::Text) |
156 | .append(Spelling: ")" , Kind: DeclarationFragments::FragmentKind::Text); |
157 | case ExceptionSpecificationType::EST_Dynamic: |
158 | // FIXME: throw(int), get types of inner expression |
159 | return Fragments; |
160 | case ExceptionSpecificationType::EST_BasicNoexcept: |
161 | return Fragments.append(Spelling: " " , Kind: DeclarationFragments::FragmentKind::Text) |
162 | .append(Spelling: "noexcept" , Kind: DeclarationFragments::FragmentKind::Keyword); |
163 | case ExceptionSpecificationType::EST_DependentNoexcept: |
164 | // FIXME: throw(conditional-expression), get expression |
165 | break; |
166 | case ExceptionSpecificationType::EST_NoexceptFalse: |
167 | return Fragments.append(Spelling: " " , Kind: DeclarationFragments::FragmentKind::Text) |
168 | .append(Spelling: "noexcept" , Kind: DeclarationFragments::FragmentKind::Keyword) |
169 | .append(Spelling: "(" , Kind: DeclarationFragments::FragmentKind::Text) |
170 | .append(Spelling: "false" , Kind: DeclarationFragments::FragmentKind::Keyword) |
171 | .append(Spelling: ")" , Kind: DeclarationFragments::FragmentKind::Text); |
172 | case ExceptionSpecificationType::EST_NoexceptTrue: |
173 | return Fragments.append(Spelling: " " , Kind: DeclarationFragments::FragmentKind::Text) |
174 | .append(Spelling: "noexcept" , Kind: DeclarationFragments::FragmentKind::Keyword) |
175 | .append(Spelling: "(" , Kind: DeclarationFragments::FragmentKind::Text) |
176 | .append(Spelling: "true" , Kind: DeclarationFragments::FragmentKind::Keyword) |
177 | .append(Spelling: ")" , Kind: DeclarationFragments::FragmentKind::Text); |
178 | default: |
179 | return Fragments; |
180 | } |
181 | |
182 | llvm_unreachable("Unhandled exception specification" ); |
183 | } |
184 | |
185 | DeclarationFragments |
186 | DeclarationFragments::(const RecordDecl *Record) { |
187 | DeclarationFragments Fragments; |
188 | if (Record->isStruct()) |
189 | Fragments.append(Spelling: "struct" , Kind: DeclarationFragments::FragmentKind::Keyword); |
190 | else if (Record->isUnion()) |
191 | Fragments.append(Spelling: "union" , Kind: DeclarationFragments::FragmentKind::Keyword); |
192 | else |
193 | Fragments.append(Spelling: "class" , Kind: DeclarationFragments::FragmentKind::Keyword); |
194 | |
195 | return Fragments; |
196 | } |
197 | |
198 | // NNS stores C++ nested name specifiers, which are prefixes to qualified names. |
199 | // Build declaration fragments for NNS recursively so that we have the USR for |
200 | // every part in a qualified name, and also leaves the actual underlying type |
201 | // cleaner for its own fragment. |
202 | DeclarationFragments |
203 | DeclarationFragmentsBuilder::(const NestedNameSpecifier *NNS, |
204 | ASTContext &Context, |
205 | DeclarationFragments &After) { |
206 | DeclarationFragments Fragments; |
207 | if (NNS->getPrefix()) |
208 | Fragments.append(Other: getFragmentsForNNS(NNS: NNS->getPrefix(), Context, After)); |
209 | |
210 | switch (NNS->getKind()) { |
211 | case NestedNameSpecifier::Identifier: |
212 | Fragments.append(Spelling: NNS->getAsIdentifier()->getName(), |
213 | Kind: DeclarationFragments::FragmentKind::Identifier); |
214 | break; |
215 | |
216 | case NestedNameSpecifier::Namespace: { |
217 | const NamespaceDecl *NS = NNS->getAsNamespace(); |
218 | if (NS->isAnonymousNamespace()) |
219 | return Fragments; |
220 | SmallString<128> USR; |
221 | index::generateUSRForDecl(NS, USR); |
222 | Fragments.append(NS->getName(), |
223 | DeclarationFragments::FragmentKind::Identifier, USR, NS); |
224 | break; |
225 | } |
226 | |
227 | case NestedNameSpecifier::NamespaceAlias: { |
228 | const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias(); |
229 | SmallString<128> USR; |
230 | index::generateUSRForDecl(Alias, USR); |
231 | Fragments.append(Alias->getName(), |
232 | DeclarationFragments::FragmentKind::Identifier, USR, |
233 | Alias); |
234 | break; |
235 | } |
236 | |
237 | case NestedNameSpecifier::Global: |
238 | // The global specifier `::` at the beginning. No stored value. |
239 | break; |
240 | |
241 | case NestedNameSpecifier::Super: |
242 | // Microsoft's `__super` specifier. |
243 | Fragments.append(Spelling: "__super" , Kind: DeclarationFragments::FragmentKind::Keyword); |
244 | break; |
245 | |
246 | case NestedNameSpecifier::TypeSpecWithTemplate: |
247 | // A type prefixed by the `template` keyword. |
248 | Fragments.append(Spelling: "template" , Kind: DeclarationFragments::FragmentKind::Keyword); |
249 | Fragments.appendSpace(); |
250 | // Fallthrough after adding the keyword to handle the actual type. |
251 | [[fallthrough]]; |
252 | |
253 | case NestedNameSpecifier::TypeSpec: { |
254 | const Type *T = NNS->getAsType(); |
255 | // FIXME: Handle C++ template specialization type |
256 | Fragments.append(Other: getFragmentsForType(T, Context, After)); |
257 | break; |
258 | } |
259 | } |
260 | |
261 | // Add the separator text `::` for this segment. |
262 | return Fragments.append(Spelling: "::" , Kind: DeclarationFragments::FragmentKind::Text); |
263 | } |
264 | |
265 | // Recursively build the declaration fragments for an underlying `Type` with |
266 | // qualifiers removed. |
267 | DeclarationFragments DeclarationFragmentsBuilder::( |
268 | const Type *T, ASTContext &Context, DeclarationFragments &After) { |
269 | assert(T && "invalid type" ); |
270 | |
271 | DeclarationFragments Fragments; |
272 | |
273 | // An ElaboratedType is a sugar for types that are referred to using an |
274 | // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a |
275 | // qualified name, e.g., `N::M::type`, or both. |
276 | if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Val: T)) { |
277 | ElaboratedTypeKeyword Keyword = ET->getKeyword(); |
278 | if (Keyword != ElaboratedTypeKeyword::None) { |
279 | Fragments |
280 | .append(Spelling: ElaboratedType::getKeywordName(Keyword), |
281 | Kind: DeclarationFragments::FragmentKind::Keyword) |
282 | .appendSpace(); |
283 | } |
284 | |
285 | if (const NestedNameSpecifier *NNS = ET->getQualifier()) |
286 | Fragments.append(Other: getFragmentsForNNS(NNS, Context, After)); |
287 | |
288 | // After handling the elaborated keyword or qualified name, build |
289 | // declaration fragments for the desugared underlying type. |
290 | return Fragments.append(Other: getFragmentsForType(ET->desugar(), Context, After)); |
291 | } |
292 | |
293 | // If the type is a typedefed type, get the underlying TypedefNameDecl for a |
294 | // direct reference to the typedef instead of the wrapped type. |
295 | |
296 | // 'id' type is a typedef for an ObjCObjectPointerType |
297 | // we treat it as a typedef |
298 | if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(Val: T)) { |
299 | const TypedefNameDecl *Decl = TypedefTy->getDecl(); |
300 | TypedefUnderlyingTypeResolver TypedefResolver(Context); |
301 | std::string USR = TypedefResolver.getUSRForType(Type: QualType(T, 0)); |
302 | |
303 | if (T->isObjCIdType()) { |
304 | return Fragments.append(Decl->getName(), |
305 | DeclarationFragments::FragmentKind::Keyword); |
306 | } |
307 | |
308 | return Fragments.append( |
309 | Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier, |
310 | USR, TypedefResolver.getUnderlyingTypeDecl(Type: QualType(T, 0))); |
311 | } |
312 | |
313 | // Declaration fragments of a pointer type is the declaration fragments of |
314 | // the pointee type followed by a `*`, |
315 | if (T->isPointerType() && !T->isFunctionPointerType()) |
316 | return Fragments |
317 | .append(Other: getFragmentsForType(T->getPointeeType(), Context, After)) |
318 | .append(Spelling: " *" , Kind: DeclarationFragments::FragmentKind::Text); |
319 | |
320 | // For Objective-C `id` and `Class` pointers |
321 | // we do not spell out the `*`. |
322 | if (T->isObjCObjectPointerType() && |
323 | !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) { |
324 | |
325 | Fragments.append(Other: getFragmentsForType(T->getPointeeType(), Context, After)); |
326 | |
327 | // id<protocol> is an qualified id type |
328 | // id<protocol>* is not an qualified id type |
329 | if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) { |
330 | Fragments.append(Spelling: " *" , Kind: DeclarationFragments::FragmentKind::Text); |
331 | } |
332 | |
333 | return Fragments; |
334 | } |
335 | |
336 | // Declaration fragments of a lvalue reference type is the declaration |
337 | // fragments of the underlying type followed by a `&`. |
338 | if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(Val: T)) |
339 | return Fragments |
340 | .append( |
341 | getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After)) |
342 | .append(" &" , DeclarationFragments::FragmentKind::Text); |
343 | |
344 | // Declaration fragments of a rvalue reference type is the declaration |
345 | // fragments of the underlying type followed by a `&&`. |
346 | if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(Val: T)) |
347 | return Fragments |
348 | .append( |
349 | getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After)) |
350 | .append(" &&" , DeclarationFragments::FragmentKind::Text); |
351 | |
352 | // Declaration fragments of an array-typed variable have two parts: |
353 | // 1. the element type of the array that appears before the variable name; |
354 | // 2. array brackets `[(0-9)?]` that appear after the variable name. |
355 | if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) { |
356 | // Build the "after" part first because the inner element type might also |
357 | // be an array-type. For example `int matrix[3][4]` which has a type of |
358 | // "(array 3 of (array 4 of ints))." |
359 | // Push the array size part first to make sure they are in the right order. |
360 | After.append(Spelling: "[" , Kind: DeclarationFragments::FragmentKind::Text); |
361 | |
362 | switch (AT->getSizeModifier()) { |
363 | case ArraySizeModifier::Normal: |
364 | break; |
365 | case ArraySizeModifier::Static: |
366 | Fragments.append(Spelling: "static" , Kind: DeclarationFragments::FragmentKind::Keyword); |
367 | break; |
368 | case ArraySizeModifier::Star: |
369 | Fragments.append(Spelling: "*" , Kind: DeclarationFragments::FragmentKind::Text); |
370 | break; |
371 | } |
372 | |
373 | if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Val: AT)) { |
374 | // FIXME: right now this would evaluate any expressions/macros written in |
375 | // the original source to concrete values. For example |
376 | // `int nums[MAX]` -> `int nums[100]` |
377 | // `char *str[5 + 1]` -> `char *str[6]` |
378 | SmallString<128> Size; |
379 | CAT->getSize().toStringUnsigned(Str&: Size); |
380 | After.append(Spelling: Size, Kind: DeclarationFragments::FragmentKind::NumberLiteral); |
381 | } |
382 | |
383 | After.append(Spelling: "]" , Kind: DeclarationFragments::FragmentKind::Text); |
384 | |
385 | return Fragments.append( |
386 | Other: getFragmentsForType(AT->getElementType(), Context, After)); |
387 | } |
388 | |
389 | // Everything we care about has been handled now, reduce to the canonical |
390 | // unqualified base type. |
391 | QualType Base = T->getCanonicalTypeUnqualified(); |
392 | |
393 | // If the base type is a TagType (struct/interface/union/class/enum), let's |
394 | // get the underlying Decl for better names and USRs. |
395 | if (const TagType *TagTy = dyn_cast<TagType>(Val&: Base)) { |
396 | const TagDecl *Decl = TagTy->getDecl(); |
397 | // Anonymous decl, skip this fragment. |
398 | if (Decl->getName().empty()) |
399 | return Fragments.append(Spelling: "{ ... }" , |
400 | Kind: DeclarationFragments::FragmentKind::Text); |
401 | SmallString<128> TagUSR; |
402 | clang::index::generateUSRForDecl(Decl, TagUSR); |
403 | return Fragments.append(Decl->getName(), |
404 | DeclarationFragments::FragmentKind::TypeIdentifier, |
405 | TagUSR, Decl); |
406 | } |
407 | |
408 | // If the base type is an ObjCInterfaceType, use the underlying |
409 | // ObjCInterfaceDecl for the true USR. |
410 | if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) { |
411 | const auto *Decl = ObjCIT->getDecl(); |
412 | SmallString<128> USR; |
413 | index::generateUSRForDecl(D: Decl, Buf&: USR); |
414 | return Fragments.append(Decl->getName(), |
415 | DeclarationFragments::FragmentKind::TypeIdentifier, |
416 | USR, Decl); |
417 | } |
418 | |
419 | // Default fragment builder for other kinds of types (BuiltinType etc.) |
420 | SmallString<128> USR; |
421 | clang::index::generateUSRForType(T: Base, Ctx&: Context, Buf&: USR); |
422 | Fragments.append(Spelling: Base.getAsString(), |
423 | Kind: DeclarationFragments::FragmentKind::TypeIdentifier, PreciseIdentifier: USR); |
424 | |
425 | return Fragments; |
426 | } |
427 | |
428 | DeclarationFragments |
429 | DeclarationFragmentsBuilder::(const Qualifiers Quals) { |
430 | DeclarationFragments Fragments; |
431 | if (Quals.hasConst()) |
432 | Fragments.append(Spelling: "const" , Kind: DeclarationFragments::FragmentKind::Keyword); |
433 | if (Quals.hasVolatile()) |
434 | Fragments.append(Spelling: "volatile" , Kind: DeclarationFragments::FragmentKind::Keyword); |
435 | if (Quals.hasRestrict()) |
436 | Fragments.append(Spelling: "restrict" , Kind: DeclarationFragments::FragmentKind::Keyword); |
437 | |
438 | return Fragments; |
439 | } |
440 | |
441 | DeclarationFragments DeclarationFragmentsBuilder::( |
442 | const QualType QT, ASTContext &Context, DeclarationFragments &After) { |
443 | assert(!QT.isNull() && "invalid type" ); |
444 | |
445 | if (const ParenType *PT = dyn_cast<ParenType>(Val: QT)) { |
446 | After.append(Spelling: ")" , Kind: DeclarationFragments::FragmentKind::Text); |
447 | return getFragmentsForType(QT: PT->getInnerType(), Context, After) |
448 | .append(Spelling: "(" , Kind: DeclarationFragments::FragmentKind::Text); |
449 | } |
450 | |
451 | const SplitQualType SQT = QT.split(); |
452 | DeclarationFragments QualsFragments = getFragmentsForQualifiers(Quals: SQT.Quals), |
453 | TypeFragments = |
454 | getFragmentsForType(T: SQT.Ty, Context, After); |
455 | if (QT.getAsString() == "_Bool" ) |
456 | TypeFragments.replace(NewSpelling: "bool" , Position: 0); |
457 | |
458 | if (QualsFragments.getFragments().empty()) |
459 | return TypeFragments; |
460 | |
461 | // Use east qualifier for pointer types |
462 | // For example: |
463 | // ``` |
464 | // int * const |
465 | // ^---- ^---- |
466 | // type qualifier |
467 | // ^----------------- |
468 | // const pointer to int |
469 | // ``` |
470 | // should not be reconstructed as |
471 | // ``` |
472 | // const int * |
473 | // ^---- ^-- |
474 | // qualifier type |
475 | // ^---------------- ^ |
476 | // pointer to const int |
477 | // ``` |
478 | if (SQT.Ty->isAnyPointerType()) |
479 | return TypeFragments.appendSpace().append(Other: std::move(QualsFragments)); |
480 | |
481 | return QualsFragments.appendSpace().append(Other: std::move(TypeFragments)); |
482 | } |
483 | |
484 | DeclarationFragments DeclarationFragmentsBuilder::( |
485 | const NamespaceDecl *Decl) { |
486 | DeclarationFragments Fragments; |
487 | Fragments.append(Spelling: "namespace" , Kind: DeclarationFragments::FragmentKind::Keyword); |
488 | if (!Decl->isAnonymousNamespace()) |
489 | Fragments.appendSpace().append( |
490 | Decl->getName(), DeclarationFragments::FragmentKind::Identifier); |
491 | return Fragments.appendSemicolon(); |
492 | } |
493 | |
494 | DeclarationFragments |
495 | DeclarationFragmentsBuilder::(const VarDecl *Var) { |
496 | DeclarationFragments Fragments; |
497 | if (Var->isConstexpr()) |
498 | Fragments.append(Spelling: "constexpr" , Kind: DeclarationFragments::FragmentKind::Keyword) |
499 | .appendSpace(); |
500 | |
501 | StorageClass SC = Var->getStorageClass(); |
502 | if (SC != SC_None) |
503 | Fragments |
504 | .append(Spelling: VarDecl::getStorageClassSpecifierString(SC), |
505 | Kind: DeclarationFragments::FragmentKind::Keyword) |
506 | .appendSpace(); |
507 | |
508 | // Capture potential fragments that needs to be placed after the variable name |
509 | // ``` |
510 | // int nums[5]; |
511 | // char (*ptr_to_array)[6]; |
512 | // ``` |
513 | DeclarationFragments After; |
514 | FunctionTypeLoc BlockLoc; |
515 | FunctionProtoTypeLoc BlockProtoLoc; |
516 | findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc); |
517 | |
518 | if (!BlockLoc) { |
519 | QualType T = Var->getTypeSourceInfo() |
520 | ? Var->getTypeSourceInfo()->getType() |
521 | : Var->getASTContext().getUnqualifiedObjCPointerType( |
522 | Var->getType()); |
523 | |
524 | Fragments.append(getFragmentsForType(T, Var->getASTContext(), After)) |
525 | .appendSpace(); |
526 | } else { |
527 | Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After)); |
528 | } |
529 | |
530 | return Fragments |
531 | .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) |
532 | .append(std::move(After)) |
533 | .appendSemicolon(); |
534 | } |
535 | |
536 | DeclarationFragments |
537 | DeclarationFragmentsBuilder::(const VarDecl *Var) { |
538 | DeclarationFragments Fragments; |
539 | if (Var->isConstexpr()) |
540 | Fragments.append(Spelling: "constexpr" , Kind: DeclarationFragments::FragmentKind::Keyword) |
541 | .appendSpace(); |
542 | QualType T = |
543 | Var->getTypeSourceInfo() |
544 | ? Var->getTypeSourceInfo()->getType() |
545 | : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); |
546 | |
547 | // Might be a member, so might be static. |
548 | if (Var->isStaticDataMember()) |
549 | Fragments.append(Spelling: "static" , Kind: DeclarationFragments::FragmentKind::Keyword) |
550 | .appendSpace(); |
551 | |
552 | DeclarationFragments After; |
553 | DeclarationFragments ArgumentFragment = |
554 | getFragmentsForType(T, Var->getASTContext(), After); |
555 | if (StringRef(ArgumentFragment.begin()->Spelling) |
556 | .starts_with(Prefix: "type-parameter" )) { |
557 | std::string ProperArgName = T.getAsString(); |
558 | ArgumentFragment.begin()->Spelling.swap(s&: ProperArgName); |
559 | } |
560 | Fragments.append(Other: std::move(ArgumentFragment)) |
561 | .appendSpace() |
562 | .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) |
563 | .appendSemicolon(); |
564 | return Fragments; |
565 | } |
566 | |
567 | DeclarationFragments |
568 | DeclarationFragmentsBuilder::(const ParmVarDecl *Param) { |
569 | DeclarationFragments Fragments, After; |
570 | |
571 | auto *TSInfo = Param->getTypeSourceInfo(); |
572 | |
573 | QualType T = TSInfo ? TSInfo->getType() |
574 | : Param->getASTContext().getUnqualifiedObjCPointerType( |
575 | Param->getType()); |
576 | |
577 | FunctionTypeLoc BlockLoc; |
578 | FunctionProtoTypeLoc BlockProtoLoc; |
579 | findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc); |
580 | |
581 | DeclarationFragments TypeFragments; |
582 | if (BlockLoc) |
583 | TypeFragments.append( |
584 | getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After)); |
585 | else |
586 | TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After)); |
587 | |
588 | if (StringRef(TypeFragments.begin()->Spelling) |
589 | .starts_with(Prefix: "type-parameter" )) { |
590 | std::string ProperArgName = Param->getOriginalType().getAsString(); |
591 | TypeFragments.begin()->Spelling.swap(s&: ProperArgName); |
592 | } |
593 | |
594 | if (Param->isObjCMethodParameter()) { |
595 | Fragments.append(Spelling: "(" , Kind: DeclarationFragments::FragmentKind::Text) |
596 | .append(Other: std::move(TypeFragments)) |
597 | .append(Other: std::move(After)) |
598 | .append(Spelling: ") " , Kind: DeclarationFragments::FragmentKind::Text) |
599 | .append(Param->getName(), |
600 | DeclarationFragments::FragmentKind::InternalParam); |
601 | } else { |
602 | Fragments.append(Other: std::move(TypeFragments)); |
603 | if (!T->isBlockPointerType()) |
604 | Fragments.appendSpace(); |
605 | Fragments |
606 | .append(Param->getName(), |
607 | DeclarationFragments::FragmentKind::InternalParam) |
608 | .append(std::move(After)); |
609 | } |
610 | return Fragments; |
611 | } |
612 | |
613 | DeclarationFragments DeclarationFragmentsBuilder::( |
614 | const NamedDecl *BlockDecl, FunctionTypeLoc &Block, |
615 | FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) { |
616 | DeclarationFragments Fragments; |
617 | |
618 | DeclarationFragments RetTyAfter; |
619 | auto ReturnValueFragment = getFragmentsForType( |
620 | Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After); |
621 | |
622 | Fragments.append(std::move(ReturnValueFragment)) |
623 | .append(std::move(RetTyAfter)) |
624 | .appendSpace() |
625 | .append("(^" , DeclarationFragments::FragmentKind::Text); |
626 | |
627 | After.append(Spelling: ")" , Kind: DeclarationFragments::FragmentKind::Text); |
628 | unsigned NumParams = Block.getNumParams(); |
629 | |
630 | if (!BlockProto || NumParams == 0) { |
631 | if (BlockProto && BlockProto.getTypePtr()->isVariadic()) |
632 | After.append(Spelling: "(...)" , Kind: DeclarationFragments::FragmentKind::Text); |
633 | else |
634 | After.append(Spelling: "()" , Kind: DeclarationFragments::FragmentKind::Text); |
635 | } else { |
636 | After.append(Spelling: "(" , Kind: DeclarationFragments::FragmentKind::Text); |
637 | for (unsigned I = 0; I != NumParams; ++I) { |
638 | if (I) |
639 | After.append(Spelling: ", " , Kind: DeclarationFragments::FragmentKind::Text); |
640 | After.append(Other: getFragmentsForParam(Param: Block.getParam(i: I))); |
641 | if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic()) |
642 | After.append(Spelling: ", ..." , Kind: DeclarationFragments::FragmentKind::Text); |
643 | } |
644 | After.append(Spelling: ")" , Kind: DeclarationFragments::FragmentKind::Text); |
645 | } |
646 | |
647 | return Fragments; |
648 | } |
649 | |
650 | DeclarationFragments |
651 | DeclarationFragmentsBuilder::(const FunctionDecl *Func) { |
652 | DeclarationFragments Fragments; |
653 | // FIXME: Handle template specialization |
654 | switch (Func->getStorageClass()) { |
655 | case SC_None: |
656 | case SC_PrivateExtern: |
657 | break; |
658 | case SC_Extern: |
659 | Fragments.append(Spelling: "extern" , Kind: DeclarationFragments::FragmentKind::Keyword) |
660 | .appendSpace(); |
661 | break; |
662 | case SC_Static: |
663 | Fragments.append(Spelling: "static" , Kind: DeclarationFragments::FragmentKind::Keyword) |
664 | .appendSpace(); |
665 | break; |
666 | case SC_Auto: |
667 | case SC_Register: |
668 | llvm_unreachable("invalid for functions" ); |
669 | } |
670 | if (Func->isConsteval()) // if consteval, it is also constexpr |
671 | Fragments.append(Spelling: "consteval" , Kind: DeclarationFragments::FragmentKind::Keyword) |
672 | .appendSpace(); |
673 | else if (Func->isConstexpr()) |
674 | Fragments.append(Spelling: "constexpr" , Kind: DeclarationFragments::FragmentKind::Keyword) |
675 | .appendSpace(); |
676 | |
677 | // FIXME: Is `after` actually needed here? |
678 | DeclarationFragments After; |
679 | auto ReturnValueFragment = |
680 | getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After); |
681 | if (StringRef(ReturnValueFragment.begin()->Spelling) |
682 | .starts_with(Prefix: "type-parameter" )) { |
683 | std::string ProperArgName = Func->getReturnType().getAsString(); |
684 | ReturnValueFragment.begin()->Spelling.swap(ProperArgName); |
685 | } |
686 | |
687 | Fragments.append(std::move(ReturnValueFragment)) |
688 | .appendSpace() |
689 | .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier); |
690 | |
691 | if (Func->getTemplateSpecializationInfo()) { |
692 | Fragments.append(Spelling: "<" , Kind: DeclarationFragments::FragmentKind::Text); |
693 | |
694 | for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) { |
695 | if (i) |
696 | Fragments.append(Spelling: ", " , Kind: DeclarationFragments::FragmentKind::Text); |
697 | Fragments.append( |
698 | getFragmentsForType(Func->getParamDecl(i)->getType(), |
699 | Func->getParamDecl(i)->getASTContext(), After)); |
700 | } |
701 | Fragments.append(Spelling: ">" , Kind: DeclarationFragments::FragmentKind::Text); |
702 | } |
703 | Fragments.append(Other: std::move(After)); |
704 | |
705 | Fragments.append(Spelling: "(" , Kind: DeclarationFragments::FragmentKind::Text); |
706 | unsigned NumParams = Func->getNumParams(); |
707 | for (unsigned i = 0; i != NumParams; ++i) { |
708 | if (i) |
709 | Fragments.append(Spelling: ", " , Kind: DeclarationFragments::FragmentKind::Text); |
710 | Fragments.append(Other: getFragmentsForParam(Param: Func->getParamDecl(i))); |
711 | } |
712 | |
713 | if (Func->isVariadic()) { |
714 | if (NumParams > 0) |
715 | Fragments.append(Spelling: ", " , Kind: DeclarationFragments::FragmentKind::Text); |
716 | Fragments.append(Spelling: "..." , Kind: DeclarationFragments::FragmentKind::Text); |
717 | } |
718 | Fragments.append(Spelling: ")" , Kind: DeclarationFragments::FragmentKind::Text); |
719 | |
720 | Fragments.append(Other: DeclarationFragments::getExceptionSpecificationString( |
721 | ExceptionSpec: Func->getExceptionSpecType())); |
722 | |
723 | return Fragments.appendSemicolon(); |
724 | } |
725 | |
726 | DeclarationFragments DeclarationFragmentsBuilder::( |
727 | const EnumConstantDecl *EnumConstDecl) { |
728 | DeclarationFragments Fragments; |
729 | return Fragments.append(EnumConstDecl->getName(), |
730 | DeclarationFragments::FragmentKind::Identifier); |
731 | } |
732 | |
733 | DeclarationFragments |
734 | DeclarationFragmentsBuilder::(const EnumDecl *EnumDecl) { |
735 | if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl()) |
736 | return getFragmentsForTypedef(Decl: TypedefNameDecl); |
737 | |
738 | DeclarationFragments Fragments, After; |
739 | Fragments.append(Spelling: "enum" , Kind: DeclarationFragments::FragmentKind::Keyword); |
740 | |
741 | if (!EnumDecl->getName().empty()) |
742 | Fragments.appendSpace().append( |
743 | EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier); |
744 | |
745 | QualType IntegerType = EnumDecl->getIntegerType(); |
746 | if (!IntegerType.isNull()) |
747 | Fragments.appendSpace() |
748 | .append(Spelling: ": " , Kind: DeclarationFragments::FragmentKind::Text) |
749 | .append( |
750 | getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After)) |
751 | .append(std::move(After)); |
752 | |
753 | if (EnumDecl->getName().empty()) |
754 | Fragments.appendSpace().append(Spelling: "{ ... }" , |
755 | Kind: DeclarationFragments::FragmentKind::Text); |
756 | |
757 | return Fragments.appendSemicolon(); |
758 | } |
759 | |
760 | DeclarationFragments |
761 | DeclarationFragmentsBuilder::(const FieldDecl *Field) { |
762 | DeclarationFragments After; |
763 | DeclarationFragments Fragments; |
764 | if (Field->isMutable()) |
765 | Fragments.append(Spelling: "mutable" , Kind: DeclarationFragments::FragmentKind::Keyword) |
766 | .appendSpace(); |
767 | return Fragments |
768 | .append( |
769 | getFragmentsForType(Field->getType(), Field->getASTContext(), After)) |
770 | .appendSpace() |
771 | .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier) |
772 | .append(std::move(After)) |
773 | .appendSemicolon(); |
774 | } |
775 | |
776 | DeclarationFragments DeclarationFragmentsBuilder::( |
777 | const RecordDecl *Record) { |
778 | if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) |
779 | return getFragmentsForTypedef(Decl: TypedefNameDecl); |
780 | |
781 | DeclarationFragments Fragments; |
782 | if (Record->isUnion()) |
783 | Fragments.append(Spelling: "union" , Kind: DeclarationFragments::FragmentKind::Keyword); |
784 | else |
785 | Fragments.append(Spelling: "struct" , Kind: DeclarationFragments::FragmentKind::Keyword); |
786 | |
787 | Fragments.appendSpace(); |
788 | if (!Record->getName().empty()) |
789 | Fragments.append(Record->getName(), |
790 | DeclarationFragments::FragmentKind::Identifier); |
791 | else |
792 | Fragments.append(Spelling: "{ ... }" , Kind: DeclarationFragments::FragmentKind::Text); |
793 | |
794 | return Fragments.appendSemicolon(); |
795 | } |
796 | |
797 | DeclarationFragments DeclarationFragmentsBuilder::( |
798 | const CXXRecordDecl *Record) { |
799 | if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) |
800 | return getFragmentsForTypedef(Decl: TypedefNameDecl); |
801 | |
802 | DeclarationFragments Fragments; |
803 | Fragments.append(DeclarationFragments::getStructureTypeFragment(Record)); |
804 | |
805 | if (!Record->getName().empty()) |
806 | Fragments.appendSpace().append( |
807 | Record->getName(), DeclarationFragments::FragmentKind::Identifier); |
808 | |
809 | return Fragments.appendSemicolon(); |
810 | } |
811 | |
812 | DeclarationFragments |
813 | DeclarationFragmentsBuilder::( |
814 | const CXXMethodDecl *Method) { |
815 | DeclarationFragments Fragments; |
816 | std::string Name; |
817 | if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Val: Method)) { |
818 | Name = Method->getNameAsString(); |
819 | if (Constructor->isExplicit()) |
820 | Fragments.append(Spelling: "explicit" , Kind: DeclarationFragments::FragmentKind::Keyword) |
821 | .appendSpace(); |
822 | } else if (isa<CXXDestructorDecl>(Val: Method)) |
823 | Name = Method->getNameAsString(); |
824 | |
825 | DeclarationFragments After; |
826 | Fragments.append(Spelling: Name, Kind: DeclarationFragments::FragmentKind::Identifier) |
827 | .append(Other: std::move(After)); |
828 | Fragments.append(Spelling: "(" , Kind: DeclarationFragments::FragmentKind::Text); |
829 | for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { |
830 | if (i) |
831 | Fragments.append(Spelling: ", " , Kind: DeclarationFragments::FragmentKind::Text); |
832 | Fragments.append(getFragmentsForParam(Param: Method->getParamDecl(i))); |
833 | } |
834 | Fragments.append(Spelling: ")" , Kind: DeclarationFragments::FragmentKind::Text); |
835 | |
836 | Fragments.append(DeclarationFragments::getExceptionSpecificationString( |
837 | ExceptionSpec: Method->getExceptionSpecType())); |
838 | |
839 | return Fragments.appendSemicolon(); |
840 | } |
841 | |
842 | DeclarationFragments DeclarationFragmentsBuilder::( |
843 | const CXXMethodDecl *Method) { |
844 | DeclarationFragments Fragments; |
845 | StringRef Name = Method->getName(); |
846 | if (Method->isStatic()) |
847 | Fragments.append(Spelling: "static" , Kind: DeclarationFragments::FragmentKind::Keyword) |
848 | .appendSpace(); |
849 | if (Method->isConstexpr()) |
850 | Fragments.append(Spelling: "constexpr" , Kind: DeclarationFragments::FragmentKind::Keyword) |
851 | .appendSpace(); |
852 | if (Method->isVolatile()) |
853 | Fragments.append(Spelling: "volatile" , Kind: DeclarationFragments::FragmentKind::Keyword) |
854 | .appendSpace(); |
855 | |
856 | // Build return type |
857 | DeclarationFragments After; |
858 | Fragments |
859 | .append(getFragmentsForType(Method->getReturnType(), |
860 | Method->getASTContext(), After)) |
861 | .appendSpace() |
862 | .append(Name, DeclarationFragments::FragmentKind::Identifier) |
863 | .append(std::move(After)); |
864 | Fragments.append(Spelling: "(" , Kind: DeclarationFragments::FragmentKind::Text); |
865 | for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { |
866 | if (i) |
867 | Fragments.append(Spelling: ", " , Kind: DeclarationFragments::FragmentKind::Text); |
868 | Fragments.append(getFragmentsForParam(Param: Method->getParamDecl(i))); |
869 | } |
870 | Fragments.append(Spelling: ")" , Kind: DeclarationFragments::FragmentKind::Text); |
871 | |
872 | if (Method->isConst()) |
873 | Fragments.appendSpace().append(Spelling: "const" , |
874 | Kind: DeclarationFragments::FragmentKind::Keyword); |
875 | |
876 | Fragments.append(DeclarationFragments::getExceptionSpecificationString( |
877 | ExceptionSpec: Method->getExceptionSpecType())); |
878 | |
879 | return Fragments.appendSemicolon(); |
880 | } |
881 | |
882 | DeclarationFragments |
883 | DeclarationFragmentsBuilder::( |
884 | const CXXConversionDecl *ConversionFunction) { |
885 | DeclarationFragments Fragments; |
886 | |
887 | if (ConversionFunction->isExplicit()) |
888 | Fragments.append(Spelling: "explicit" , Kind: DeclarationFragments::FragmentKind::Keyword) |
889 | .appendSpace(); |
890 | |
891 | Fragments.append(Spelling: "operator" , Kind: DeclarationFragments::FragmentKind::Keyword) |
892 | .appendSpace(); |
893 | |
894 | Fragments |
895 | .append(Spelling: ConversionFunction->getConversionType().getAsString(), |
896 | Kind: DeclarationFragments::FragmentKind::TypeIdentifier) |
897 | .append(Spelling: "(" , Kind: DeclarationFragments::FragmentKind::Text); |
898 | for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end; |
899 | ++i) { |
900 | if (i) |
901 | Fragments.append(Spelling: ", " , Kind: DeclarationFragments::FragmentKind::Text); |
902 | Fragments.append(getFragmentsForParam(Param: ConversionFunction->getParamDecl(i))); |
903 | } |
904 | Fragments.append(Spelling: ")" , Kind: DeclarationFragments::FragmentKind::Text); |
905 | |
906 | if (ConversionFunction->isConst()) |
907 | Fragments.appendSpace().append(Spelling: "const" , |
908 | Kind: DeclarationFragments::FragmentKind::Keyword); |
909 | |
910 | return Fragments.appendSemicolon(); |
911 | } |
912 | |
913 | DeclarationFragments |
914 | DeclarationFragmentsBuilder::( |
915 | const CXXMethodDecl *Method) { |
916 | DeclarationFragments Fragments; |
917 | |
918 | // Build return type |
919 | DeclarationFragments After; |
920 | Fragments |
921 | .append(getFragmentsForType(Method->getReturnType(), |
922 | Method->getASTContext(), After)) |
923 | .appendSpace() |
924 | .append(Method->getNameAsString(), |
925 | DeclarationFragments::FragmentKind::Identifier) |
926 | .append(std::move(After)); |
927 | Fragments.append(Spelling: "(" , Kind: DeclarationFragments::FragmentKind::Text); |
928 | for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) { |
929 | if (i) |
930 | Fragments.append(Spelling: ", " , Kind: DeclarationFragments::FragmentKind::Text); |
931 | Fragments.append(getFragmentsForParam(Param: Method->getParamDecl(i))); |
932 | } |
933 | Fragments.append(Spelling: ")" , Kind: DeclarationFragments::FragmentKind::Text); |
934 | |
935 | if (Method->isConst()) |
936 | Fragments.appendSpace().append(Spelling: "const" , |
937 | Kind: DeclarationFragments::FragmentKind::Keyword); |
938 | |
939 | Fragments.append(DeclarationFragments::getExceptionSpecificationString( |
940 | ExceptionSpec: Method->getExceptionSpecType())); |
941 | |
942 | return Fragments.appendSemicolon(); |
943 | } |
944 | |
945 | // Get fragments for template parameters, e.g. T in tempalte<typename T> ... |
946 | DeclarationFragments |
947 | DeclarationFragmentsBuilder::( |
948 | ArrayRef<NamedDecl *> ParameterArray) { |
949 | DeclarationFragments Fragments; |
950 | for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) { |
951 | if (i) |
952 | Fragments.append(Spelling: "," , Kind: DeclarationFragments::FragmentKind::Text) |
953 | .appendSpace(); |
954 | |
955 | const auto *TemplateParam = |
956 | dyn_cast<TemplateTypeParmDecl>(Val: ParameterArray[i]); |
957 | if (!TemplateParam) |
958 | continue; |
959 | if (TemplateParam->hasTypeConstraint()) |
960 | Fragments.append(TemplateParam->getTypeConstraint() |
961 | ->getNamedConcept() |
962 | ->getName() |
963 | .str(), |
964 | DeclarationFragments::FragmentKind::TypeIdentifier); |
965 | else if (TemplateParam->wasDeclaredWithTypename()) |
966 | Fragments.append(Spelling: "typename" , Kind: DeclarationFragments::FragmentKind::Keyword); |
967 | else |
968 | Fragments.append(Spelling: "class" , Kind: DeclarationFragments::FragmentKind::Keyword); |
969 | |
970 | if (TemplateParam->isParameterPack()) |
971 | Fragments.append(Spelling: "..." , Kind: DeclarationFragments::FragmentKind::Text); |
972 | |
973 | Fragments.appendSpace().append( |
974 | TemplateParam->getName(), |
975 | DeclarationFragments::FragmentKind::GenericParameter); |
976 | } |
977 | return Fragments; |
978 | } |
979 | |
980 | // Get fragments for template arguments, e.g. int in template<typename T> |
981 | // Foo<int>; |
982 | // |
983 | // Note: TemplateParameters is only necessary if the Decl is a |
984 | // PartialSpecialization, where we need the parameters to deduce the name of the |
985 | // generic arguments. |
986 | DeclarationFragments |
987 | DeclarationFragmentsBuilder::( |
988 | const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context, |
989 | const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs) { |
990 | DeclarationFragments Fragments; |
991 | for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) { |
992 | if (i) |
993 | Fragments.append(Spelling: "," , Kind: DeclarationFragments::FragmentKind::Text) |
994 | .appendSpace(); |
995 | |
996 | std::string Type = TemplateArguments[i].getAsType().getAsString(); |
997 | DeclarationFragments After; |
998 | DeclarationFragments ArgumentFragment = |
999 | getFragmentsForType(QT: TemplateArguments[i].getAsType(), Context, After); |
1000 | |
1001 | if (StringRef(ArgumentFragment.begin()->Spelling) |
1002 | .starts_with(Prefix: "type-parameter" )) { |
1003 | std::string ProperArgName = TemplateArgumentLocs.value()[i] |
1004 | .getTypeSourceInfo() |
1005 | ->getType() |
1006 | .getAsString(); |
1007 | ArgumentFragment.begin()->Spelling.swap(s&: ProperArgName); |
1008 | } |
1009 | Fragments.append(Other: std::move(ArgumentFragment)); |
1010 | |
1011 | if (TemplateArguments[i].isPackExpansion()) |
1012 | Fragments.append(Spelling: "..." , Kind: DeclarationFragments::FragmentKind::Text); |
1013 | } |
1014 | return Fragments; |
1015 | } |
1016 | |
1017 | DeclarationFragments DeclarationFragmentsBuilder::( |
1018 | const ConceptDecl *Concept) { |
1019 | DeclarationFragments Fragments; |
1020 | return Fragments |
1021 | .append(Spelling: "template" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1022 | .append(Spelling: "<" , Kind: DeclarationFragments::FragmentKind::Text) |
1023 | .append(getFragmentsForTemplateParameters( |
1024 | ParameterArray: Concept->getTemplateParameters()->asArray())) |
1025 | .append("> " , DeclarationFragments::FragmentKind::Text) |
1026 | .append("concept" , DeclarationFragments::FragmentKind::Keyword) |
1027 | .appendSpace() |
1028 | .append(Concept->getName().str(), |
1029 | DeclarationFragments::FragmentKind::Identifier) |
1030 | .appendSemicolon(); |
1031 | } |
1032 | |
1033 | DeclarationFragments |
1034 | DeclarationFragmentsBuilder::( |
1035 | const RedeclarableTemplateDecl *RedeclarableTemplate) { |
1036 | DeclarationFragments Fragments; |
1037 | Fragments.append(Spelling: "template" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1038 | .append(Spelling: "<" , Kind: DeclarationFragments::FragmentKind::Text) |
1039 | .append(getFragmentsForTemplateParameters( |
1040 | ParameterArray: RedeclarableTemplate->getTemplateParameters()->asArray())) |
1041 | .append(">" , DeclarationFragments::FragmentKind::Text) |
1042 | .appendSpace(); |
1043 | |
1044 | if (isa<TypeAliasTemplateDecl>(Val: RedeclarableTemplate)) |
1045 | Fragments.appendSpace() |
1046 | .append(Spelling: "using" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1047 | .appendSpace() |
1048 | .append(RedeclarableTemplate->getName(), |
1049 | DeclarationFragments::FragmentKind::Identifier); |
1050 | // the templated records will be resposbible for injecting their templates |
1051 | return Fragments.appendSpace(); |
1052 | } |
1053 | |
1054 | DeclarationFragments |
1055 | DeclarationFragmentsBuilder::( |
1056 | const ClassTemplateSpecializationDecl *Decl) { |
1057 | DeclarationFragments Fragments; |
1058 | return Fragments |
1059 | .append(Spelling: "template" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1060 | .append(Spelling: "<" , Kind: DeclarationFragments::FragmentKind::Text) |
1061 | .append(Spelling: ">" , Kind: DeclarationFragments::FragmentKind::Text) |
1062 | .appendSpace() |
1063 | .append(Other: DeclarationFragmentsBuilder::getFragmentsForCXXClass( |
1064 | Record: cast<CXXRecordDecl>(Val: Decl))) |
1065 | .pop_back() // there is an extra semicolon now |
1066 | .append(Spelling: "<" , Kind: DeclarationFragments::FragmentKind::Text) |
1067 | .append( |
1068 | getFragmentsForTemplateArguments(TemplateArguments: Decl->getTemplateArgs().asArray(), |
1069 | Context&: Decl->getASTContext(), TemplateArgumentLocs: std::nullopt)) |
1070 | .append(">" , DeclarationFragments::FragmentKind::Text) |
1071 | .appendSemicolon(); |
1072 | } |
1073 | |
1074 | DeclarationFragments |
1075 | DeclarationFragmentsBuilder::( |
1076 | const ClassTemplatePartialSpecializationDecl *Decl) { |
1077 | DeclarationFragments Fragments; |
1078 | return Fragments |
1079 | .append(Spelling: "template" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1080 | .append(Spelling: "<" , Kind: DeclarationFragments::FragmentKind::Text) |
1081 | .append(Other: getFragmentsForTemplateParameters( |
1082 | ParameterArray: Decl->getTemplateParameters()->asArray())) |
1083 | .append(Spelling: ">" , Kind: DeclarationFragments::FragmentKind::Text) |
1084 | .appendSpace() |
1085 | .append(Other: DeclarationFragmentsBuilder::getFragmentsForCXXClass( |
1086 | Record: cast<CXXRecordDecl>(Val: Decl))) |
1087 | .pop_back() // there is an extra semicolon now |
1088 | .append(Spelling: "<" , Kind: DeclarationFragments::FragmentKind::Text) |
1089 | .append(getFragmentsForTemplateArguments( |
1090 | TemplateArguments: Decl->getTemplateArgs().asArray(), Context&: Decl->getASTContext(), |
1091 | TemplateArgumentLocs: Decl->getTemplateArgsAsWritten()->arguments())) |
1092 | .append(">" , DeclarationFragments::FragmentKind::Text) |
1093 | .appendSemicolon(); |
1094 | } |
1095 | |
1096 | DeclarationFragments |
1097 | DeclarationFragmentsBuilder::( |
1098 | const VarTemplateSpecializationDecl *Decl) { |
1099 | DeclarationFragments Fragments; |
1100 | return Fragments |
1101 | .append(Spelling: "template" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1102 | .append(Spelling: "<" , Kind: DeclarationFragments::FragmentKind::Text) |
1103 | .append(Spelling: ">" , Kind: DeclarationFragments::FragmentKind::Text) |
1104 | .appendSpace() |
1105 | .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) |
1106 | .pop_back() // there is an extra semicolon now |
1107 | .append("<" , DeclarationFragments::FragmentKind::Text) |
1108 | .append( |
1109 | getFragmentsForTemplateArguments(TemplateArguments: Decl->getTemplateArgs().asArray(), |
1110 | Context&: Decl->getASTContext(), TemplateArgumentLocs: std::nullopt)) |
1111 | .append(">" , DeclarationFragments::FragmentKind::Text) |
1112 | .appendSemicolon(); |
1113 | } |
1114 | |
1115 | DeclarationFragments |
1116 | DeclarationFragmentsBuilder::( |
1117 | const VarTemplatePartialSpecializationDecl *Decl) { |
1118 | DeclarationFragments Fragments; |
1119 | return Fragments |
1120 | .append(Spelling: "template" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1121 | .append(Spelling: "<" , Kind: DeclarationFragments::FragmentKind::Text) |
1122 | // Partial specs may have new params. |
1123 | .append(Other: getFragmentsForTemplateParameters( |
1124 | ParameterArray: Decl->getTemplateParameters()->asArray())) |
1125 | .append(Spelling: ">" , Kind: DeclarationFragments::FragmentKind::Text) |
1126 | .appendSpace() |
1127 | .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) |
1128 | .pop_back() // there is an extra semicolon now |
1129 | .append("<" , DeclarationFragments::FragmentKind::Text) |
1130 | .append(getFragmentsForTemplateArguments( |
1131 | TemplateArguments: Decl->getTemplateArgs().asArray(), Context&: Decl->getASTContext(), |
1132 | TemplateArgumentLocs: Decl->getTemplateArgsAsWritten()->arguments())) |
1133 | .append(">" , DeclarationFragments::FragmentKind::Text) |
1134 | .appendSemicolon(); |
1135 | } |
1136 | |
1137 | DeclarationFragments |
1138 | DeclarationFragmentsBuilder::( |
1139 | const FunctionTemplateDecl *Decl) { |
1140 | DeclarationFragments Fragments; |
1141 | return Fragments |
1142 | .append(Spelling: "template" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1143 | .append(Spelling: "<" , Kind: DeclarationFragments::FragmentKind::Text) |
1144 | // Partial specs may have new params. |
1145 | .append(getFragmentsForTemplateParameters( |
1146 | ParameterArray: Decl->getTemplateParameters()->asArray())) |
1147 | .append(">" , DeclarationFragments::FragmentKind::Text) |
1148 | .appendSpace() |
1149 | .append(DeclarationFragmentsBuilder::getFragmentsForFunction( |
1150 | Func: Decl->getAsFunction())); |
1151 | } |
1152 | |
1153 | DeclarationFragments |
1154 | DeclarationFragmentsBuilder::( |
1155 | const FunctionDecl *Decl) { |
1156 | DeclarationFragments Fragments; |
1157 | return Fragments |
1158 | .append(Spelling: "template" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1159 | .append(Spelling: "<>" , Kind: DeclarationFragments::FragmentKind::Text) |
1160 | .appendSpace() |
1161 | .append(Other: DeclarationFragmentsBuilder::getFragmentsForFunction(Func: Decl)); |
1162 | } |
1163 | |
1164 | DeclarationFragments |
1165 | DeclarationFragmentsBuilder::(StringRef Name, |
1166 | const MacroDirective *MD) { |
1167 | DeclarationFragments Fragments; |
1168 | Fragments.append(Spelling: "#define" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1169 | .appendSpace(); |
1170 | Fragments.append(Spelling: Name, Kind: DeclarationFragments::FragmentKind::Identifier); |
1171 | |
1172 | auto *MI = MD->getMacroInfo(); |
1173 | |
1174 | if (MI->isFunctionLike()) { |
1175 | Fragments.append(Spelling: "(" , Kind: DeclarationFragments::FragmentKind::Text); |
1176 | unsigned numParameters = MI->getNumParams(); |
1177 | if (MI->isC99Varargs()) |
1178 | --numParameters; |
1179 | for (unsigned i = 0; i < numParameters; ++i) { |
1180 | if (i) |
1181 | Fragments.append(Spelling: ", " , Kind: DeclarationFragments::FragmentKind::Text); |
1182 | Fragments.append(Spelling: MI->params()[i]->getName(), |
1183 | Kind: DeclarationFragments::FragmentKind::InternalParam); |
1184 | } |
1185 | if (MI->isVariadic()) { |
1186 | if (numParameters && MI->isC99Varargs()) |
1187 | Fragments.append(Spelling: ", " , Kind: DeclarationFragments::FragmentKind::Text); |
1188 | Fragments.append(Spelling: "..." , Kind: DeclarationFragments::FragmentKind::Text); |
1189 | } |
1190 | Fragments.append(Spelling: ")" , Kind: DeclarationFragments::FragmentKind::Text); |
1191 | } |
1192 | return Fragments; |
1193 | } |
1194 | |
1195 | DeclarationFragments DeclarationFragmentsBuilder::( |
1196 | const ObjCCategoryDecl *Category) { |
1197 | DeclarationFragments Fragments; |
1198 | |
1199 | auto *Interface = Category->getClassInterface(); |
1200 | SmallString<128> InterfaceUSR; |
1201 | index::generateUSRForDecl(Interface, InterfaceUSR); |
1202 | |
1203 | Fragments.append(Spelling: "@interface" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1204 | .appendSpace() |
1205 | .append(Interface->getName(), |
1206 | DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR, |
1207 | Interface) |
1208 | .append(" (" , DeclarationFragments::FragmentKind::Text) |
1209 | .append(Category->getName(), |
1210 | DeclarationFragments::FragmentKind::Identifier) |
1211 | .append(")" , DeclarationFragments::FragmentKind::Text); |
1212 | |
1213 | return Fragments; |
1214 | } |
1215 | |
1216 | DeclarationFragments DeclarationFragmentsBuilder::( |
1217 | const ObjCInterfaceDecl *Interface) { |
1218 | DeclarationFragments Fragments; |
1219 | // Build the base of the Objective-C interface declaration. |
1220 | Fragments.append(Spelling: "@interface" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1221 | .appendSpace() |
1222 | .append(Interface->getName(), |
1223 | DeclarationFragments::FragmentKind::Identifier); |
1224 | |
1225 | // Build the inheritance part of the declaration. |
1226 | if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) { |
1227 | SmallString<128> SuperUSR; |
1228 | index::generateUSRForDecl(SuperClass, SuperUSR); |
1229 | Fragments.append(Spelling: " : " , Kind: DeclarationFragments::FragmentKind::Text) |
1230 | .append(SuperClass->getName(), |
1231 | DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR, |
1232 | SuperClass); |
1233 | } |
1234 | |
1235 | return Fragments; |
1236 | } |
1237 | |
1238 | DeclarationFragments DeclarationFragmentsBuilder::( |
1239 | const ObjCMethodDecl *Method) { |
1240 | DeclarationFragments Fragments, After; |
1241 | // Build the instance/class method indicator. |
1242 | if (Method->isClassMethod()) |
1243 | Fragments.append(Spelling: "+ " , Kind: DeclarationFragments::FragmentKind::Text); |
1244 | else if (Method->isInstanceMethod()) |
1245 | Fragments.append(Spelling: "- " , Kind: DeclarationFragments::FragmentKind::Text); |
1246 | |
1247 | // Build the return type. |
1248 | Fragments.append(Spelling: "(" , Kind: DeclarationFragments::FragmentKind::Text) |
1249 | .append(getFragmentsForType(Method->getReturnType(), |
1250 | Method->getASTContext(), After)) |
1251 | .append(std::move(After)) |
1252 | .append(")" , DeclarationFragments::FragmentKind::Text); |
1253 | |
1254 | // Build the selector part. |
1255 | Selector Selector = Method->getSelector(); |
1256 | if (Selector.getNumArgs() == 0) |
1257 | // For Objective-C methods that don't take arguments, the first (and only) |
1258 | // slot of the selector is the method name. |
1259 | Fragments.appendSpace().append( |
1260 | Spelling: Selector.getNameForSlot(argIndex: 0), |
1261 | Kind: DeclarationFragments::FragmentKind::Identifier); |
1262 | |
1263 | // For Objective-C methods that take arguments, build the selector slots. |
1264 | for (unsigned i = 0, end = Method->param_size(); i != end; ++i) { |
1265 | // Objective-C method selector parts are considered as identifiers instead |
1266 | // of "external parameters" as in Swift. This is because Objective-C method |
1267 | // symbols are referenced with the entire selector, instead of just the |
1268 | // method name in Swift. |
1269 | SmallString<32> ParamID(Selector.getNameForSlot(argIndex: i)); |
1270 | ParamID.append(RHS: ":" ); |
1271 | Fragments.appendSpace().append( |
1272 | Spelling: ParamID, Kind: DeclarationFragments::FragmentKind::Identifier); |
1273 | |
1274 | // Build the internal parameter. |
1275 | const ParmVarDecl *Param = Method->getParamDecl(Idx: i); |
1276 | Fragments.append(Other: getFragmentsForParam(Param)); |
1277 | } |
1278 | |
1279 | return Fragments.appendSemicolon(); |
1280 | } |
1281 | |
1282 | DeclarationFragments DeclarationFragmentsBuilder::( |
1283 | const ObjCPropertyDecl *Property) { |
1284 | DeclarationFragments Fragments, After; |
1285 | |
1286 | // Build the Objective-C property keyword. |
1287 | Fragments.append(Spelling: "@property" , Kind: DeclarationFragments::FragmentKind::Keyword); |
1288 | |
1289 | const auto Attributes = Property->getPropertyAttributesAsWritten(); |
1290 | // Build the attributes if there is any associated with the property. |
1291 | if (Attributes != ObjCPropertyAttribute::kind_noattr) { |
1292 | // No leading comma for the first attribute. |
1293 | bool First = true; |
1294 | Fragments.append(Spelling: " (" , Kind: DeclarationFragments::FragmentKind::Text); |
1295 | // Helper function to render the attribute. |
1296 | auto RenderAttribute = |
1297 | [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling, |
1298 | StringRef Arg = "" , |
1299 | DeclarationFragments::FragmentKind ArgKind = |
1300 | DeclarationFragments::FragmentKind::Identifier) { |
1301 | // Check if the `Kind` attribute is set for this property. |
1302 | if ((Attributes & Kind) && !Spelling.empty()) { |
1303 | // Add a leading comma if this is not the first attribute rendered. |
1304 | if (!First) |
1305 | Fragments.append(Spelling: ", " , Kind: DeclarationFragments::FragmentKind::Text); |
1306 | // Render the spelling of this attribute `Kind` as a keyword. |
1307 | Fragments.append(Spelling, |
1308 | Kind: DeclarationFragments::FragmentKind::Keyword); |
1309 | // If this attribute takes in arguments (e.g. `getter=getterName`), |
1310 | // render the arguments. |
1311 | if (!Arg.empty()) |
1312 | Fragments.append(Spelling: "=" , Kind: DeclarationFragments::FragmentKind::Text) |
1313 | .append(Spelling: Arg, Kind: ArgKind); |
1314 | First = false; |
1315 | } |
1316 | }; |
1317 | |
1318 | // Go through all possible Objective-C property attributes and render set |
1319 | // ones. |
1320 | RenderAttribute(ObjCPropertyAttribute::kind_class, "class" ); |
1321 | RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct" ); |
1322 | RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic" ); |
1323 | RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic" ); |
1324 | RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign" ); |
1325 | RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain" ); |
1326 | RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong" ); |
1327 | RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy" ); |
1328 | RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak" ); |
1329 | RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained, |
1330 | "unsafe_unretained" ); |
1331 | RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite" ); |
1332 | RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly" ); |
1333 | RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter" , |
1334 | Property->getGetterName().getAsString()); |
1335 | RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter" , |
1336 | Property->getSetterName().getAsString()); |
1337 | |
1338 | // Render nullability attributes. |
1339 | if (Attributes & ObjCPropertyAttribute::kind_nullability) { |
1340 | QualType Type = Property->getType(); |
1341 | if (const auto Nullability = |
1342 | AttributedType::stripOuterNullability(T&: Type)) { |
1343 | if (!First) |
1344 | Fragments.append(Spelling: ", " , Kind: DeclarationFragments::FragmentKind::Text); |
1345 | if (*Nullability == NullabilityKind::Unspecified && |
1346 | (Attributes & ObjCPropertyAttribute::kind_null_resettable)) |
1347 | Fragments.append(Spelling: "null_resettable" , |
1348 | Kind: DeclarationFragments::FragmentKind::Keyword); |
1349 | else |
1350 | Fragments.append( |
1351 | Spelling: getNullabilitySpelling(kind: *Nullability, /*isContextSensitive=*/true), |
1352 | Kind: DeclarationFragments::FragmentKind::Keyword); |
1353 | First = false; |
1354 | } |
1355 | } |
1356 | |
1357 | Fragments.append(Spelling: ")" , Kind: DeclarationFragments::FragmentKind::Text); |
1358 | } |
1359 | |
1360 | Fragments.appendSpace(); |
1361 | |
1362 | FunctionTypeLoc BlockLoc; |
1363 | FunctionProtoTypeLoc BlockProtoLoc; |
1364 | findTypeLocForBlockDecl(TSInfo: Property->getTypeSourceInfo(), Block&: BlockLoc, |
1365 | BlockProto&: BlockProtoLoc); |
1366 | |
1367 | auto PropType = Property->getType(); |
1368 | if (!BlockLoc) |
1369 | Fragments |
1370 | .append(getFragmentsForType(PropType, Property->getASTContext(), After)) |
1371 | .appendSpace(); |
1372 | else |
1373 | Fragments.append( |
1374 | getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After)); |
1375 | |
1376 | return Fragments |
1377 | .append(Property->getName(), |
1378 | DeclarationFragments::FragmentKind::Identifier) |
1379 | .append(std::move(After)) |
1380 | .appendSemicolon(); |
1381 | } |
1382 | |
1383 | DeclarationFragments DeclarationFragmentsBuilder::( |
1384 | const ObjCProtocolDecl *Protocol) { |
1385 | DeclarationFragments Fragments; |
1386 | // Build basic protocol declaration. |
1387 | Fragments.append(Spelling: "@protocol" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1388 | .appendSpace() |
1389 | .append(Protocol->getName(), |
1390 | DeclarationFragments::FragmentKind::Identifier); |
1391 | |
1392 | // If this protocol conforms to other protocols, build the conformance list. |
1393 | if (!Protocol->protocols().empty()) { |
1394 | Fragments.append(Spelling: " <" , Kind: DeclarationFragments::FragmentKind::Text); |
1395 | for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin(); |
1396 | It != Protocol->protocol_end(); It++) { |
1397 | // Add a leading comma if this is not the first protocol rendered. |
1398 | if (It != Protocol->protocol_begin()) |
1399 | Fragments.append(Spelling: ", " , Kind: DeclarationFragments::FragmentKind::Text); |
1400 | |
1401 | SmallString<128> USR; |
1402 | index::generateUSRForDecl(*It, USR); |
1403 | Fragments.append((*It)->getName(), |
1404 | DeclarationFragments::FragmentKind::TypeIdentifier, USR, |
1405 | *It); |
1406 | } |
1407 | Fragments.append(Spelling: ">" , Kind: DeclarationFragments::FragmentKind::Text); |
1408 | } |
1409 | |
1410 | return Fragments; |
1411 | } |
1412 | |
1413 | DeclarationFragments DeclarationFragmentsBuilder::( |
1414 | const TypedefNameDecl *Decl) { |
1415 | DeclarationFragments Fragments, After; |
1416 | Fragments.append(Spelling: "typedef" , Kind: DeclarationFragments::FragmentKind::Keyword) |
1417 | .appendSpace() |
1418 | .append(getFragmentsForType(Decl->getUnderlyingType(), |
1419 | Decl->getASTContext(), After)) |
1420 | .append(std::move(After)) |
1421 | .appendSpace() |
1422 | .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); |
1423 | |
1424 | return Fragments.appendSemicolon(); |
1425 | } |
1426 | |
1427 | // Instantiate template for FunctionDecl. |
1428 | template FunctionSignature |
1429 | DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *); |
1430 | |
1431 | // Instantiate template for ObjCMethodDecl. |
1432 | template FunctionSignature |
1433 | DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *); |
1434 | |
1435 | // Subheading of a symbol defaults to its name. |
1436 | DeclarationFragments |
1437 | DeclarationFragmentsBuilder::(const NamedDecl *Decl) { |
1438 | DeclarationFragments Fragments; |
1439 | if (isa<CXXConstructorDecl>(Val: Decl) || isa<CXXDestructorDecl>(Val: Decl)) |
1440 | Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(), |
1441 | DeclarationFragments::FragmentKind::Identifier); |
1442 | else if (isa<CXXConversionDecl>(Val: Decl)) { |
1443 | Fragments.append( |
1444 | Spelling: cast<CXXConversionDecl>(Val: Decl)->getConversionType().getAsString(), |
1445 | Kind: DeclarationFragments::FragmentKind::Identifier); |
1446 | } else if (isa<CXXMethodDecl>(Val: Decl) && |
1447 | cast<CXXMethodDecl>(Val: Decl)->isOverloadedOperator()) { |
1448 | Fragments.append(Spelling: Decl->getNameAsString(), |
1449 | Kind: DeclarationFragments::FragmentKind::Identifier); |
1450 | } else if (!Decl->getName().empty()) |
1451 | Fragments.append(Spelling: Decl->getName(), |
1452 | Kind: DeclarationFragments::FragmentKind::Identifier); |
1453 | return Fragments; |
1454 | } |
1455 | |
1456 | // Subheading of an Objective-C method is a `+` or `-` sign indicating whether |
1457 | // it's a class method or an instance method, followed by the selector name. |
1458 | DeclarationFragments |
1459 | DeclarationFragmentsBuilder::(const ObjCMethodDecl *Method) { |
1460 | DeclarationFragments Fragments; |
1461 | if (Method->isClassMethod()) |
1462 | Fragments.append(Spelling: "+ " , Kind: DeclarationFragments::FragmentKind::Text); |
1463 | else if (Method->isInstanceMethod()) |
1464 | Fragments.append(Spelling: "- " , Kind: DeclarationFragments::FragmentKind::Text); |
1465 | |
1466 | return Fragments.append(Method->getNameAsString(), |
1467 | DeclarationFragments::FragmentKind::Identifier); |
1468 | } |
1469 | |
1470 | // Subheading of a symbol defaults to its name. |
1471 | DeclarationFragments |
1472 | DeclarationFragmentsBuilder::(StringRef Name) { |
1473 | DeclarationFragments Fragments; |
1474 | Fragments.append(Spelling: Name, Kind: DeclarationFragments::FragmentKind::Identifier); |
1475 | return Fragments; |
1476 | } |
1477 | |