1 //===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file implements Declaration Fragments related classes.
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"
24 using namespace clang::extractapi
;
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
33 if (Last
.Spelling
.back() != ' ') { // avoid extra trailing spaces.
34 Last
.Spelling
.push_back(' ');
37 append(" ", FragmentKind::Text
);
44 StringRef
DeclarationFragments::getFragmentKindString(
45 DeclarationFragments::FragmentKind Kind
) {
47 case DeclarationFragments::FragmentKind::None
:
49 case DeclarationFragments::FragmentKind::Keyword
:
51 case DeclarationFragments::FragmentKind::Attribute
:
53 case DeclarationFragments::FragmentKind::NumberLiteral
:
55 case DeclarationFragments::FragmentKind::StringLiteral
:
57 case DeclarationFragments::FragmentKind::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
:
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
:
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
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
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
);
128 llvm_unreachable("Unhandled exception specification");
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
);
139 Fragments
.append("class", DeclarationFragments::FragmentKind::Keyword
);
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.
149 DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier
*NNS
,
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
);
162 case NestedNameSpecifier::Namespace
: {
163 const NamespaceDecl
*NS
= NNS
->getAsNamespace();
164 if (NS
->isAnonymousNamespace())
166 SmallString
<128> USR
;
167 index::generateUSRForDecl(NS
, USR
);
168 Fragments
.append(NS
->getName(),
169 DeclarationFragments::FragmentKind::Identifier
, USR
, NS
);
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
,
183 case NestedNameSpecifier::Global
:
184 // The global specifier `::` at the beginning. No stored value.
187 case NestedNameSpecifier::Super
:
188 // Microsoft's `__super` specifier.
189 Fragments
.append("__super", DeclarationFragments::FragmentKind::Keyword
);
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.
199 case NestedNameSpecifier::TypeSpec
: {
200 const Type
*T
= NNS
->getAsType();
201 // FIXME: Handle C++ template specialization type
202 Fragments
.append(getFragmentsForType(T
, Context
, After
));
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())
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
);
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
))
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
))
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
:
271 case ArraySizeModifier::Static
:
272 Fragments
.append("static", DeclarationFragments::FragmentKind::Keyword
);
274 case ArraySizeModifier::Star
:
275 Fragments
.append("*", DeclarationFragments::FragmentKind::Text
);
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
) {
302 .append(ElaboratedType::getKeywordName(Keyword
),
303 DeclarationFragments::FragmentKind::Keyword
)
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())
346 SmallString
<128> TagUSR
;
347 clang::index::generateUSRForDecl(Decl
, TagUSR
);
348 return Fragments
.append(Decl
->getName(),
349 DeclarationFragments::FragmentKind::TypeIdentifier
,
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
,
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
);
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
);
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
),
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
412 // ^-----------------
413 // const pointer to int
415 // should not be reconstructed as
420 // ^---------------- ^
421 // pointer to const int
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
);
440 DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl
*Var
) {
441 DeclarationFragments Fragments
;
442 if (Var
->isConstexpr())
443 Fragments
.append("constexpr", DeclarationFragments::FragmentKind::Keyword
)
446 StorageClass SC
= Var
->getStorageClass();
449 .append(VarDecl::getStorageClassSpecifierString(SC
),
450 DeclarationFragments::FragmentKind::Keyword
)
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
460 // char (*ptr_to_array)[6];
462 DeclarationFragments After
;
463 return Fragments
.append(getFragmentsForType(T
, Var
->getASTContext(), After
))
465 .append(Var
->getName(), DeclarationFragments::FragmentKind::Identifier
)
466 .append(std::move(After
))
467 .append(";", DeclarationFragments::FragmentKind::Text
);
471 DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl
*Var
) {
472 DeclarationFragments Fragments
;
473 if (Var
->isConstexpr())
474 Fragments
.append("constexpr", DeclarationFragments::FragmentKind::Keyword
)
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
)
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
))
498 .append(Var
->getName(), DeclarationFragments::FragmentKind::Identifier
)
499 .append(";", DeclarationFragments::FragmentKind::Text
);
504 DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl
*Param
) {
505 DeclarationFragments Fragments
, After
;
507 QualType T
= Param
->getTypeSourceInfo()
508 ? Param
->getTypeSourceInfo()->getType()
509 : Param
->getASTContext().getUnqualifiedObjCPointerType(
512 DeclarationFragments TypeFragments
=
513 getFragmentsForType(T
, Param
->getASTContext(), After
);
514 if (TypeFragments
.begin()->Spelling
.substr(0, 14).compare("type-parameter") ==
516 std::string ProperArgName
= getNameForTemplateArgument(
517 dyn_cast
<FunctionDecl
>(Param
->getDeclContext())
518 ->getDescribedFunctionTemplate()
519 ->getTemplateParameters()
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
);
530 Fragments
.append(std::move(TypeFragments
)).appendSpace();
533 .append(Param
->getName(),
534 DeclarationFragments::FragmentKind::InternalParam
)
535 .append(std::move(After
));
539 DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl
*Func
) {
540 DeclarationFragments Fragments
;
541 // FIXME: Handle template specialization
542 switch (Func
->getStorageClass()) {
544 case SC_PrivateExtern
:
547 Fragments
.append("extern", DeclarationFragments::FragmentKind::Keyword
)
551 Fragments
.append("static", DeclarationFragments::FragmentKind::Keyword
)
556 llvm_unreachable("invalid for functions");
558 if (Func
->isConsteval()) // if consteval, it is also constexpr
559 Fragments
.append("consteval", DeclarationFragments::FragmentKind::Keyword
)
561 else if (Func
->isConstexpr())
562 Fragments
.append("constexpr", DeclarationFragments::FragmentKind::Keyword
)
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()
575 ReturnValueFragment
.begin()->Spelling
);
576 ReturnValueFragment
.begin()->Spelling
.swap(ProperArgName
);
579 Fragments
.append(std::move(ReturnValueFragment
))
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
) {
588 Fragments
.append(", ", DeclarationFragments::FragmentKind::Text
);
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
) {
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
);
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
)
634 getFragmentsForType(IntegerType
, EnumDecl
->getASTContext(), After
))
635 .append(std::move(After
));
637 return Fragments
.append(";", DeclarationFragments::FragmentKind::Text
);
641 DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl
*Field
) {
642 DeclarationFragments After
;
643 DeclarationFragments Fragments
;
644 if (Field
->isMutable())
645 Fragments
.append("mutable", DeclarationFragments::FragmentKind::Keyword
)
649 getFragmentsForType(Field
->getType(), Field
->getASTContext(), After
))
651 .append(Field
->getName(), DeclarationFragments::FragmentKind::Identifier
)
652 .append(std::move(After
))
653 .append(";", DeclarationFragments::FragmentKind::Text
);
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
);
687 DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
688 const CXXMethodDecl
*Method
) {
689 DeclarationFragments Fragments
;
691 if (const auto *Constructor
= dyn_cast
<CXXConstructorDecl
>(Method
)) {
692 Name
= Method
->getNameAsString();
693 if (Constructor
->isExplicit())
694 Fragments
.append("explicit", DeclarationFragments::FragmentKind::Keyword
)
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
) {
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
)
723 if (Method
->isConstexpr())
724 Fragments
.append("constexpr", DeclarationFragments::FragmentKind::Keyword
)
726 if (Method
->isVolatile())
727 Fragments
.append("volatile", DeclarationFragments::FragmentKind::Keyword
)
731 DeclarationFragments After
;
733 .append(getFragmentsForType(Method
->getReturnType(),
734 Method
->getASTContext(), After
))
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
) {
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
);
757 DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
758 const CXXConversionDecl
*ConversionFunction
) {
759 DeclarationFragments Fragments
;
761 if (ConversionFunction
->isExplicit())
762 Fragments
.append("explicit", DeclarationFragments::FragmentKind::Keyword
)
765 Fragments
.append("operator", DeclarationFragments::FragmentKind::Keyword
)
769 .append(ConversionFunction
->getConversionType().getAsString(),
770 DeclarationFragments::FragmentKind::TypeIdentifier
)
771 .append("(", DeclarationFragments::FragmentKind::Text
);
772 for (unsigned i
= 0, end
= ConversionFunction
->getNumParams(); i
!= end
;
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
);
788 DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
789 const CXXMethodDecl
*Method
) {
790 DeclarationFragments Fragments
;
793 DeclarationFragments After
;
795 .append(getFragmentsForType(Method
->getReturnType(),
796 Method
->getASTContext(), After
))
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
) {
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> ...
821 DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(
822 ArrayRef
<NamedDecl
*> ParameterArray
) {
823 DeclarationFragments Fragments
;
824 for (unsigned i
= 0, end
= ParameterArray
.size(); i
!= end
; ++i
) {
826 Fragments
.append(",", DeclarationFragments::FragmentKind::Text
)
829 const auto *TemplateParam
=
830 dyn_cast
<TemplateTypeParmDecl
>(ParameterArray
[i
]);
833 if (TemplateParam
->hasTypeConstraint())
834 Fragments
.append(TemplateParam
->getTypeConstraint()
838 DeclarationFragments::FragmentKind::TypeIdentifier
);
839 else if (TemplateParam
->wasDeclaredWithTypename())
840 Fragments
.append("typename", DeclarationFragments::FragmentKind::Keyword
);
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
);
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>
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.
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
) {
886 Fragments
.append(",", DeclarationFragments::FragmentKind::Text
)
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
);
908 DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForConcept(
909 const ConceptDecl
*Concept
) {
910 DeclarationFragments 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
)
919 .append(Concept
->getName().str(),
920 DeclarationFragments::FragmentKind::Identifier
)
921 .append(";", DeclarationFragments::FragmentKind::Text
);
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
)
935 if (isa
<TypeAliasTemplateDecl
>(RedeclarableTemplate
))
936 Fragments
.appendSpace()
937 .append("using", DeclarationFragments::FragmentKind::Keyword
)
939 .append(RedeclarableTemplate
->getName(),
940 DeclarationFragments::FragmentKind::Identifier
);
941 // the templated records will be resposbible for injecting their templates
942 return Fragments
.appendSpace();
946 DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
947 const ClassTemplateSpecializationDecl
*Decl
) {
948 DeclarationFragments Fragments
;
950 .append("template", DeclarationFragments::FragmentKind::Keyword
)
951 .append("<", DeclarationFragments::FragmentKind::Text
)
952 .append(">", DeclarationFragments::FragmentKind::Text
)
954 .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
955 cast
<CXXRecordDecl
>(Decl
)))
956 .pop_back() // there is an extra semicolon now
957 .append("<", DeclarationFragments::FragmentKind::Text
)
959 getFragmentsForTemplateArguments(Decl
->getTemplateArgs().asArray(),
960 Decl
->getASTContext(), std::nullopt
))
961 .append(">", DeclarationFragments::FragmentKind::Text
)
962 .append(";", DeclarationFragments::FragmentKind::Text
);
966 DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
967 const ClassTemplatePartialSpecializationDecl
*Decl
) {
968 DeclarationFragments Fragments
;
970 .append("template", DeclarationFragments::FragmentKind::Keyword
)
971 .append("<", DeclarationFragments::FragmentKind::Text
)
972 .append(getFragmentsForTemplateParameters(
973 Decl
->getTemplateParameters()->asArray()))
974 .append(">", DeclarationFragments::FragmentKind::Text
)
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
);
988 DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
989 const VarTemplateSpecializationDecl
*Decl
) {
990 DeclarationFragments Fragments
;
992 .append("template", DeclarationFragments::FragmentKind::Keyword
)
993 .append("<", DeclarationFragments::FragmentKind::Text
)
994 .append(">", DeclarationFragments::FragmentKind::Text
)
996 .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl
))
997 .pop_back() // there is an extra semicolon now
998 .append("<", DeclarationFragments::FragmentKind::Text
)
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
;
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
)
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
;
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
)
1040 .append(DeclarationFragmentsBuilder::getFragmentsForFunction(
1041 Decl
->getAsFunction()));
1044 DeclarationFragments
1045 DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(
1046 const FunctionDecl
*Decl
) {
1047 DeclarationFragments Fragments
;
1049 .append("template", DeclarationFragments::FragmentKind::Keyword
)
1050 .append("<>", DeclarationFragments::FragmentKind::Text
)
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
)
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())
1070 for (unsigned i
= 0; i
< numParameters
; ++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
);
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
)
1096 .append(Category
->getClassInterface()->getName(),
1097 DeclarationFragments::FragmentKind::TypeIdentifier
, InterfaceUSR
,
1099 .append(" (", DeclarationFragments::FragmentKind::Text
)
1100 .append(Category
->getName(),
1101 DeclarationFragments::FragmentKind::Identifier
)
1102 .append(")", DeclarationFragments::FragmentKind::Text
);
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
)
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
,
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.
1185 Fragments
.append(" (", DeclarationFragments::FragmentKind::Text
);
1186 // Helper function to render the attribute.
1187 auto RenderAttribute
=
1188 [&](ObjCPropertyAttribute::Kind Kind
, StringRef Spelling
,
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.
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.
1203 Fragments
.append("=", DeclarationFragments::FragmentKind::Text
)
1204 .append(Arg
, ArgKind
);
1209 // Go through all possible Objective-C property attributes and render set
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
)) {
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
);
1242 getNullabilitySpelling(*Nullability
, /*isContextSensitive=*/true),
1243 DeclarationFragments::FragmentKind::Keyword
);
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
))
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
)
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
,
1285 Fragments
.append(">", DeclarationFragments::FragmentKind::Text
);
1291 DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForTypedef(
1292 const TypedefNameDecl
*Decl
) {
1293 DeclarationFragments Fragments
, After
;
1294 Fragments
.append("typedef", DeclarationFragments::FragmentKind::Keyword
)
1296 .append(getFragmentsForType(Decl
->getUnderlyingType(),
1297 Decl
->getASTContext(), After
))
1298 .append(std::move(After
))
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
)) {
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
);
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
);