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

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