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