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

source code of clang/lib/ExtractAPI/DeclarationFragments.cpp