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