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