xref: /freebsd/contrib/llvm-project/clang/lib/ExtractAPI/DeclarationFragments.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
181ad6265SDimitry Andric //===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric ///
981ad6265SDimitry Andric /// \file
1081ad6265SDimitry Andric /// This file implements Declaration Fragments related classes.
1181ad6265SDimitry Andric ///
1281ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1381ad6265SDimitry Andric 
1481ad6265SDimitry Andric #include "clang/ExtractAPI/DeclarationFragments.h"
15*5f757f3fSDimitry Andric #include "clang/AST/Decl.h"
16*5f757f3fSDimitry Andric #include "clang/AST/DeclCXX.h"
17*5f757f3fSDimitry Andric #include "clang/AST/QualTypeNames.h"
18*5f757f3fSDimitry Andric #include "clang/AST/Type.h"
19*5f757f3fSDimitry Andric #include "clang/AST/TypeLoc.h"
20*5f757f3fSDimitry Andric #include "clang/Basic/OperatorKinds.h"
2106c3fb27SDimitry Andric #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
2281ad6265SDimitry Andric #include "clang/Index/USRGeneration.h"
2381ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h"
24*5f757f3fSDimitry Andric #include <typeinfo>
2581ad6265SDimitry Andric 
2681ad6265SDimitry Andric using namespace clang::extractapi;
2781ad6265SDimitry Andric using namespace llvm;
2881ad6265SDimitry Andric 
29*5f757f3fSDimitry Andric namespace {
30*5f757f3fSDimitry Andric 
31*5f757f3fSDimitry Andric void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
32*5f757f3fSDimitry Andric                              clang::FunctionTypeLoc &Block,
33*5f757f3fSDimitry Andric                              clang::FunctionProtoTypeLoc &BlockProto) {
34*5f757f3fSDimitry Andric   if (!TSInfo)
35*5f757f3fSDimitry Andric     return;
36*5f757f3fSDimitry Andric 
37*5f757f3fSDimitry Andric   clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
38*5f757f3fSDimitry Andric   while (true) {
39*5f757f3fSDimitry Andric     // Look through qualified types
40*5f757f3fSDimitry Andric     if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) {
41*5f757f3fSDimitry Andric       TL = QualifiedTL.getUnqualifiedLoc();
42*5f757f3fSDimitry Andric       continue;
43*5f757f3fSDimitry Andric     }
44*5f757f3fSDimitry Andric 
45*5f757f3fSDimitry Andric     if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) {
46*5f757f3fSDimitry Andric       TL = AttrTL.getModifiedLoc();
47*5f757f3fSDimitry Andric       continue;
48*5f757f3fSDimitry Andric     }
49*5f757f3fSDimitry Andric 
50*5f757f3fSDimitry Andric     // Try to get the function prototype behind the block pointer type,
51*5f757f3fSDimitry Andric     // then we're done.
52*5f757f3fSDimitry Andric     if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) {
53*5f757f3fSDimitry Andric       TL = BlockPtr.getPointeeLoc().IgnoreParens();
54*5f757f3fSDimitry Andric       Block = TL.getAs<clang::FunctionTypeLoc>();
55*5f757f3fSDimitry Andric       BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>();
56*5f757f3fSDimitry Andric     }
57*5f757f3fSDimitry Andric     break;
58*5f757f3fSDimitry Andric   }
59*5f757f3fSDimitry Andric }
60*5f757f3fSDimitry Andric 
61*5f757f3fSDimitry Andric } // namespace
62*5f757f3fSDimitry Andric 
6381ad6265SDimitry Andric DeclarationFragments &DeclarationFragments::appendSpace() {
6481ad6265SDimitry Andric   if (!Fragments.empty()) {
6581ad6265SDimitry Andric     Fragment &Last = Fragments.back();
6681ad6265SDimitry Andric     if (Last.Kind == FragmentKind::Text) {
6781ad6265SDimitry Andric       // Merge the extra space into the last fragment if the last fragment is
6881ad6265SDimitry Andric       // also text.
6981ad6265SDimitry Andric       if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces.
7081ad6265SDimitry Andric         Last.Spelling.push_back(' ');
7181ad6265SDimitry Andric       }
7281ad6265SDimitry Andric     } else {
7381ad6265SDimitry Andric       append(" ", FragmentKind::Text);
7481ad6265SDimitry Andric     }
7581ad6265SDimitry Andric   }
7681ad6265SDimitry Andric 
7781ad6265SDimitry Andric   return *this;
7881ad6265SDimitry Andric }
7981ad6265SDimitry Andric 
8081ad6265SDimitry Andric StringRef DeclarationFragments::getFragmentKindString(
8181ad6265SDimitry Andric     DeclarationFragments::FragmentKind Kind) {
8281ad6265SDimitry Andric   switch (Kind) {
8381ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::None:
8481ad6265SDimitry Andric     return "none";
8581ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Keyword:
8681ad6265SDimitry Andric     return "keyword";
8781ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Attribute:
8881ad6265SDimitry Andric     return "attribute";
8981ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::NumberLiteral:
9081ad6265SDimitry Andric     return "number";
9181ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::StringLiteral:
9281ad6265SDimitry Andric     return "string";
9381ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Identifier:
9481ad6265SDimitry Andric     return "identifier";
9581ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::TypeIdentifier:
9681ad6265SDimitry Andric     return "typeIdentifier";
9781ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::GenericParameter:
9881ad6265SDimitry Andric     return "genericParameter";
9981ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::ExternalParam:
10081ad6265SDimitry Andric     return "externalParam";
10181ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::InternalParam:
10281ad6265SDimitry Andric     return "internalParam";
10381ad6265SDimitry Andric   case DeclarationFragments::FragmentKind::Text:
10481ad6265SDimitry Andric     return "text";
10581ad6265SDimitry Andric   }
10681ad6265SDimitry Andric 
10781ad6265SDimitry Andric   llvm_unreachable("Unhandled FragmentKind");
10881ad6265SDimitry Andric }
10981ad6265SDimitry Andric 
11081ad6265SDimitry Andric DeclarationFragments::FragmentKind
11181ad6265SDimitry Andric DeclarationFragments::parseFragmentKindFromString(StringRef S) {
11281ad6265SDimitry Andric   return llvm::StringSwitch<FragmentKind>(S)
11381ad6265SDimitry Andric       .Case("keyword", DeclarationFragments::FragmentKind::Keyword)
11481ad6265SDimitry Andric       .Case("attribute", DeclarationFragments::FragmentKind::Attribute)
11581ad6265SDimitry Andric       .Case("number", DeclarationFragments::FragmentKind::NumberLiteral)
11681ad6265SDimitry Andric       .Case("string", DeclarationFragments::FragmentKind::StringLiteral)
11781ad6265SDimitry Andric       .Case("identifier", DeclarationFragments::FragmentKind::Identifier)
11881ad6265SDimitry Andric       .Case("typeIdentifier",
11981ad6265SDimitry Andric             DeclarationFragments::FragmentKind::TypeIdentifier)
12081ad6265SDimitry Andric       .Case("genericParameter",
12181ad6265SDimitry Andric             DeclarationFragments::FragmentKind::GenericParameter)
12281ad6265SDimitry Andric       .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam)
12381ad6265SDimitry Andric       .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam)
12481ad6265SDimitry Andric       .Case("text", DeclarationFragments::FragmentKind::Text)
12581ad6265SDimitry Andric       .Default(DeclarationFragments::FragmentKind::None);
12681ad6265SDimitry Andric }
12781ad6265SDimitry Andric 
128*5f757f3fSDimitry Andric DeclarationFragments DeclarationFragments::getExceptionSpecificationString(
129*5f757f3fSDimitry Andric     ExceptionSpecificationType ExceptionSpec) {
130*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
131*5f757f3fSDimitry Andric   switch (ExceptionSpec) {
132*5f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_None:
133*5f757f3fSDimitry Andric     return Fragments;
134*5f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_DynamicNone:
135*5f757f3fSDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
136*5f757f3fSDimitry Andric         .append("throw", DeclarationFragments::FragmentKind::Keyword)
137*5f757f3fSDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text)
138*5f757f3fSDimitry Andric         .append(")", DeclarationFragments::FragmentKind::Text);
139*5f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_Dynamic:
140*5f757f3fSDimitry Andric     // FIXME: throw(int), get types of inner expression
141*5f757f3fSDimitry Andric     return Fragments;
142*5f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_BasicNoexcept:
143*5f757f3fSDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
144*5f757f3fSDimitry Andric         .append("noexcept", DeclarationFragments::FragmentKind::Keyword);
145*5f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_DependentNoexcept:
146*5f757f3fSDimitry Andric     // FIXME: throw(conditional-expression), get expression
147*5f757f3fSDimitry Andric     break;
148*5f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_NoexceptFalse:
149*5f757f3fSDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
150*5f757f3fSDimitry Andric         .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
151*5f757f3fSDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text)
152*5f757f3fSDimitry Andric         .append("false", DeclarationFragments::FragmentKind::Keyword)
153*5f757f3fSDimitry Andric         .append(")", DeclarationFragments::FragmentKind::Text);
154*5f757f3fSDimitry Andric   case ExceptionSpecificationType::EST_NoexceptTrue:
155*5f757f3fSDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
156*5f757f3fSDimitry Andric         .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
157*5f757f3fSDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text)
158*5f757f3fSDimitry Andric         .append("true", DeclarationFragments::FragmentKind::Keyword)
159*5f757f3fSDimitry Andric         .append(")", DeclarationFragments::FragmentKind::Text);
160*5f757f3fSDimitry Andric   default:
161*5f757f3fSDimitry Andric     return Fragments;
162*5f757f3fSDimitry Andric   }
163*5f757f3fSDimitry Andric 
164*5f757f3fSDimitry Andric   llvm_unreachable("Unhandled exception specification");
165*5f757f3fSDimitry Andric }
166*5f757f3fSDimitry Andric 
167*5f757f3fSDimitry Andric DeclarationFragments
168*5f757f3fSDimitry Andric DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {
169*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
170*5f757f3fSDimitry Andric   if (Record->isStruct())
171*5f757f3fSDimitry Andric     Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
172*5f757f3fSDimitry Andric   else if (Record->isUnion())
173*5f757f3fSDimitry Andric     Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
174*5f757f3fSDimitry Andric   else
175*5f757f3fSDimitry Andric     Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
176*5f757f3fSDimitry Andric 
177*5f757f3fSDimitry Andric   return Fragments;
178*5f757f3fSDimitry Andric }
179*5f757f3fSDimitry Andric 
18081ad6265SDimitry Andric // NNS stores C++ nested name specifiers, which are prefixes to qualified names.
18181ad6265SDimitry Andric // Build declaration fragments for NNS recursively so that we have the USR for
18281ad6265SDimitry Andric // every part in a qualified name, and also leaves the actual underlying type
18381ad6265SDimitry Andric // cleaner for its own fragment.
18481ad6265SDimitry Andric DeclarationFragments
18581ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS,
18681ad6265SDimitry Andric                                                 ASTContext &Context,
18781ad6265SDimitry Andric                                                 DeclarationFragments &After) {
18881ad6265SDimitry Andric   DeclarationFragments Fragments;
18981ad6265SDimitry Andric   if (NNS->getPrefix())
19081ad6265SDimitry Andric     Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After));
19181ad6265SDimitry Andric 
19281ad6265SDimitry Andric   switch (NNS->getKind()) {
19381ad6265SDimitry Andric   case NestedNameSpecifier::Identifier:
19481ad6265SDimitry Andric     Fragments.append(NNS->getAsIdentifier()->getName(),
19581ad6265SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
19681ad6265SDimitry Andric     break;
19781ad6265SDimitry Andric 
19881ad6265SDimitry Andric   case NestedNameSpecifier::Namespace: {
19981ad6265SDimitry Andric     const NamespaceDecl *NS = NNS->getAsNamespace();
20081ad6265SDimitry Andric     if (NS->isAnonymousNamespace())
20181ad6265SDimitry Andric       return Fragments;
20281ad6265SDimitry Andric     SmallString<128> USR;
20381ad6265SDimitry Andric     index::generateUSRForDecl(NS, USR);
20481ad6265SDimitry Andric     Fragments.append(NS->getName(),
205bdd1243dSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier, USR, NS);
20681ad6265SDimitry Andric     break;
20781ad6265SDimitry Andric   }
20881ad6265SDimitry Andric 
20981ad6265SDimitry Andric   case NestedNameSpecifier::NamespaceAlias: {
21081ad6265SDimitry Andric     const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias();
21181ad6265SDimitry Andric     SmallString<128> USR;
21281ad6265SDimitry Andric     index::generateUSRForDecl(Alias, USR);
21381ad6265SDimitry Andric     Fragments.append(Alias->getName(),
214bdd1243dSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier, USR,
215bdd1243dSDimitry Andric                      Alias);
21681ad6265SDimitry Andric     break;
21781ad6265SDimitry Andric   }
21881ad6265SDimitry Andric 
21981ad6265SDimitry Andric   case NestedNameSpecifier::Global:
22081ad6265SDimitry Andric     // The global specifier `::` at the beginning. No stored value.
22181ad6265SDimitry Andric     break;
22281ad6265SDimitry Andric 
22381ad6265SDimitry Andric   case NestedNameSpecifier::Super:
22481ad6265SDimitry Andric     // Microsoft's `__super` specifier.
22581ad6265SDimitry Andric     Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);
22681ad6265SDimitry Andric     break;
22781ad6265SDimitry Andric 
22881ad6265SDimitry Andric   case NestedNameSpecifier::TypeSpecWithTemplate:
22981ad6265SDimitry Andric     // A type prefixed by the `template` keyword.
23081ad6265SDimitry Andric     Fragments.append("template", DeclarationFragments::FragmentKind::Keyword);
23181ad6265SDimitry Andric     Fragments.appendSpace();
23281ad6265SDimitry Andric     // Fallthrough after adding the keyword to handle the actual type.
233bdd1243dSDimitry Andric     [[fallthrough]];
23481ad6265SDimitry Andric 
23581ad6265SDimitry Andric   case NestedNameSpecifier::TypeSpec: {
23681ad6265SDimitry Andric     const Type *T = NNS->getAsType();
23781ad6265SDimitry Andric     // FIXME: Handle C++ template specialization type
23881ad6265SDimitry Andric     Fragments.append(getFragmentsForType(T, Context, After));
23981ad6265SDimitry Andric     break;
24081ad6265SDimitry Andric   }
24181ad6265SDimitry Andric   }
24281ad6265SDimitry Andric 
24381ad6265SDimitry Andric   // Add the separator text `::` for this segment.
24481ad6265SDimitry Andric   return Fragments.append("::", DeclarationFragments::FragmentKind::Text);
24581ad6265SDimitry Andric }
24681ad6265SDimitry Andric 
24781ad6265SDimitry Andric // Recursively build the declaration fragments for an underlying `Type` with
24881ad6265SDimitry Andric // qualifiers removed.
24981ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
25081ad6265SDimitry Andric     const Type *T, ASTContext &Context, DeclarationFragments &After) {
25181ad6265SDimitry Andric   assert(T && "invalid type");
25281ad6265SDimitry Andric 
25381ad6265SDimitry Andric   DeclarationFragments Fragments;
25481ad6265SDimitry Andric 
25581ad6265SDimitry Andric   // Declaration fragments of a pointer type is the declaration fragments of
25606c3fb27SDimitry Andric   // the pointee type followed by a `*`,
257*5f757f3fSDimitry Andric   if (T->isPointerType() && !T->isFunctionPointerType())
25881ad6265SDimitry Andric     return Fragments
25981ad6265SDimitry Andric         .append(getFragmentsForType(T->getPointeeType(), Context, After))
26081ad6265SDimitry Andric         .append(" *", DeclarationFragments::FragmentKind::Text);
26106c3fb27SDimitry Andric 
26206c3fb27SDimitry Andric   // For Objective-C `id` and `Class` pointers
26306c3fb27SDimitry Andric   // we do not spell out the `*`.
26406c3fb27SDimitry Andric   if (T->isObjCObjectPointerType() &&
26506c3fb27SDimitry Andric       !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {
26606c3fb27SDimitry Andric 
26706c3fb27SDimitry Andric     Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After));
26806c3fb27SDimitry Andric 
26906c3fb27SDimitry Andric     // id<protocol> is an qualified id type
27006c3fb27SDimitry Andric     // id<protocol>* is not an qualified id type
27106c3fb27SDimitry Andric     if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {
27206c3fb27SDimitry Andric       Fragments.append(" *", DeclarationFragments::FragmentKind::Text);
27306c3fb27SDimitry Andric     }
27406c3fb27SDimitry Andric 
27506c3fb27SDimitry Andric     return Fragments;
27681ad6265SDimitry Andric   }
27781ad6265SDimitry Andric 
27881ad6265SDimitry Andric   // Declaration fragments of a lvalue reference type is the declaration
27981ad6265SDimitry Andric   // fragments of the underlying type followed by a `&`.
28081ad6265SDimitry Andric   if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T))
28181ad6265SDimitry Andric     return Fragments
28281ad6265SDimitry Andric         .append(
28381ad6265SDimitry Andric             getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
28481ad6265SDimitry Andric         .append(" &", DeclarationFragments::FragmentKind::Text);
28581ad6265SDimitry Andric 
28681ad6265SDimitry Andric   // Declaration fragments of a rvalue reference type is the declaration
28781ad6265SDimitry Andric   // fragments of the underlying type followed by a `&&`.
28881ad6265SDimitry Andric   if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T))
28981ad6265SDimitry Andric     return Fragments
29081ad6265SDimitry Andric         .append(
29181ad6265SDimitry Andric             getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
29281ad6265SDimitry Andric         .append(" &&", DeclarationFragments::FragmentKind::Text);
29381ad6265SDimitry Andric 
29481ad6265SDimitry Andric   // Declaration fragments of an array-typed variable have two parts:
29581ad6265SDimitry Andric   // 1. the element type of the array that appears before the variable name;
29681ad6265SDimitry Andric   // 2. array brackets `[(0-9)?]` that appear after the variable name.
29781ad6265SDimitry Andric   if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) {
29881ad6265SDimitry Andric     // Build the "after" part first because the inner element type might also
29981ad6265SDimitry Andric     // be an array-type. For example `int matrix[3][4]` which has a type of
30081ad6265SDimitry Andric     // "(array 3 of (array 4 of ints))."
30181ad6265SDimitry Andric     // Push the array size part first to make sure they are in the right order.
30281ad6265SDimitry Andric     After.append("[", DeclarationFragments::FragmentKind::Text);
30381ad6265SDimitry Andric 
30481ad6265SDimitry Andric     switch (AT->getSizeModifier()) {
305*5f757f3fSDimitry Andric     case ArraySizeModifier::Normal:
30681ad6265SDimitry Andric       break;
307*5f757f3fSDimitry Andric     case ArraySizeModifier::Static:
30881ad6265SDimitry Andric       Fragments.append("static", DeclarationFragments::FragmentKind::Keyword);
30981ad6265SDimitry Andric       break;
310*5f757f3fSDimitry Andric     case ArraySizeModifier::Star:
31181ad6265SDimitry Andric       Fragments.append("*", DeclarationFragments::FragmentKind::Text);
31281ad6265SDimitry Andric       break;
31381ad6265SDimitry Andric     }
31481ad6265SDimitry Andric 
31581ad6265SDimitry Andric     if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
31681ad6265SDimitry Andric       // FIXME: right now this would evaluate any expressions/macros written in
31781ad6265SDimitry Andric       // the original source to concrete values. For example
31881ad6265SDimitry Andric       // `int nums[MAX]` -> `int nums[100]`
31981ad6265SDimitry Andric       // `char *str[5 + 1]` -> `char *str[6]`
32081ad6265SDimitry Andric       SmallString<128> Size;
32181ad6265SDimitry Andric       CAT->getSize().toStringUnsigned(Size);
32281ad6265SDimitry Andric       After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral);
32381ad6265SDimitry Andric     }
32481ad6265SDimitry Andric 
32581ad6265SDimitry Andric     After.append("]", DeclarationFragments::FragmentKind::Text);
32681ad6265SDimitry Andric 
32781ad6265SDimitry Andric     return Fragments.append(
32881ad6265SDimitry Andric         getFragmentsForType(AT->getElementType(), Context, After));
32981ad6265SDimitry Andric   }
33081ad6265SDimitry Andric 
33181ad6265SDimitry Andric   // An ElaboratedType is a sugar for types that are referred to using an
33281ad6265SDimitry Andric   // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
33381ad6265SDimitry Andric   // qualified name, e.g., `N::M::type`, or both.
33481ad6265SDimitry Andric   if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
33581ad6265SDimitry Andric     ElaboratedTypeKeyword Keyword = ET->getKeyword();
336*5f757f3fSDimitry Andric     if (Keyword != ElaboratedTypeKeyword::None) {
33781ad6265SDimitry Andric       Fragments
33881ad6265SDimitry Andric           .append(ElaboratedType::getKeywordName(Keyword),
33981ad6265SDimitry Andric                   DeclarationFragments::FragmentKind::Keyword)
34081ad6265SDimitry Andric           .appendSpace();
34181ad6265SDimitry Andric     }
34281ad6265SDimitry Andric 
34381ad6265SDimitry Andric     if (const NestedNameSpecifier *NNS = ET->getQualifier())
34481ad6265SDimitry Andric       Fragments.append(getFragmentsForNNS(NNS, Context, After));
34581ad6265SDimitry Andric 
34681ad6265SDimitry Andric     // After handling the elaborated keyword or qualified name, build
34781ad6265SDimitry Andric     // declaration fragments for the desugared underlying type.
34881ad6265SDimitry Andric     return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
34981ad6265SDimitry Andric   }
35081ad6265SDimitry Andric 
35181ad6265SDimitry Andric   // If the type is a typedefed type, get the underlying TypedefNameDecl for a
35281ad6265SDimitry Andric   // direct reference to the typedef instead of the wrapped type.
35306c3fb27SDimitry Andric 
35406c3fb27SDimitry Andric   // 'id' type is a typedef for an ObjCObjectPointerType
35506c3fb27SDimitry Andric   //  we treat it as a typedef
35681ad6265SDimitry Andric   if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
35781ad6265SDimitry Andric     const TypedefNameDecl *Decl = TypedefTy->getDecl();
358bdd1243dSDimitry Andric     TypedefUnderlyingTypeResolver TypedefResolver(Context);
359bdd1243dSDimitry Andric     std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));
36006c3fb27SDimitry Andric 
36106c3fb27SDimitry Andric     if (T->isObjCIdType()) {
36206c3fb27SDimitry Andric       return Fragments.append(Decl->getName(),
36306c3fb27SDimitry Andric                               DeclarationFragments::FragmentKind::Keyword);
36406c3fb27SDimitry Andric     }
36506c3fb27SDimitry Andric 
366bdd1243dSDimitry Andric     return Fragments.append(
367bdd1243dSDimitry Andric         Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,
368bdd1243dSDimitry Andric         USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));
36981ad6265SDimitry Andric   }
37081ad6265SDimitry Andric 
37106c3fb27SDimitry Andric   // Everything we care about has been handled now, reduce to the canonical
37206c3fb27SDimitry Andric   // unqualified base type.
37306c3fb27SDimitry Andric   QualType Base = T->getCanonicalTypeUnqualified();
37406c3fb27SDimitry Andric 
37581ad6265SDimitry Andric   // If the base type is a TagType (struct/interface/union/class/enum), let's
37681ad6265SDimitry Andric   // get the underlying Decl for better names and USRs.
37781ad6265SDimitry Andric   if (const TagType *TagTy = dyn_cast<TagType>(Base)) {
37881ad6265SDimitry Andric     const TagDecl *Decl = TagTy->getDecl();
37981ad6265SDimitry Andric     // Anonymous decl, skip this fragment.
38081ad6265SDimitry Andric     if (Decl->getName().empty())
38181ad6265SDimitry Andric       return Fragments;
38281ad6265SDimitry Andric     SmallString<128> TagUSR;
38381ad6265SDimitry Andric     clang::index::generateUSRForDecl(Decl, TagUSR);
38481ad6265SDimitry Andric     return Fragments.append(Decl->getName(),
38581ad6265SDimitry Andric                             DeclarationFragments::FragmentKind::TypeIdentifier,
386bdd1243dSDimitry Andric                             TagUSR, Decl);
38781ad6265SDimitry Andric   }
38881ad6265SDimitry Andric 
38981ad6265SDimitry Andric   // If the base type is an ObjCInterfaceType, use the underlying
39081ad6265SDimitry Andric   // ObjCInterfaceDecl for the true USR.
39181ad6265SDimitry Andric   if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
39281ad6265SDimitry Andric     const auto *Decl = ObjCIT->getDecl();
39381ad6265SDimitry Andric     SmallString<128> USR;
39481ad6265SDimitry Andric     index::generateUSRForDecl(Decl, USR);
39581ad6265SDimitry Andric     return Fragments.append(Decl->getName(),
39681ad6265SDimitry Andric                             DeclarationFragments::FragmentKind::TypeIdentifier,
397bdd1243dSDimitry Andric                             USR, Decl);
39881ad6265SDimitry Andric   }
39981ad6265SDimitry Andric 
40081ad6265SDimitry Andric   // Default fragment builder for other kinds of types (BuiltinType etc.)
40181ad6265SDimitry Andric   SmallString<128> USR;
40281ad6265SDimitry Andric   clang::index::generateUSRForType(Base, Context, USR);
40381ad6265SDimitry Andric   Fragments.append(Base.getAsString(),
40481ad6265SDimitry Andric                    DeclarationFragments::FragmentKind::TypeIdentifier, USR);
40581ad6265SDimitry Andric 
40681ad6265SDimitry Andric   return Fragments;
40781ad6265SDimitry Andric }
40881ad6265SDimitry Andric 
40981ad6265SDimitry Andric DeclarationFragments
41081ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) {
41181ad6265SDimitry Andric   DeclarationFragments Fragments;
41281ad6265SDimitry Andric   if (Quals.hasConst())
41381ad6265SDimitry Andric     Fragments.append("const", DeclarationFragments::FragmentKind::Keyword);
41481ad6265SDimitry Andric   if (Quals.hasVolatile())
41581ad6265SDimitry Andric     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword);
41681ad6265SDimitry Andric   if (Quals.hasRestrict())
41781ad6265SDimitry Andric     Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword);
41881ad6265SDimitry Andric 
41981ad6265SDimitry Andric   return Fragments;
42081ad6265SDimitry Andric }
42181ad6265SDimitry Andric 
42281ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
42381ad6265SDimitry Andric     const QualType QT, ASTContext &Context, DeclarationFragments &After) {
42481ad6265SDimitry Andric   assert(!QT.isNull() && "invalid type");
42581ad6265SDimitry Andric 
42681ad6265SDimitry Andric   if (const ParenType *PT = dyn_cast<ParenType>(QT)) {
42781ad6265SDimitry Andric     After.append(")", DeclarationFragments::FragmentKind::Text);
42881ad6265SDimitry Andric     return getFragmentsForType(PT->getInnerType(), Context, After)
42981ad6265SDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text);
43081ad6265SDimitry Andric   }
43181ad6265SDimitry Andric 
43281ad6265SDimitry Andric   const SplitQualType SQT = QT.split();
43381ad6265SDimitry Andric   DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals),
43481ad6265SDimitry Andric                        TypeFragments =
43581ad6265SDimitry Andric                            getFragmentsForType(SQT.Ty, Context, After);
436*5f757f3fSDimitry Andric   if (QT.getAsString() == "_Bool")
437*5f757f3fSDimitry Andric     TypeFragments.replace("bool", 0);
438*5f757f3fSDimitry Andric 
43981ad6265SDimitry Andric   if (QualsFragments.getFragments().empty())
44081ad6265SDimitry Andric     return TypeFragments;
44181ad6265SDimitry Andric 
44281ad6265SDimitry Andric   // Use east qualifier for pointer types
44381ad6265SDimitry Andric   // For example:
44481ad6265SDimitry Andric   // ```
44581ad6265SDimitry Andric   // int *   const
44681ad6265SDimitry Andric   // ^----   ^----
44781ad6265SDimitry Andric   //  type    qualifier
44881ad6265SDimitry Andric   // ^-----------------
44981ad6265SDimitry Andric   //  const pointer to int
45081ad6265SDimitry Andric   // ```
45181ad6265SDimitry Andric   // should not be reconstructed as
45281ad6265SDimitry Andric   // ```
45381ad6265SDimitry Andric   // const       int       *
45481ad6265SDimitry Andric   // ^----       ^--
45581ad6265SDimitry Andric   //  qualifier   type
45681ad6265SDimitry Andric   // ^----------------     ^
45781ad6265SDimitry Andric   //  pointer to const int
45881ad6265SDimitry Andric   // ```
45981ad6265SDimitry Andric   if (SQT.Ty->isAnyPointerType())
46081ad6265SDimitry Andric     return TypeFragments.appendSpace().append(std::move(QualsFragments));
46181ad6265SDimitry Andric 
46281ad6265SDimitry Andric   return QualsFragments.appendSpace().append(std::move(TypeFragments));
46381ad6265SDimitry Andric }
46481ad6265SDimitry Andric 
465*5f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
466*5f757f3fSDimitry Andric     const NamespaceDecl *Decl) {
467*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
468*5f757f3fSDimitry Andric   Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword);
469*5f757f3fSDimitry Andric   if (!Decl->isAnonymousNamespace())
470*5f757f3fSDimitry Andric     Fragments.appendSpace().append(
471*5f757f3fSDimitry Andric         Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
472*5f757f3fSDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
473*5f757f3fSDimitry Andric }
474*5f757f3fSDimitry Andric 
47581ad6265SDimitry Andric DeclarationFragments
47681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
47781ad6265SDimitry Andric   DeclarationFragments Fragments;
478*5f757f3fSDimitry Andric   if (Var->isConstexpr())
479*5f757f3fSDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
480*5f757f3fSDimitry Andric         .appendSpace();
481*5f757f3fSDimitry Andric 
48281ad6265SDimitry Andric   StorageClass SC = Var->getStorageClass();
48381ad6265SDimitry Andric   if (SC != SC_None)
48481ad6265SDimitry Andric     Fragments
48581ad6265SDimitry Andric         .append(VarDecl::getStorageClassSpecifierString(SC),
48681ad6265SDimitry Andric                 DeclarationFragments::FragmentKind::Keyword)
48781ad6265SDimitry Andric         .appendSpace();
48881ad6265SDimitry Andric 
48981ad6265SDimitry Andric   // Capture potential fragments that needs to be placed after the variable name
49081ad6265SDimitry Andric   // ```
49181ad6265SDimitry Andric   // int nums[5];
49281ad6265SDimitry Andric   // char (*ptr_to_array)[6];
49381ad6265SDimitry Andric   // ```
49481ad6265SDimitry Andric   DeclarationFragments After;
495*5f757f3fSDimitry Andric   FunctionTypeLoc BlockLoc;
496*5f757f3fSDimitry Andric   FunctionProtoTypeLoc BlockProtoLoc;
497*5f757f3fSDimitry Andric   findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc);
498*5f757f3fSDimitry Andric 
499*5f757f3fSDimitry Andric   if (!BlockLoc) {
500*5f757f3fSDimitry Andric     QualType T = Var->getTypeSourceInfo()
501*5f757f3fSDimitry Andric                      ? Var->getTypeSourceInfo()->getType()
502*5f757f3fSDimitry Andric                      : Var->getASTContext().getUnqualifiedObjCPointerType(
503*5f757f3fSDimitry Andric                            Var->getType());
504*5f757f3fSDimitry Andric 
505*5f757f3fSDimitry Andric     Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))
506*5f757f3fSDimitry Andric         .appendSpace();
507*5f757f3fSDimitry Andric   } else {
508*5f757f3fSDimitry Andric     Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));
509*5f757f3fSDimitry Andric   }
510*5f757f3fSDimitry Andric 
511*5f757f3fSDimitry Andric   return Fragments
512*5f757f3fSDimitry Andric       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
513*5f757f3fSDimitry Andric       .append(std::move(After))
514*5f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
515*5f757f3fSDimitry Andric }
516*5f757f3fSDimitry Andric 
517*5f757f3fSDimitry Andric DeclarationFragments
518*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
519*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
520*5f757f3fSDimitry Andric   if (Var->isConstexpr())
521*5f757f3fSDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
522*5f757f3fSDimitry Andric         .appendSpace();
523*5f757f3fSDimitry Andric   QualType T =
524*5f757f3fSDimitry Andric       Var->getTypeSourceInfo()
525*5f757f3fSDimitry Andric           ? Var->getTypeSourceInfo()->getType()
526*5f757f3fSDimitry Andric           : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());
527*5f757f3fSDimitry Andric 
528*5f757f3fSDimitry Andric   // Might be a member, so might be static.
529*5f757f3fSDimitry Andric   if (Var->isStaticDataMember())
530*5f757f3fSDimitry Andric     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
531*5f757f3fSDimitry Andric         .appendSpace();
532*5f757f3fSDimitry Andric 
533*5f757f3fSDimitry Andric   DeclarationFragments After;
534*5f757f3fSDimitry Andric   DeclarationFragments ArgumentFragment =
535*5f757f3fSDimitry Andric       getFragmentsForType(T, Var->getASTContext(), After);
536*5f757f3fSDimitry Andric   if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare(
537*5f757f3fSDimitry Andric           "type-parameter") == 0) {
538*5f757f3fSDimitry Andric     std::string ProperArgName = getNameForTemplateArgument(
539*5f757f3fSDimitry Andric         Var->getDescribedVarTemplate()->getTemplateParameters()->asArray(),
540*5f757f3fSDimitry Andric         ArgumentFragment.begin()->Spelling);
541*5f757f3fSDimitry Andric     ArgumentFragment.begin()->Spelling.swap(ProperArgName);
542*5f757f3fSDimitry Andric   }
543*5f757f3fSDimitry Andric   Fragments.append(std::move(ArgumentFragment))
54481ad6265SDimitry Andric       .appendSpace()
54581ad6265SDimitry Andric       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
546*5f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
547*5f757f3fSDimitry Andric   return Fragments;
54881ad6265SDimitry Andric }
54981ad6265SDimitry Andric 
55081ad6265SDimitry Andric DeclarationFragments
55181ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
55281ad6265SDimitry Andric   DeclarationFragments Fragments, After;
55381ad6265SDimitry Andric 
554*5f757f3fSDimitry Andric   auto *TSInfo = Param->getTypeSourceInfo();
555*5f757f3fSDimitry Andric 
556*5f757f3fSDimitry Andric   QualType T = TSInfo ? TSInfo->getType()
55781ad6265SDimitry Andric                       : Param->getASTContext().getUnqualifiedObjCPointerType(
55881ad6265SDimitry Andric                             Param->getType());
55981ad6265SDimitry Andric 
560*5f757f3fSDimitry Andric   FunctionTypeLoc BlockLoc;
561*5f757f3fSDimitry Andric   FunctionProtoTypeLoc BlockProtoLoc;
562*5f757f3fSDimitry Andric   findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);
56381ad6265SDimitry Andric 
564*5f757f3fSDimitry Andric   DeclarationFragments TypeFragments;
565*5f757f3fSDimitry Andric   if (BlockLoc)
566*5f757f3fSDimitry Andric     TypeFragments.append(
567*5f757f3fSDimitry Andric         getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
568*5f757f3fSDimitry Andric   else
569*5f757f3fSDimitry Andric     TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After));
570*5f757f3fSDimitry Andric 
571*5f757f3fSDimitry Andric   if (TypeFragments.begin()->Spelling.substr(0, 14).compare("type-parameter") ==
572*5f757f3fSDimitry Andric       0) {
573*5f757f3fSDimitry Andric     std::string ProperArgName = getNameForTemplateArgument(
574*5f757f3fSDimitry Andric         dyn_cast<FunctionDecl>(Param->getDeclContext())
575*5f757f3fSDimitry Andric             ->getDescribedFunctionTemplate()
576*5f757f3fSDimitry Andric             ->getTemplateParameters()
577*5f757f3fSDimitry Andric             ->asArray(),
578*5f757f3fSDimitry Andric         TypeFragments.begin()->Spelling);
579*5f757f3fSDimitry Andric     TypeFragments.begin()->Spelling.swap(ProperArgName);
580*5f757f3fSDimitry Andric   }
581*5f757f3fSDimitry Andric 
582*5f757f3fSDimitry Andric   if (Param->isObjCMethodParameter()) {
58381ad6265SDimitry Andric     Fragments.append("(", DeclarationFragments::FragmentKind::Text)
58481ad6265SDimitry Andric         .append(std::move(TypeFragments))
585*5f757f3fSDimitry Andric         .append(std::move(After))
586*5f757f3fSDimitry Andric         .append(") ", DeclarationFragments::FragmentKind::Text)
587*5f757f3fSDimitry Andric         .append(Param->getName(),
588*5f757f3fSDimitry Andric                 DeclarationFragments::FragmentKind::InternalParam);
589*5f757f3fSDimitry Andric   } else {
590*5f757f3fSDimitry Andric     Fragments.append(std::move(TypeFragments));
591*5f757f3fSDimitry Andric     if (!T->isBlockPointerType())
592*5f757f3fSDimitry Andric       Fragments.appendSpace();
593*5f757f3fSDimitry Andric     Fragments
59481ad6265SDimitry Andric         .append(Param->getName(),
59581ad6265SDimitry Andric                 DeclarationFragments::FragmentKind::InternalParam)
59681ad6265SDimitry Andric         .append(std::move(After));
59781ad6265SDimitry Andric   }
598*5f757f3fSDimitry Andric   return Fragments;
599*5f757f3fSDimitry Andric }
600*5f757f3fSDimitry Andric 
601*5f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock(
602*5f757f3fSDimitry Andric     const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
603*5f757f3fSDimitry Andric     FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) {
604*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
605*5f757f3fSDimitry Andric 
606*5f757f3fSDimitry Andric   DeclarationFragments RetTyAfter;
607*5f757f3fSDimitry Andric   auto ReturnValueFragment = getFragmentsForType(
608*5f757f3fSDimitry Andric       Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After);
609*5f757f3fSDimitry Andric 
610*5f757f3fSDimitry Andric   Fragments.append(std::move(ReturnValueFragment))
611*5f757f3fSDimitry Andric       .append(std::move(RetTyAfter))
612*5f757f3fSDimitry Andric       .appendSpace()
613*5f757f3fSDimitry Andric       .append("(^", DeclarationFragments::FragmentKind::Text);
614*5f757f3fSDimitry Andric 
615*5f757f3fSDimitry Andric   After.append(")", DeclarationFragments::FragmentKind::Text);
616*5f757f3fSDimitry Andric   unsigned NumParams = Block.getNumParams();
617*5f757f3fSDimitry Andric 
618*5f757f3fSDimitry Andric   if (!BlockProto || NumParams == 0) {
619*5f757f3fSDimitry Andric     if (BlockProto && BlockProto.getTypePtr()->isVariadic())
620*5f757f3fSDimitry Andric       After.append("(...)", DeclarationFragments::FragmentKind::Text);
621*5f757f3fSDimitry Andric     else
622*5f757f3fSDimitry Andric       After.append("()", DeclarationFragments::FragmentKind::Text);
623*5f757f3fSDimitry Andric   } else {
624*5f757f3fSDimitry Andric     After.append("(", DeclarationFragments::FragmentKind::Text);
625*5f757f3fSDimitry Andric     for (unsigned I = 0; I != NumParams; ++I) {
626*5f757f3fSDimitry Andric       if (I)
627*5f757f3fSDimitry Andric         After.append(", ", DeclarationFragments::FragmentKind::Text);
628*5f757f3fSDimitry Andric       After.append(getFragmentsForParam(Block.getParam(I)));
629*5f757f3fSDimitry Andric       if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic())
630*5f757f3fSDimitry Andric         After.append(", ...", DeclarationFragments::FragmentKind::Text);
631*5f757f3fSDimitry Andric     }
632*5f757f3fSDimitry Andric     After.append(")", DeclarationFragments::FragmentKind::Text);
633*5f757f3fSDimitry Andric   }
634*5f757f3fSDimitry Andric 
635*5f757f3fSDimitry Andric   return Fragments;
636*5f757f3fSDimitry Andric }
63781ad6265SDimitry Andric 
63881ad6265SDimitry Andric DeclarationFragments
63981ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
64081ad6265SDimitry Andric   DeclarationFragments Fragments;
64181ad6265SDimitry Andric   // FIXME: Handle template specialization
64281ad6265SDimitry Andric   switch (Func->getStorageClass()) {
64381ad6265SDimitry Andric   case SC_None:
64481ad6265SDimitry Andric   case SC_PrivateExtern:
64581ad6265SDimitry Andric     break;
64681ad6265SDimitry Andric   case SC_Extern:
64781ad6265SDimitry Andric     Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword)
64881ad6265SDimitry Andric         .appendSpace();
64981ad6265SDimitry Andric     break;
65081ad6265SDimitry Andric   case SC_Static:
65181ad6265SDimitry Andric     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
65281ad6265SDimitry Andric         .appendSpace();
65381ad6265SDimitry Andric     break;
65481ad6265SDimitry Andric   case SC_Auto:
65581ad6265SDimitry Andric   case SC_Register:
65681ad6265SDimitry Andric     llvm_unreachable("invalid for functions");
65781ad6265SDimitry Andric   }
658*5f757f3fSDimitry Andric   if (Func->isConsteval()) // if consteval, it is also constexpr
659*5f757f3fSDimitry Andric     Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword)
660*5f757f3fSDimitry Andric         .appendSpace();
661*5f757f3fSDimitry Andric   else if (Func->isConstexpr())
662*5f757f3fSDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
663*5f757f3fSDimitry Andric         .appendSpace();
66481ad6265SDimitry Andric 
66581ad6265SDimitry Andric   // FIXME: Is `after` actually needed here?
66681ad6265SDimitry Andric   DeclarationFragments After;
667*5f757f3fSDimitry Andric   auto ReturnValueFragment =
668*5f757f3fSDimitry Andric       getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After);
669*5f757f3fSDimitry Andric   if (ReturnValueFragment.begin()->Spelling.substr(0, 14).compare(
670*5f757f3fSDimitry Andric           "type-parameter") == 0) {
671*5f757f3fSDimitry Andric     std::string ProperArgName =
672*5f757f3fSDimitry Andric         getNameForTemplateArgument(Func->getDescribedFunctionTemplate()
673*5f757f3fSDimitry Andric                                        ->getTemplateParameters()
674*5f757f3fSDimitry Andric                                        ->asArray(),
675*5f757f3fSDimitry Andric                                    ReturnValueFragment.begin()->Spelling);
676*5f757f3fSDimitry Andric     ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
677*5f757f3fSDimitry Andric   }
678*5f757f3fSDimitry Andric 
679*5f757f3fSDimitry Andric   Fragments.append(std::move(ReturnValueFragment))
68081ad6265SDimitry Andric       .appendSpace()
681*5f757f3fSDimitry Andric       .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier);
682*5f757f3fSDimitry Andric 
683*5f757f3fSDimitry Andric   if (Func->getTemplateSpecializationInfo()) {
684*5f757f3fSDimitry Andric     Fragments.append("<", DeclarationFragments::FragmentKind::Text);
685*5f757f3fSDimitry Andric 
686*5f757f3fSDimitry Andric     for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
687*5f757f3fSDimitry Andric       if (i)
688*5f757f3fSDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
689*5f757f3fSDimitry Andric       Fragments.append(
690*5f757f3fSDimitry Andric           getFragmentsForType(Func->getParamDecl(i)->getType(),
691*5f757f3fSDimitry Andric                               Func->getParamDecl(i)->getASTContext(), After));
692*5f757f3fSDimitry Andric     }
693*5f757f3fSDimitry Andric     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
694*5f757f3fSDimitry Andric   }
695*5f757f3fSDimitry Andric   Fragments.append(std::move(After));
69681ad6265SDimitry Andric 
69781ad6265SDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
698*5f757f3fSDimitry Andric   unsigned NumParams = Func->getNumParams();
699*5f757f3fSDimitry Andric   for (unsigned i = 0; i != NumParams; ++i) {
70081ad6265SDimitry Andric     if (i)
70181ad6265SDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
70281ad6265SDimitry Andric     Fragments.append(getFragmentsForParam(Func->getParamDecl(i)));
70381ad6265SDimitry Andric   }
704*5f757f3fSDimitry Andric 
705*5f757f3fSDimitry Andric   if (Func->isVariadic()) {
706*5f757f3fSDimitry Andric     if (NumParams > 0)
707*5f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
708*5f757f3fSDimitry Andric     Fragments.append("...", DeclarationFragments::FragmentKind::Text);
709*5f757f3fSDimitry Andric   }
71081ad6265SDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
71181ad6265SDimitry Andric 
712*5f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
713*5f757f3fSDimitry Andric       Func->getExceptionSpecType()));
714*5f757f3fSDimitry Andric 
71506c3fb27SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
71681ad6265SDimitry Andric }
71781ad6265SDimitry Andric 
71881ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
71981ad6265SDimitry Andric     const EnumConstantDecl *EnumConstDecl) {
72081ad6265SDimitry Andric   DeclarationFragments Fragments;
72181ad6265SDimitry Andric   return Fragments.append(EnumConstDecl->getName(),
72281ad6265SDimitry Andric                           DeclarationFragments::FragmentKind::Identifier);
72381ad6265SDimitry Andric }
72481ad6265SDimitry Andric 
72581ad6265SDimitry Andric DeclarationFragments
72681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
72781ad6265SDimitry Andric   if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl())
72881ad6265SDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
72981ad6265SDimitry Andric 
73081ad6265SDimitry Andric   DeclarationFragments Fragments, After;
73181ad6265SDimitry Andric   Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword);
73281ad6265SDimitry Andric 
73381ad6265SDimitry Andric   if (!EnumDecl->getName().empty())
73481ad6265SDimitry Andric     Fragments.appendSpace().append(
73581ad6265SDimitry Andric         EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier);
73681ad6265SDimitry Andric 
73781ad6265SDimitry Andric   QualType IntegerType = EnumDecl->getIntegerType();
73881ad6265SDimitry Andric   if (!IntegerType.isNull())
73981ad6265SDimitry Andric     Fragments.append(": ", DeclarationFragments::FragmentKind::Text)
74081ad6265SDimitry Andric         .append(
74181ad6265SDimitry Andric             getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
74281ad6265SDimitry Andric         .append(std::move(After));
74381ad6265SDimitry Andric 
74406c3fb27SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
74581ad6265SDimitry Andric }
74681ad6265SDimitry Andric 
74781ad6265SDimitry Andric DeclarationFragments
74881ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
74981ad6265SDimitry Andric   DeclarationFragments After;
750*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
751*5f757f3fSDimitry Andric   if (Field->isMutable())
752*5f757f3fSDimitry Andric     Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword)
753*5f757f3fSDimitry Andric         .appendSpace();
754*5f757f3fSDimitry Andric   return Fragments
755*5f757f3fSDimitry Andric       .append(
756*5f757f3fSDimitry Andric           getFragmentsForType(Field->getType(), Field->getASTContext(), After))
75781ad6265SDimitry Andric       .appendSpace()
75881ad6265SDimitry Andric       .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
759*5f757f3fSDimitry Andric       .append(std::move(After))
760*5f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
76181ad6265SDimitry Andric }
76281ad6265SDimitry Andric 
76381ad6265SDimitry Andric DeclarationFragments
76481ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) {
76581ad6265SDimitry Andric   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
76681ad6265SDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
76781ad6265SDimitry Andric 
76881ad6265SDimitry Andric   DeclarationFragments Fragments;
76981ad6265SDimitry Andric   Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
77081ad6265SDimitry Andric 
77181ad6265SDimitry Andric   if (!Record->getName().empty())
77281ad6265SDimitry Andric     Fragments.appendSpace().append(
77381ad6265SDimitry Andric         Record->getName(), DeclarationFragments::FragmentKind::Identifier);
77406c3fb27SDimitry Andric 
77506c3fb27SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
77681ad6265SDimitry Andric }
77781ad6265SDimitry Andric 
778*5f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
779*5f757f3fSDimitry Andric     const CXXRecordDecl *Record) {
780*5f757f3fSDimitry Andric   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
781*5f757f3fSDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
782*5f757f3fSDimitry Andric 
783*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
784*5f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getStructureTypeFragment(Record));
785*5f757f3fSDimitry Andric 
786*5f757f3fSDimitry Andric   if (!Record->getName().empty())
787*5f757f3fSDimitry Andric     Fragments.appendSpace().append(
788*5f757f3fSDimitry Andric         Record->getName(), DeclarationFragments::FragmentKind::Identifier);
789*5f757f3fSDimitry Andric 
790*5f757f3fSDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
791*5f757f3fSDimitry Andric }
792*5f757f3fSDimitry Andric 
793*5f757f3fSDimitry Andric DeclarationFragments
794*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
795*5f757f3fSDimitry Andric     const CXXMethodDecl *Method) {
796*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
797*5f757f3fSDimitry Andric   std::string Name;
798*5f757f3fSDimitry Andric   if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) {
799*5f757f3fSDimitry Andric     Name = Method->getNameAsString();
800*5f757f3fSDimitry Andric     if (Constructor->isExplicit())
801*5f757f3fSDimitry Andric       Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
802*5f757f3fSDimitry Andric           .appendSpace();
803*5f757f3fSDimitry Andric   } else if (isa<CXXDestructorDecl>(Method))
804*5f757f3fSDimitry Andric     Name = Method->getNameAsString();
805*5f757f3fSDimitry Andric 
806*5f757f3fSDimitry Andric   DeclarationFragments After;
807*5f757f3fSDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier)
808*5f757f3fSDimitry Andric       .append(std::move(After));
809*5f757f3fSDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
810*5f757f3fSDimitry Andric   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
811*5f757f3fSDimitry Andric     if (i)
812*5f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
813*5f757f3fSDimitry Andric     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
814*5f757f3fSDimitry Andric   }
815*5f757f3fSDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
816*5f757f3fSDimitry Andric 
817*5f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
818*5f757f3fSDimitry Andric       Method->getExceptionSpecType()));
819*5f757f3fSDimitry Andric 
820*5f757f3fSDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
821*5f757f3fSDimitry Andric }
822*5f757f3fSDimitry Andric 
823*5f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
824*5f757f3fSDimitry Andric     const CXXMethodDecl *Method) {
825*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
826*5f757f3fSDimitry Andric   StringRef Name = Method->getName();
827*5f757f3fSDimitry Andric   if (Method->isStatic())
828*5f757f3fSDimitry Andric     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
829*5f757f3fSDimitry Andric         .appendSpace();
830*5f757f3fSDimitry Andric   if (Method->isConstexpr())
831*5f757f3fSDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
832*5f757f3fSDimitry Andric         .appendSpace();
833*5f757f3fSDimitry Andric   if (Method->isVolatile())
834*5f757f3fSDimitry Andric     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword)
835*5f757f3fSDimitry Andric         .appendSpace();
836*5f757f3fSDimitry Andric 
837*5f757f3fSDimitry Andric   // Build return type
838*5f757f3fSDimitry Andric   DeclarationFragments After;
839*5f757f3fSDimitry Andric   Fragments
840*5f757f3fSDimitry Andric       .append(getFragmentsForType(Method->getReturnType(),
841*5f757f3fSDimitry Andric                                   Method->getASTContext(), After))
842*5f757f3fSDimitry Andric       .appendSpace()
843*5f757f3fSDimitry Andric       .append(Name, DeclarationFragments::FragmentKind::Identifier)
844*5f757f3fSDimitry Andric       .append(std::move(After));
845*5f757f3fSDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
846*5f757f3fSDimitry Andric   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
847*5f757f3fSDimitry Andric     if (i)
848*5f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
849*5f757f3fSDimitry Andric     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
850*5f757f3fSDimitry Andric   }
851*5f757f3fSDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
852*5f757f3fSDimitry Andric 
853*5f757f3fSDimitry Andric   if (Method->isConst())
854*5f757f3fSDimitry Andric     Fragments.appendSpace().append("const",
855*5f757f3fSDimitry Andric                                    DeclarationFragments::FragmentKind::Keyword);
856*5f757f3fSDimitry Andric 
857*5f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
858*5f757f3fSDimitry Andric       Method->getExceptionSpecType()));
859*5f757f3fSDimitry Andric 
860*5f757f3fSDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
861*5f757f3fSDimitry Andric }
862*5f757f3fSDimitry Andric 
863*5f757f3fSDimitry Andric DeclarationFragments
864*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
865*5f757f3fSDimitry Andric     const CXXConversionDecl *ConversionFunction) {
866*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
867*5f757f3fSDimitry Andric 
868*5f757f3fSDimitry Andric   if (ConversionFunction->isExplicit())
869*5f757f3fSDimitry Andric     Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
870*5f757f3fSDimitry Andric         .appendSpace();
871*5f757f3fSDimitry Andric 
872*5f757f3fSDimitry Andric   Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword)
873*5f757f3fSDimitry Andric       .appendSpace();
874*5f757f3fSDimitry Andric 
875*5f757f3fSDimitry Andric   Fragments
876*5f757f3fSDimitry Andric       .append(ConversionFunction->getConversionType().getAsString(),
877*5f757f3fSDimitry Andric               DeclarationFragments::FragmentKind::TypeIdentifier)
878*5f757f3fSDimitry Andric       .append("(", DeclarationFragments::FragmentKind::Text);
879*5f757f3fSDimitry Andric   for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
880*5f757f3fSDimitry Andric        ++i) {
881*5f757f3fSDimitry Andric     if (i)
882*5f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
883*5f757f3fSDimitry Andric     Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
884*5f757f3fSDimitry Andric   }
885*5f757f3fSDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
886*5f757f3fSDimitry Andric 
887*5f757f3fSDimitry Andric   if (ConversionFunction->isConst())
888*5f757f3fSDimitry Andric     Fragments.appendSpace().append("const",
889*5f757f3fSDimitry Andric                                    DeclarationFragments::FragmentKind::Keyword);
890*5f757f3fSDimitry Andric 
891*5f757f3fSDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
892*5f757f3fSDimitry Andric }
893*5f757f3fSDimitry Andric 
894*5f757f3fSDimitry Andric DeclarationFragments
895*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
896*5f757f3fSDimitry Andric     const CXXMethodDecl *Method) {
897*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
898*5f757f3fSDimitry Andric 
899*5f757f3fSDimitry Andric   // Build return type
900*5f757f3fSDimitry Andric   DeclarationFragments After;
901*5f757f3fSDimitry Andric   Fragments
902*5f757f3fSDimitry Andric       .append(getFragmentsForType(Method->getReturnType(),
903*5f757f3fSDimitry Andric                                   Method->getASTContext(), After))
904*5f757f3fSDimitry Andric       .appendSpace()
905*5f757f3fSDimitry Andric       .append(Method->getNameAsString(),
906*5f757f3fSDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
907*5f757f3fSDimitry Andric       .append(std::move(After));
908*5f757f3fSDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
909*5f757f3fSDimitry Andric   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
910*5f757f3fSDimitry Andric     if (i)
911*5f757f3fSDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
912*5f757f3fSDimitry Andric     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
913*5f757f3fSDimitry Andric   }
914*5f757f3fSDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
915*5f757f3fSDimitry Andric 
916*5f757f3fSDimitry Andric   if (Method->isConst())
917*5f757f3fSDimitry Andric     Fragments.appendSpace().append("const",
918*5f757f3fSDimitry Andric                                    DeclarationFragments::FragmentKind::Keyword);
919*5f757f3fSDimitry Andric 
920*5f757f3fSDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
921*5f757f3fSDimitry Andric       Method->getExceptionSpecType()));
922*5f757f3fSDimitry Andric 
923*5f757f3fSDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
924*5f757f3fSDimitry Andric }
925*5f757f3fSDimitry Andric 
926*5f757f3fSDimitry Andric // Get fragments for template parameters, e.g. T in tempalte<typename T> ...
927*5f757f3fSDimitry Andric DeclarationFragments
928*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(
929*5f757f3fSDimitry Andric     ArrayRef<NamedDecl *> ParameterArray) {
930*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
931*5f757f3fSDimitry Andric   for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {
932*5f757f3fSDimitry Andric     if (i)
933*5f757f3fSDimitry Andric       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
934*5f757f3fSDimitry Andric           .appendSpace();
935*5f757f3fSDimitry Andric 
936*5f757f3fSDimitry Andric     const auto *TemplateParam =
937*5f757f3fSDimitry Andric         dyn_cast<TemplateTypeParmDecl>(ParameterArray[i]);
938*5f757f3fSDimitry Andric     if (!TemplateParam)
939*5f757f3fSDimitry Andric       continue;
940*5f757f3fSDimitry Andric     if (TemplateParam->hasTypeConstraint())
941*5f757f3fSDimitry Andric       Fragments.append(TemplateParam->getTypeConstraint()
942*5f757f3fSDimitry Andric                            ->getNamedConcept()
943*5f757f3fSDimitry Andric                            ->getName()
944*5f757f3fSDimitry Andric                            .str(),
945*5f757f3fSDimitry Andric                        DeclarationFragments::FragmentKind::TypeIdentifier);
946*5f757f3fSDimitry Andric     else if (TemplateParam->wasDeclaredWithTypename())
947*5f757f3fSDimitry Andric       Fragments.append("typename", DeclarationFragments::FragmentKind::Keyword);
948*5f757f3fSDimitry Andric     else
949*5f757f3fSDimitry Andric       Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
950*5f757f3fSDimitry Andric 
951*5f757f3fSDimitry Andric     if (TemplateParam->isParameterPack())
952*5f757f3fSDimitry Andric       Fragments.append("...", DeclarationFragments::FragmentKind::Text);
953*5f757f3fSDimitry Andric 
954*5f757f3fSDimitry Andric     Fragments.appendSpace().append(
955*5f757f3fSDimitry Andric         TemplateParam->getName(),
956*5f757f3fSDimitry Andric         DeclarationFragments::FragmentKind::GenericParameter);
957*5f757f3fSDimitry Andric   }
958*5f757f3fSDimitry Andric   return Fragments;
959*5f757f3fSDimitry Andric }
960*5f757f3fSDimitry Andric 
961*5f757f3fSDimitry Andric // Find the name of a template argument from the template's parameters.
962*5f757f3fSDimitry Andric std::string DeclarationFragmentsBuilder::getNameForTemplateArgument(
963*5f757f3fSDimitry Andric     const ArrayRef<NamedDecl *> TemplateParameters, std::string TypeParameter) {
964*5f757f3fSDimitry Andric   // The arg is a generic parameter from a partial spec, e.g.
965*5f757f3fSDimitry Andric   // T in template<typename T> Foo<T, int>.
966*5f757f3fSDimitry Andric   //
967*5f757f3fSDimitry Andric   // Those names appear as "type-parameter-<index>-<depth>", so we must find its
968*5f757f3fSDimitry Andric   // name from the template's parameter list.
969*5f757f3fSDimitry Andric   for (unsigned i = 0; i < TemplateParameters.size(); ++i) {
970*5f757f3fSDimitry Andric     const auto *Parameter =
971*5f757f3fSDimitry Andric         dyn_cast<TemplateTypeParmDecl>(TemplateParameters[i]);
972*5f757f3fSDimitry Andric     if (TypeParameter.compare("type-parameter-" +
973*5f757f3fSDimitry Andric                               std::to_string(Parameter->getDepth()) + "-" +
974*5f757f3fSDimitry Andric                               std::to_string(Parameter->getIndex())) == 0)
975*5f757f3fSDimitry Andric       return std::string(TemplateParameters[i]->getName());
976*5f757f3fSDimitry Andric   }
977*5f757f3fSDimitry Andric   llvm_unreachable("Could not find the name of a template argument.");
978*5f757f3fSDimitry Andric }
979*5f757f3fSDimitry Andric 
980*5f757f3fSDimitry Andric // Get fragments for template arguments, e.g. int in template<typename T>
981*5f757f3fSDimitry Andric // Foo<int>;
982*5f757f3fSDimitry Andric //
983*5f757f3fSDimitry Andric // Note: TemplateParameters is only necessary if the Decl is a
984*5f757f3fSDimitry Andric // PartialSpecialization, where we need the parameters to deduce the name of the
985*5f757f3fSDimitry Andric // generic arguments.
986*5f757f3fSDimitry Andric DeclarationFragments
987*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateArguments(
988*5f757f3fSDimitry Andric     const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context,
989*5f757f3fSDimitry Andric     const std::optional<ArrayRef<NamedDecl *>> TemplateParameters) {
990*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
991*5f757f3fSDimitry Andric   for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
992*5f757f3fSDimitry Andric     if (i)
993*5f757f3fSDimitry Andric       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
994*5f757f3fSDimitry Andric           .appendSpace();
995*5f757f3fSDimitry Andric 
996*5f757f3fSDimitry Andric     std::string Type = TemplateArguments[i].getAsType().getAsString();
997*5f757f3fSDimitry Andric     DeclarationFragments After;
998*5f757f3fSDimitry Andric     DeclarationFragments ArgumentFragment =
999*5f757f3fSDimitry Andric         getFragmentsForType(TemplateArguments[i].getAsType(), Context, After);
1000*5f757f3fSDimitry Andric 
1001*5f757f3fSDimitry Andric     if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare(
1002*5f757f3fSDimitry Andric             "type-parameter") == 0) {
1003*5f757f3fSDimitry Andric       std::string ProperArgName = getNameForTemplateArgument(
1004*5f757f3fSDimitry Andric           TemplateParameters.value(), ArgumentFragment.begin()->Spelling);
1005*5f757f3fSDimitry Andric       ArgumentFragment.begin()->Spelling.swap(ProperArgName);
1006*5f757f3fSDimitry Andric     }
1007*5f757f3fSDimitry Andric     Fragments.append(std::move(ArgumentFragment));
1008*5f757f3fSDimitry Andric 
1009*5f757f3fSDimitry Andric     if (TemplateArguments[i].isPackExpansion())
1010*5f757f3fSDimitry Andric       Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1011*5f757f3fSDimitry Andric   }
1012*5f757f3fSDimitry Andric   return Fragments;
1013*5f757f3fSDimitry Andric }
1014*5f757f3fSDimitry Andric 
1015*5f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
1016*5f757f3fSDimitry Andric     const ConceptDecl *Concept) {
1017*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
1018*5f757f3fSDimitry Andric   return Fragments
1019*5f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1020*5f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1021*5f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
1022*5f757f3fSDimitry Andric           Concept->getTemplateParameters()->asArray()))
1023*5f757f3fSDimitry Andric       .append("> ", DeclarationFragments::FragmentKind::Text)
1024*5f757f3fSDimitry Andric       .append("concept", DeclarationFragments::FragmentKind::Keyword)
1025*5f757f3fSDimitry Andric       .appendSpace()
1026*5f757f3fSDimitry Andric       .append(Concept->getName().str(),
1027*5f757f3fSDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
1028*5f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
1029*5f757f3fSDimitry Andric }
1030*5f757f3fSDimitry Andric 
1031*5f757f3fSDimitry Andric DeclarationFragments
1032*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
1033*5f757f3fSDimitry Andric     const RedeclarableTemplateDecl *RedeclarableTemplate) {
1034*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
1035*5f757f3fSDimitry Andric   Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
1036*5f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1037*5f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
1038*5f757f3fSDimitry Andric           RedeclarableTemplate->getTemplateParameters()->asArray()))
1039*5f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1040*5f757f3fSDimitry Andric       .appendSpace();
1041*5f757f3fSDimitry Andric 
1042*5f757f3fSDimitry Andric   if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate))
1043*5f757f3fSDimitry Andric     Fragments.appendSpace()
1044*5f757f3fSDimitry Andric         .append("using", DeclarationFragments::FragmentKind::Keyword)
1045*5f757f3fSDimitry Andric         .appendSpace()
1046*5f757f3fSDimitry Andric         .append(RedeclarableTemplate->getName(),
1047*5f757f3fSDimitry Andric                 DeclarationFragments::FragmentKind::Identifier);
1048*5f757f3fSDimitry Andric   // the templated records will be resposbible for injecting their templates
1049*5f757f3fSDimitry Andric   return Fragments.appendSpace();
1050*5f757f3fSDimitry Andric }
1051*5f757f3fSDimitry Andric 
1052*5f757f3fSDimitry Andric DeclarationFragments
1053*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
1054*5f757f3fSDimitry Andric     const ClassTemplateSpecializationDecl *Decl) {
1055*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
1056*5f757f3fSDimitry Andric   return Fragments
1057*5f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1058*5f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1059*5f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1060*5f757f3fSDimitry Andric       .appendSpace()
1061*5f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
1062*5f757f3fSDimitry Andric           cast<CXXRecordDecl>(Decl)))
1063*5f757f3fSDimitry Andric       .pop_back() // there is an extra semicolon now
1064*5f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1065*5f757f3fSDimitry Andric       .append(
1066*5f757f3fSDimitry Andric           getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
1067*5f757f3fSDimitry Andric                                            Decl->getASTContext(), std::nullopt))
1068*5f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1069*5f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
1070*5f757f3fSDimitry Andric }
1071*5f757f3fSDimitry Andric 
1072*5f757f3fSDimitry Andric DeclarationFragments
1073*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
1074*5f757f3fSDimitry Andric     const ClassTemplatePartialSpecializationDecl *Decl) {
1075*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
1076*5f757f3fSDimitry Andric   return Fragments
1077*5f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1078*5f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1079*5f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
1080*5f757f3fSDimitry Andric           Decl->getTemplateParameters()->asArray()))
1081*5f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1082*5f757f3fSDimitry Andric       .appendSpace()
1083*5f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
1084*5f757f3fSDimitry Andric           cast<CXXRecordDecl>(Decl)))
1085*5f757f3fSDimitry Andric       .pop_back() // there is an extra semicolon now
1086*5f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1087*5f757f3fSDimitry Andric       .append(getFragmentsForTemplateArguments(
1088*5f757f3fSDimitry Andric           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1089*5f757f3fSDimitry Andric           Decl->getTemplateParameters()->asArray()))
1090*5f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1091*5f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
1092*5f757f3fSDimitry Andric }
1093*5f757f3fSDimitry Andric 
1094*5f757f3fSDimitry Andric DeclarationFragments
1095*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
1096*5f757f3fSDimitry Andric     const VarTemplateSpecializationDecl *Decl) {
1097*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
1098*5f757f3fSDimitry Andric   return Fragments
1099*5f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1100*5f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1101*5f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1102*5f757f3fSDimitry Andric       .appendSpace()
1103*5f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
1104*5f757f3fSDimitry Andric       .pop_back() // there is an extra semicolon now
1105*5f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1106*5f757f3fSDimitry Andric       .append(
1107*5f757f3fSDimitry Andric           getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
1108*5f757f3fSDimitry Andric                                            Decl->getASTContext(), std::nullopt))
1109*5f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1110*5f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
1111*5f757f3fSDimitry Andric }
1112*5f757f3fSDimitry Andric 
1113*5f757f3fSDimitry Andric DeclarationFragments
1114*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
1115*5f757f3fSDimitry Andric     const VarTemplatePartialSpecializationDecl *Decl) {
1116*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
1117*5f757f3fSDimitry Andric   return Fragments
1118*5f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1119*5f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1120*5f757f3fSDimitry Andric       // Partial specs may have new params.
1121*5f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
1122*5f757f3fSDimitry Andric           Decl->getTemplateParameters()->asArray()))
1123*5f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1124*5f757f3fSDimitry Andric       .appendSpace()
1125*5f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
1126*5f757f3fSDimitry Andric       .pop_back() // there is an extra semicolon now
1127*5f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1128*5f757f3fSDimitry Andric       .append(getFragmentsForTemplateArguments(
1129*5f757f3fSDimitry Andric           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1130*5f757f3fSDimitry Andric           Decl->getTemplateParameters()->asArray()))
1131*5f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1132*5f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
1133*5f757f3fSDimitry Andric }
1134*5f757f3fSDimitry Andric 
1135*5f757f3fSDimitry Andric DeclarationFragments
1136*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
1137*5f757f3fSDimitry Andric     const FunctionTemplateDecl *Decl) {
1138*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
1139*5f757f3fSDimitry Andric   return Fragments
1140*5f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1141*5f757f3fSDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1142*5f757f3fSDimitry Andric       // Partial specs may have new params.
1143*5f757f3fSDimitry Andric       .append(getFragmentsForTemplateParameters(
1144*5f757f3fSDimitry Andric           Decl->getTemplateParameters()->asArray()))
1145*5f757f3fSDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1146*5f757f3fSDimitry Andric       .appendSpace()
1147*5f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForFunction(
1148*5f757f3fSDimitry Andric           Decl->getAsFunction()));
1149*5f757f3fSDimitry Andric }
1150*5f757f3fSDimitry Andric 
1151*5f757f3fSDimitry Andric DeclarationFragments
1152*5f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(
1153*5f757f3fSDimitry Andric     const FunctionDecl *Decl) {
1154*5f757f3fSDimitry Andric   DeclarationFragments Fragments;
1155*5f757f3fSDimitry Andric   return Fragments
1156*5f757f3fSDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1157*5f757f3fSDimitry Andric       .append("<>", DeclarationFragments::FragmentKind::Text)
1158*5f757f3fSDimitry Andric       .appendSpace()
1159*5f757f3fSDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl));
1160*5f757f3fSDimitry Andric }
1161*5f757f3fSDimitry Andric 
116281ad6265SDimitry Andric DeclarationFragments
116381ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,
116481ad6265SDimitry Andric                                                   const MacroDirective *MD) {
116581ad6265SDimitry Andric   DeclarationFragments Fragments;
116681ad6265SDimitry Andric   Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword)
116781ad6265SDimitry Andric       .appendSpace();
116881ad6265SDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
116981ad6265SDimitry Andric 
117081ad6265SDimitry Andric   auto *MI = MD->getMacroInfo();
117181ad6265SDimitry Andric 
117281ad6265SDimitry Andric   if (MI->isFunctionLike()) {
117381ad6265SDimitry Andric     Fragments.append("(", DeclarationFragments::FragmentKind::Text);
117481ad6265SDimitry Andric     unsigned numParameters = MI->getNumParams();
117581ad6265SDimitry Andric     if (MI->isC99Varargs())
117681ad6265SDimitry Andric       --numParameters;
117781ad6265SDimitry Andric     for (unsigned i = 0; i < numParameters; ++i) {
117881ad6265SDimitry Andric       if (i)
117981ad6265SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
118081ad6265SDimitry Andric       Fragments.append(MI->params()[i]->getName(),
118181ad6265SDimitry Andric                        DeclarationFragments::FragmentKind::InternalParam);
118281ad6265SDimitry Andric     }
118381ad6265SDimitry Andric     if (MI->isVariadic()) {
118481ad6265SDimitry Andric       if (numParameters && MI->isC99Varargs())
118581ad6265SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
118681ad6265SDimitry Andric       Fragments.append("...", DeclarationFragments::FragmentKind::Text);
118781ad6265SDimitry Andric     }
118881ad6265SDimitry Andric     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
118981ad6265SDimitry Andric   }
119081ad6265SDimitry Andric   return Fragments;
119181ad6265SDimitry Andric }
119281ad6265SDimitry Andric 
119381ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
119481ad6265SDimitry Andric     const ObjCCategoryDecl *Category) {
119581ad6265SDimitry Andric   DeclarationFragments Fragments;
119681ad6265SDimitry Andric 
1197bdd1243dSDimitry Andric   auto *Interface = Category->getClassInterface();
119881ad6265SDimitry Andric   SmallString<128> InterfaceUSR;
1199bdd1243dSDimitry Andric   index::generateUSRForDecl(Interface, InterfaceUSR);
120081ad6265SDimitry Andric 
120181ad6265SDimitry Andric   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
120281ad6265SDimitry Andric       .appendSpace()
120381ad6265SDimitry Andric       .append(Category->getClassInterface()->getName(),
1204bdd1243dSDimitry Andric               DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
1205bdd1243dSDimitry Andric               Interface)
120681ad6265SDimitry Andric       .append(" (", DeclarationFragments::FragmentKind::Text)
120781ad6265SDimitry Andric       .append(Category->getName(),
120881ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
120981ad6265SDimitry Andric       .append(")", DeclarationFragments::FragmentKind::Text);
121081ad6265SDimitry Andric 
121181ad6265SDimitry Andric   return Fragments;
121281ad6265SDimitry Andric }
121381ad6265SDimitry Andric 
121481ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface(
121581ad6265SDimitry Andric     const ObjCInterfaceDecl *Interface) {
121681ad6265SDimitry Andric   DeclarationFragments Fragments;
121781ad6265SDimitry Andric   // Build the base of the Objective-C interface declaration.
121881ad6265SDimitry Andric   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
121981ad6265SDimitry Andric       .appendSpace()
122081ad6265SDimitry Andric       .append(Interface->getName(),
122181ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier);
122281ad6265SDimitry Andric 
122381ad6265SDimitry Andric   // Build the inheritance part of the declaration.
122481ad6265SDimitry Andric   if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {
122581ad6265SDimitry Andric     SmallString<128> SuperUSR;
122681ad6265SDimitry Andric     index::generateUSRForDecl(SuperClass, SuperUSR);
122781ad6265SDimitry Andric     Fragments.append(" : ", DeclarationFragments::FragmentKind::Text)
122881ad6265SDimitry Andric         .append(SuperClass->getName(),
1229bdd1243dSDimitry Andric                 DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR,
1230bdd1243dSDimitry Andric                 SuperClass);
123181ad6265SDimitry Andric   }
123281ad6265SDimitry Andric 
123381ad6265SDimitry Andric   return Fragments;
123481ad6265SDimitry Andric }
123581ad6265SDimitry Andric 
123681ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
123781ad6265SDimitry Andric     const ObjCMethodDecl *Method) {
123881ad6265SDimitry Andric   DeclarationFragments Fragments, After;
123981ad6265SDimitry Andric   // Build the instance/class method indicator.
124081ad6265SDimitry Andric   if (Method->isClassMethod())
124181ad6265SDimitry Andric     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
124281ad6265SDimitry Andric   else if (Method->isInstanceMethod())
124381ad6265SDimitry Andric     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
124481ad6265SDimitry Andric 
124581ad6265SDimitry Andric   // Build the return type.
124681ad6265SDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text)
124781ad6265SDimitry Andric       .append(getFragmentsForType(Method->getReturnType(),
124881ad6265SDimitry Andric                                   Method->getASTContext(), After))
124981ad6265SDimitry Andric       .append(std::move(After))
125081ad6265SDimitry Andric       .append(")", DeclarationFragments::FragmentKind::Text);
125181ad6265SDimitry Andric 
125281ad6265SDimitry Andric   // Build the selector part.
125381ad6265SDimitry Andric   Selector Selector = Method->getSelector();
125481ad6265SDimitry Andric   if (Selector.getNumArgs() == 0)
125581ad6265SDimitry Andric     // For Objective-C methods that don't take arguments, the first (and only)
125681ad6265SDimitry Andric     // slot of the selector is the method name.
125781ad6265SDimitry Andric     Fragments.appendSpace().append(
125881ad6265SDimitry Andric         Selector.getNameForSlot(0),
125981ad6265SDimitry Andric         DeclarationFragments::FragmentKind::Identifier);
126081ad6265SDimitry Andric 
126181ad6265SDimitry Andric   // For Objective-C methods that take arguments, build the selector slots.
126281ad6265SDimitry Andric   for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {
126381ad6265SDimitry Andric     // Objective-C method selector parts are considered as identifiers instead
126481ad6265SDimitry Andric     // of "external parameters" as in Swift. This is because Objective-C method
126581ad6265SDimitry Andric     // symbols are referenced with the entire selector, instead of just the
126681ad6265SDimitry Andric     // method name in Swift.
126781ad6265SDimitry Andric     SmallString<32> ParamID(Selector.getNameForSlot(i));
126881ad6265SDimitry Andric     ParamID.append(":");
126981ad6265SDimitry Andric     Fragments.appendSpace().append(
127081ad6265SDimitry Andric         ParamID, DeclarationFragments::FragmentKind::Identifier);
127181ad6265SDimitry Andric 
127281ad6265SDimitry Andric     // Build the internal parameter.
127381ad6265SDimitry Andric     const ParmVarDecl *Param = Method->getParamDecl(i);
127481ad6265SDimitry Andric     Fragments.append(getFragmentsForParam(Param));
127581ad6265SDimitry Andric   }
127681ad6265SDimitry Andric 
127781ad6265SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
127881ad6265SDimitry Andric }
127981ad6265SDimitry Andric 
128081ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
128181ad6265SDimitry Andric     const ObjCPropertyDecl *Property) {
128281ad6265SDimitry Andric   DeclarationFragments Fragments, After;
128381ad6265SDimitry Andric 
128481ad6265SDimitry Andric   // Build the Objective-C property keyword.
128581ad6265SDimitry Andric   Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword);
128681ad6265SDimitry Andric 
128706c3fb27SDimitry Andric   const auto Attributes = Property->getPropertyAttributesAsWritten();
128881ad6265SDimitry Andric   // Build the attributes if there is any associated with the property.
128981ad6265SDimitry Andric   if (Attributes != ObjCPropertyAttribute::kind_noattr) {
129081ad6265SDimitry Andric     // No leading comma for the first attribute.
129181ad6265SDimitry Andric     bool First = true;
129281ad6265SDimitry Andric     Fragments.append(" (", DeclarationFragments::FragmentKind::Text);
129381ad6265SDimitry Andric     // Helper function to render the attribute.
129481ad6265SDimitry Andric     auto RenderAttribute =
129581ad6265SDimitry Andric         [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,
129681ad6265SDimitry Andric             StringRef Arg = "",
129781ad6265SDimitry Andric             DeclarationFragments::FragmentKind ArgKind =
129881ad6265SDimitry Andric                 DeclarationFragments::FragmentKind::Identifier) {
129981ad6265SDimitry Andric           // Check if the `Kind` attribute is set for this property.
130081ad6265SDimitry Andric           if ((Attributes & Kind) && !Spelling.empty()) {
130181ad6265SDimitry Andric             // Add a leading comma if this is not the first attribute rendered.
130281ad6265SDimitry Andric             if (!First)
130381ad6265SDimitry Andric               Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
130481ad6265SDimitry Andric             // Render the spelling of this attribute `Kind` as a keyword.
130581ad6265SDimitry Andric             Fragments.append(Spelling,
130681ad6265SDimitry Andric                              DeclarationFragments::FragmentKind::Keyword);
130781ad6265SDimitry Andric             // If this attribute takes in arguments (e.g. `getter=getterName`),
130881ad6265SDimitry Andric             // render the arguments.
130981ad6265SDimitry Andric             if (!Arg.empty())
131081ad6265SDimitry Andric               Fragments.append("=", DeclarationFragments::FragmentKind::Text)
131181ad6265SDimitry Andric                   .append(Arg, ArgKind);
131281ad6265SDimitry Andric             First = false;
131381ad6265SDimitry Andric           }
131481ad6265SDimitry Andric         };
131581ad6265SDimitry Andric 
131681ad6265SDimitry Andric     // Go through all possible Objective-C property attributes and render set
131781ad6265SDimitry Andric     // ones.
131881ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_class, "class");
131981ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");
132081ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");
132181ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");
132281ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");
132381ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");
132481ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");
132581ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");
132681ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");
132781ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained,
132881ad6265SDimitry Andric                     "unsafe_unretained");
132981ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");
133081ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");
133181ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",
133281ad6265SDimitry Andric                     Property->getGetterName().getAsString());
133381ad6265SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",
133481ad6265SDimitry Andric                     Property->getSetterName().getAsString());
133581ad6265SDimitry Andric 
133681ad6265SDimitry Andric     // Render nullability attributes.
133781ad6265SDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_nullability) {
133881ad6265SDimitry Andric       QualType Type = Property->getType();
133981ad6265SDimitry Andric       if (const auto Nullability =
134081ad6265SDimitry Andric               AttributedType::stripOuterNullability(Type)) {
134181ad6265SDimitry Andric         if (!First)
134281ad6265SDimitry Andric           Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
134381ad6265SDimitry Andric         if (*Nullability == NullabilityKind::Unspecified &&
134481ad6265SDimitry Andric             (Attributes & ObjCPropertyAttribute::kind_null_resettable))
134581ad6265SDimitry Andric           Fragments.append("null_resettable",
134681ad6265SDimitry Andric                            DeclarationFragments::FragmentKind::Keyword);
134781ad6265SDimitry Andric         else
134881ad6265SDimitry Andric           Fragments.append(
134981ad6265SDimitry Andric               getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),
135081ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Keyword);
135181ad6265SDimitry Andric         First = false;
135281ad6265SDimitry Andric       }
135381ad6265SDimitry Andric     }
135481ad6265SDimitry Andric 
135581ad6265SDimitry Andric     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
135681ad6265SDimitry Andric   }
135781ad6265SDimitry Andric 
1358*5f757f3fSDimitry Andric   Fragments.appendSpace();
1359*5f757f3fSDimitry Andric 
1360*5f757f3fSDimitry Andric   FunctionTypeLoc BlockLoc;
1361*5f757f3fSDimitry Andric   FunctionProtoTypeLoc BlockProtoLoc;
1362*5f757f3fSDimitry Andric   findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc,
1363*5f757f3fSDimitry Andric                           BlockProtoLoc);
1364*5f757f3fSDimitry Andric 
1365*5f757f3fSDimitry Andric   auto PropType = Property->getType();
1366*5f757f3fSDimitry Andric   if (!BlockLoc)
1367*5f757f3fSDimitry Andric     Fragments
1368*5f757f3fSDimitry Andric         .append(getFragmentsForType(PropType, Property->getASTContext(), After))
1369*5f757f3fSDimitry Andric         .appendSpace();
1370*5f757f3fSDimitry Andric   else
1371*5f757f3fSDimitry Andric     Fragments.append(
1372*5f757f3fSDimitry Andric         getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After));
1373*5f757f3fSDimitry Andric 
1374*5f757f3fSDimitry Andric   return Fragments
137581ad6265SDimitry Andric       .append(Property->getName(),
137681ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
1377*5f757f3fSDimitry Andric       .append(std::move(After))
1378*5f757f3fSDimitry Andric       .append(";", DeclarationFragments::FragmentKind::Text);
137981ad6265SDimitry Andric }
138081ad6265SDimitry Andric 
138181ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
138281ad6265SDimitry Andric     const ObjCProtocolDecl *Protocol) {
138381ad6265SDimitry Andric   DeclarationFragments Fragments;
138481ad6265SDimitry Andric   // Build basic protocol declaration.
138581ad6265SDimitry Andric   Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword)
138681ad6265SDimitry Andric       .appendSpace()
138781ad6265SDimitry Andric       .append(Protocol->getName(),
138881ad6265SDimitry Andric               DeclarationFragments::FragmentKind::Identifier);
138981ad6265SDimitry Andric 
139081ad6265SDimitry Andric   // If this protocol conforms to other protocols, build the conformance list.
139181ad6265SDimitry Andric   if (!Protocol->protocols().empty()) {
139281ad6265SDimitry Andric     Fragments.append(" <", DeclarationFragments::FragmentKind::Text);
139381ad6265SDimitry Andric     for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();
139481ad6265SDimitry Andric          It != Protocol->protocol_end(); It++) {
139581ad6265SDimitry Andric       // Add a leading comma if this is not the first protocol rendered.
139681ad6265SDimitry Andric       if (It != Protocol->protocol_begin())
139781ad6265SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
139881ad6265SDimitry Andric 
139981ad6265SDimitry Andric       SmallString<128> USR;
140081ad6265SDimitry Andric       index::generateUSRForDecl(*It, USR);
140181ad6265SDimitry Andric       Fragments.append((*It)->getName(),
1402bdd1243dSDimitry Andric                        DeclarationFragments::FragmentKind::TypeIdentifier, USR,
1403bdd1243dSDimitry Andric                        *It);
140481ad6265SDimitry Andric     }
140581ad6265SDimitry Andric     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
140681ad6265SDimitry Andric   }
140781ad6265SDimitry Andric 
140881ad6265SDimitry Andric   return Fragments;
140981ad6265SDimitry Andric }
141081ad6265SDimitry Andric 
141181ad6265SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
141281ad6265SDimitry Andric     const TypedefNameDecl *Decl) {
141381ad6265SDimitry Andric   DeclarationFragments Fragments, After;
141481ad6265SDimitry Andric   Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword)
141581ad6265SDimitry Andric       .appendSpace()
141681ad6265SDimitry Andric       .append(getFragmentsForType(Decl->getUnderlyingType(),
141781ad6265SDimitry Andric                                   Decl->getASTContext(), After))
141881ad6265SDimitry Andric       .append(std::move(After))
141981ad6265SDimitry Andric       .appendSpace()
142081ad6265SDimitry Andric       .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
142181ad6265SDimitry Andric 
142206c3fb27SDimitry Andric   return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
142381ad6265SDimitry Andric }
142481ad6265SDimitry Andric 
142581ad6265SDimitry Andric // Instantiate template for FunctionDecl.
142681ad6265SDimitry Andric template FunctionSignature
142781ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);
142881ad6265SDimitry Andric 
142981ad6265SDimitry Andric // Instantiate template for ObjCMethodDecl.
143081ad6265SDimitry Andric template FunctionSignature
143181ad6265SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);
143281ad6265SDimitry Andric 
143381ad6265SDimitry Andric // Subheading of a symbol defaults to its name.
143481ad6265SDimitry Andric DeclarationFragments
143581ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
143681ad6265SDimitry Andric   DeclarationFragments Fragments;
1437*5f757f3fSDimitry Andric   if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))
1438*5f757f3fSDimitry Andric     Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(),
1439*5f757f3fSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
1440*5f757f3fSDimitry Andric   else if (isa<CXXConversionDecl>(Decl)) {
1441*5f757f3fSDimitry Andric     Fragments.append(
1442*5f757f3fSDimitry Andric         cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(),
1443*5f757f3fSDimitry Andric         DeclarationFragments::FragmentKind::Identifier);
1444*5f757f3fSDimitry Andric   } else if (isa<CXXMethodDecl>(Decl) &&
1445*5f757f3fSDimitry Andric              cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) {
1446*5f757f3fSDimitry Andric     Fragments.append(Decl->getNameAsString(),
1447*5f757f3fSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
1448*5f757f3fSDimitry Andric   } else if (!Decl->getName().empty())
144981ad6265SDimitry Andric     Fragments.append(Decl->getName(),
145081ad6265SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
145181ad6265SDimitry Andric   return Fragments;
145281ad6265SDimitry Andric }
145381ad6265SDimitry Andric 
145481ad6265SDimitry Andric // Subheading of an Objective-C method is a `+` or `-` sign indicating whether
145581ad6265SDimitry Andric // it's a class method or an instance method, followed by the selector name.
145681ad6265SDimitry Andric DeclarationFragments
145781ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) {
145881ad6265SDimitry Andric   DeclarationFragments Fragments;
145981ad6265SDimitry Andric   if (Method->isClassMethod())
146081ad6265SDimitry Andric     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
146181ad6265SDimitry Andric   else if (Method->isInstanceMethod())
146281ad6265SDimitry Andric     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
146381ad6265SDimitry Andric 
146481ad6265SDimitry Andric   return Fragments.append(Method->getNameAsString(),
146581ad6265SDimitry Andric                           DeclarationFragments::FragmentKind::Identifier);
146681ad6265SDimitry Andric }
146781ad6265SDimitry Andric 
146881ad6265SDimitry Andric // Subheading of a symbol defaults to its name.
146981ad6265SDimitry Andric DeclarationFragments
147081ad6265SDimitry Andric DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) {
147181ad6265SDimitry Andric   DeclarationFragments Fragments;
147281ad6265SDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
147381ad6265SDimitry Andric   return Fragments;
147481ad6265SDimitry Andric }
1475