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

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