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