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