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