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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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