xref: /src/contrib/llvm-project/clang/lib/ExtractAPI/DeclarationFragments.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1145449b1SDimitry Andric //===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===//
2145449b1SDimitry Andric //
3145449b1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4145449b1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5145449b1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6145449b1SDimitry Andric //
7145449b1SDimitry Andric //===----------------------------------------------------------------------===//
8145449b1SDimitry Andric ///
9145449b1SDimitry Andric /// \file
10145449b1SDimitry Andric /// This file implements Declaration Fragments related classes.
11145449b1SDimitry Andric ///
12145449b1SDimitry Andric //===----------------------------------------------------------------------===//
13145449b1SDimitry Andric 
14145449b1SDimitry Andric #include "clang/ExtractAPI/DeclarationFragments.h"
15ac9a064cSDimitry Andric #include "clang/AST/ASTFwd.h"
16b1c73532SDimitry Andric #include "clang/AST/Decl.h"
17b1c73532SDimitry Andric #include "clang/AST/DeclCXX.h"
18ac9a064cSDimitry Andric #include "clang/AST/TemplateBase.h"
19ac9a064cSDimitry Andric #include "clang/AST/TemplateName.h"
20b1c73532SDimitry Andric #include "clang/AST/Type.h"
21b1c73532SDimitry Andric #include "clang/AST/TypeLoc.h"
227fa27ce4SDimitry Andric #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
23145449b1SDimitry Andric #include "clang/Index/USRGeneration.h"
24145449b1SDimitry Andric #include "llvm/ADT/StringSwitch.h"
25ac9a064cSDimitry Andric #include "llvm/Support/ErrorHandling.h"
26ac9a064cSDimitry Andric #include "llvm/Support/raw_ostream.h"
27ac9a064cSDimitry Andric #include <optional>
28145449b1SDimitry Andric 
29145449b1SDimitry Andric using namespace clang::extractapi;
30145449b1SDimitry Andric using namespace llvm;
31145449b1SDimitry Andric 
32b1c73532SDimitry Andric namespace {
33b1c73532SDimitry Andric 
findTypeLocForBlockDecl(const clang::TypeSourceInfo * TSInfo,clang::FunctionTypeLoc & Block,clang::FunctionProtoTypeLoc & BlockProto)34b1c73532SDimitry Andric void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
35b1c73532SDimitry Andric                              clang::FunctionTypeLoc &Block,
36b1c73532SDimitry Andric                              clang::FunctionProtoTypeLoc &BlockProto) {
37b1c73532SDimitry Andric   if (!TSInfo)
38b1c73532SDimitry Andric     return;
39b1c73532SDimitry Andric 
40b1c73532SDimitry Andric   clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
41b1c73532SDimitry Andric   while (true) {
42b1c73532SDimitry Andric     // Look through qualified types
43b1c73532SDimitry Andric     if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) {
44b1c73532SDimitry Andric       TL = QualifiedTL.getUnqualifiedLoc();
45b1c73532SDimitry Andric       continue;
46b1c73532SDimitry Andric     }
47b1c73532SDimitry Andric 
48b1c73532SDimitry Andric     if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) {
49b1c73532SDimitry Andric       TL = AttrTL.getModifiedLoc();
50b1c73532SDimitry Andric       continue;
51b1c73532SDimitry Andric     }
52b1c73532SDimitry Andric 
53b1c73532SDimitry Andric     // Try to get the function prototype behind the block pointer type,
54b1c73532SDimitry Andric     // then we're done.
55b1c73532SDimitry Andric     if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) {
56b1c73532SDimitry Andric       TL = BlockPtr.getPointeeLoc().IgnoreParens();
57b1c73532SDimitry Andric       Block = TL.getAs<clang::FunctionTypeLoc>();
58b1c73532SDimitry Andric       BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>();
59b1c73532SDimitry Andric     }
60b1c73532SDimitry Andric     break;
61b1c73532SDimitry Andric   }
62b1c73532SDimitry Andric }
63b1c73532SDimitry Andric 
64b1c73532SDimitry Andric } // namespace
65b1c73532SDimitry Andric 
66ac9a064cSDimitry Andric DeclarationFragments &
appendUnduplicatedTextCharacter(char Character)67ac9a064cSDimitry Andric DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {
68145449b1SDimitry Andric   if (!Fragments.empty()) {
69145449b1SDimitry Andric     Fragment &Last = Fragments.back();
70145449b1SDimitry Andric     if (Last.Kind == FragmentKind::Text) {
71145449b1SDimitry Andric       // Merge the extra space into the last fragment if the last fragment is
72145449b1SDimitry Andric       // also text.
73ac9a064cSDimitry Andric       if (Last.Spelling.back() != Character) { // avoid duplicates at end
74ac9a064cSDimitry Andric         Last.Spelling.push_back(Character);
75145449b1SDimitry Andric       }
76145449b1SDimitry Andric     } else {
77145449b1SDimitry Andric       append("", FragmentKind::Text);
78ac9a064cSDimitry Andric       Fragments.back().Spelling.push_back(Character);
79145449b1SDimitry Andric     }
80145449b1SDimitry Andric   }
81145449b1SDimitry Andric 
82145449b1SDimitry Andric   return *this;
83145449b1SDimitry Andric }
84145449b1SDimitry Andric 
appendSpace()85ac9a064cSDimitry Andric DeclarationFragments &DeclarationFragments::appendSpace() {
86ac9a064cSDimitry Andric   return appendUnduplicatedTextCharacter(' ');
87ac9a064cSDimitry Andric }
88ac9a064cSDimitry Andric 
appendSemicolon()89ac9a064cSDimitry Andric DeclarationFragments &DeclarationFragments::appendSemicolon() {
90ac9a064cSDimitry Andric   return appendUnduplicatedTextCharacter(';');
91ac9a064cSDimitry Andric }
92ac9a064cSDimitry Andric 
removeTrailingSemicolon()93ac9a064cSDimitry Andric DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() {
94ac9a064cSDimitry Andric   if (Fragments.empty())
95ac9a064cSDimitry Andric     return *this;
96ac9a064cSDimitry Andric 
97ac9a064cSDimitry Andric   Fragment &Last = Fragments.back();
98ac9a064cSDimitry Andric   if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';')
99ac9a064cSDimitry Andric     Last.Spelling.pop_back();
100ac9a064cSDimitry Andric 
101ac9a064cSDimitry Andric   return *this;
102ac9a064cSDimitry Andric }
103ac9a064cSDimitry Andric 
getFragmentKindString(DeclarationFragments::FragmentKind Kind)104145449b1SDimitry Andric StringRef DeclarationFragments::getFragmentKindString(
105145449b1SDimitry Andric     DeclarationFragments::FragmentKind Kind) {
106145449b1SDimitry Andric   switch (Kind) {
107145449b1SDimitry Andric   case DeclarationFragments::FragmentKind::None:
108145449b1SDimitry Andric     return "none";
109145449b1SDimitry Andric   case DeclarationFragments::FragmentKind::Keyword:
110145449b1SDimitry Andric     return "keyword";
111145449b1SDimitry Andric   case DeclarationFragments::FragmentKind::Attribute:
112145449b1SDimitry Andric     return "attribute";
113145449b1SDimitry Andric   case DeclarationFragments::FragmentKind::NumberLiteral:
114145449b1SDimitry Andric     return "number";
115145449b1SDimitry Andric   case DeclarationFragments::FragmentKind::StringLiteral:
116145449b1SDimitry Andric     return "string";
117145449b1SDimitry Andric   case DeclarationFragments::FragmentKind::Identifier:
118145449b1SDimitry Andric     return "identifier";
119145449b1SDimitry Andric   case DeclarationFragments::FragmentKind::TypeIdentifier:
120145449b1SDimitry Andric     return "typeIdentifier";
121145449b1SDimitry Andric   case DeclarationFragments::FragmentKind::GenericParameter:
122145449b1SDimitry Andric     return "genericParameter";
123145449b1SDimitry Andric   case DeclarationFragments::FragmentKind::ExternalParam:
124145449b1SDimitry Andric     return "externalParam";
125145449b1SDimitry Andric   case DeclarationFragments::FragmentKind::InternalParam:
126145449b1SDimitry Andric     return "internalParam";
127145449b1SDimitry Andric   case DeclarationFragments::FragmentKind::Text:
128145449b1SDimitry Andric     return "text";
129145449b1SDimitry Andric   }
130145449b1SDimitry Andric 
131145449b1SDimitry Andric   llvm_unreachable("Unhandled FragmentKind");
132145449b1SDimitry Andric }
133145449b1SDimitry Andric 
134145449b1SDimitry Andric DeclarationFragments::FragmentKind
parseFragmentKindFromString(StringRef S)135145449b1SDimitry Andric DeclarationFragments::parseFragmentKindFromString(StringRef S) {
136145449b1SDimitry Andric   return llvm::StringSwitch<FragmentKind>(S)
137145449b1SDimitry Andric       .Case("keyword", DeclarationFragments::FragmentKind::Keyword)
138145449b1SDimitry Andric       .Case("attribute", DeclarationFragments::FragmentKind::Attribute)
139145449b1SDimitry Andric       .Case("number", DeclarationFragments::FragmentKind::NumberLiteral)
140145449b1SDimitry Andric       .Case("string", DeclarationFragments::FragmentKind::StringLiteral)
141145449b1SDimitry Andric       .Case("identifier", DeclarationFragments::FragmentKind::Identifier)
142145449b1SDimitry Andric       .Case("typeIdentifier",
143145449b1SDimitry Andric             DeclarationFragments::FragmentKind::TypeIdentifier)
144145449b1SDimitry Andric       .Case("genericParameter",
145145449b1SDimitry Andric             DeclarationFragments::FragmentKind::GenericParameter)
146145449b1SDimitry Andric       .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam)
147145449b1SDimitry Andric       .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam)
148145449b1SDimitry Andric       .Case("text", DeclarationFragments::FragmentKind::Text)
149145449b1SDimitry Andric       .Default(DeclarationFragments::FragmentKind::None);
150145449b1SDimitry Andric }
151145449b1SDimitry Andric 
getExceptionSpecificationString(ExceptionSpecificationType ExceptionSpec)152b1c73532SDimitry Andric DeclarationFragments DeclarationFragments::getExceptionSpecificationString(
153b1c73532SDimitry Andric     ExceptionSpecificationType ExceptionSpec) {
154b1c73532SDimitry Andric   DeclarationFragments Fragments;
155b1c73532SDimitry Andric   switch (ExceptionSpec) {
156b1c73532SDimitry Andric   case ExceptionSpecificationType::EST_None:
157b1c73532SDimitry Andric     return Fragments;
158b1c73532SDimitry Andric   case ExceptionSpecificationType::EST_DynamicNone:
159b1c73532SDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
160b1c73532SDimitry Andric         .append("throw", DeclarationFragments::FragmentKind::Keyword)
161b1c73532SDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text)
162b1c73532SDimitry Andric         .append(")", DeclarationFragments::FragmentKind::Text);
163b1c73532SDimitry Andric   case ExceptionSpecificationType::EST_Dynamic:
164b1c73532SDimitry Andric     // FIXME: throw(int), get types of inner expression
165b1c73532SDimitry Andric     return Fragments;
166b1c73532SDimitry Andric   case ExceptionSpecificationType::EST_BasicNoexcept:
167b1c73532SDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
168b1c73532SDimitry Andric         .append("noexcept", DeclarationFragments::FragmentKind::Keyword);
169b1c73532SDimitry Andric   case ExceptionSpecificationType::EST_DependentNoexcept:
170b1c73532SDimitry Andric     // FIXME: throw(conditional-expression), get expression
171b1c73532SDimitry Andric     break;
172b1c73532SDimitry Andric   case ExceptionSpecificationType::EST_NoexceptFalse:
173b1c73532SDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
174b1c73532SDimitry Andric         .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
175b1c73532SDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text)
176b1c73532SDimitry Andric         .append("false", DeclarationFragments::FragmentKind::Keyword)
177b1c73532SDimitry Andric         .append(")", DeclarationFragments::FragmentKind::Text);
178b1c73532SDimitry Andric   case ExceptionSpecificationType::EST_NoexceptTrue:
179b1c73532SDimitry Andric     return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
180b1c73532SDimitry Andric         .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
181b1c73532SDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text)
182b1c73532SDimitry Andric         .append("true", DeclarationFragments::FragmentKind::Keyword)
183b1c73532SDimitry Andric         .append(")", DeclarationFragments::FragmentKind::Text);
184b1c73532SDimitry Andric   default:
185b1c73532SDimitry Andric     return Fragments;
186b1c73532SDimitry Andric   }
187b1c73532SDimitry Andric 
188b1c73532SDimitry Andric   llvm_unreachable("Unhandled exception specification");
189b1c73532SDimitry Andric }
190b1c73532SDimitry Andric 
191b1c73532SDimitry Andric DeclarationFragments
getStructureTypeFragment(const RecordDecl * Record)192b1c73532SDimitry Andric DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {
193b1c73532SDimitry Andric   DeclarationFragments Fragments;
194b1c73532SDimitry Andric   if (Record->isStruct())
195b1c73532SDimitry Andric     Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
196b1c73532SDimitry Andric   else if (Record->isUnion())
197b1c73532SDimitry Andric     Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
198b1c73532SDimitry Andric   else
199b1c73532SDimitry Andric     Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
200b1c73532SDimitry Andric 
201b1c73532SDimitry Andric   return Fragments;
202b1c73532SDimitry Andric }
203b1c73532SDimitry Andric 
204145449b1SDimitry Andric // NNS stores C++ nested name specifiers, which are prefixes to qualified names.
205145449b1SDimitry Andric // Build declaration fragments for NNS recursively so that we have the USR for
206145449b1SDimitry Andric // every part in a qualified name, and also leaves the actual underlying type
207145449b1SDimitry Andric // cleaner for its own fragment.
208145449b1SDimitry Andric DeclarationFragments
getFragmentsForNNS(const NestedNameSpecifier * NNS,ASTContext & Context,DeclarationFragments & After)209145449b1SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS,
210145449b1SDimitry Andric                                                 ASTContext &Context,
211145449b1SDimitry Andric                                                 DeclarationFragments &After) {
212145449b1SDimitry Andric   DeclarationFragments Fragments;
213145449b1SDimitry Andric   if (NNS->getPrefix())
214145449b1SDimitry Andric     Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After));
215145449b1SDimitry Andric 
216145449b1SDimitry Andric   switch (NNS->getKind()) {
217145449b1SDimitry Andric   case NestedNameSpecifier::Identifier:
218145449b1SDimitry Andric     Fragments.append(NNS->getAsIdentifier()->getName(),
219145449b1SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
220145449b1SDimitry Andric     break;
221145449b1SDimitry Andric 
222145449b1SDimitry Andric   case NestedNameSpecifier::Namespace: {
223145449b1SDimitry Andric     const NamespaceDecl *NS = NNS->getAsNamespace();
224145449b1SDimitry Andric     if (NS->isAnonymousNamespace())
225145449b1SDimitry Andric       return Fragments;
226145449b1SDimitry Andric     SmallString<128> USR;
227145449b1SDimitry Andric     index::generateUSRForDecl(NS, USR);
228145449b1SDimitry Andric     Fragments.append(NS->getName(),
229e3b55780SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier, USR, NS);
230145449b1SDimitry Andric     break;
231145449b1SDimitry Andric   }
232145449b1SDimitry Andric 
233145449b1SDimitry Andric   case NestedNameSpecifier::NamespaceAlias: {
234145449b1SDimitry Andric     const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias();
235145449b1SDimitry Andric     SmallString<128> USR;
236145449b1SDimitry Andric     index::generateUSRForDecl(Alias, USR);
237145449b1SDimitry Andric     Fragments.append(Alias->getName(),
238e3b55780SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier, USR,
239e3b55780SDimitry Andric                      Alias);
240145449b1SDimitry Andric     break;
241145449b1SDimitry Andric   }
242145449b1SDimitry Andric 
243145449b1SDimitry Andric   case NestedNameSpecifier::Global:
244145449b1SDimitry Andric     // The global specifier `::` at the beginning. No stored value.
245145449b1SDimitry Andric     break;
246145449b1SDimitry Andric 
247145449b1SDimitry Andric   case NestedNameSpecifier::Super:
248145449b1SDimitry Andric     // Microsoft's `__super` specifier.
249145449b1SDimitry Andric     Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);
250145449b1SDimitry Andric     break;
251145449b1SDimitry Andric 
252145449b1SDimitry Andric   case NestedNameSpecifier::TypeSpecWithTemplate:
253145449b1SDimitry Andric     // A type prefixed by the `template` keyword.
254145449b1SDimitry Andric     Fragments.append("template", DeclarationFragments::FragmentKind::Keyword);
255145449b1SDimitry Andric     Fragments.appendSpace();
256145449b1SDimitry Andric     // Fallthrough after adding the keyword to handle the actual type.
257e3b55780SDimitry Andric     [[fallthrough]];
258145449b1SDimitry Andric 
259145449b1SDimitry Andric   case NestedNameSpecifier::TypeSpec: {
260145449b1SDimitry Andric     const Type *T = NNS->getAsType();
261145449b1SDimitry Andric     // FIXME: Handle C++ template specialization type
262145449b1SDimitry Andric     Fragments.append(getFragmentsForType(T, Context, After));
263145449b1SDimitry Andric     break;
264145449b1SDimitry Andric   }
265145449b1SDimitry Andric   }
266145449b1SDimitry Andric 
267145449b1SDimitry Andric   // Add the separator text `::` for this segment.
268145449b1SDimitry Andric   return Fragments.append("::", DeclarationFragments::FragmentKind::Text);
269145449b1SDimitry Andric }
270145449b1SDimitry Andric 
271145449b1SDimitry Andric // Recursively build the declaration fragments for an underlying `Type` with
272145449b1SDimitry Andric // qualifiers removed.
getFragmentsForType(const Type * T,ASTContext & Context,DeclarationFragments & After)273145449b1SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
274145449b1SDimitry Andric     const Type *T, ASTContext &Context, DeclarationFragments &After) {
275145449b1SDimitry Andric   assert(T && "invalid type");
276145449b1SDimitry Andric 
277145449b1SDimitry Andric   DeclarationFragments Fragments;
278145449b1SDimitry Andric 
2794df029ccSDimitry Andric   // An ElaboratedType is a sugar for types that are referred to using an
2804df029ccSDimitry Andric   // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
2814df029ccSDimitry Andric   // qualified name, e.g., `N::M::type`, or both.
2824df029ccSDimitry Andric   if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
2834df029ccSDimitry Andric     ElaboratedTypeKeyword Keyword = ET->getKeyword();
2844df029ccSDimitry Andric     if (Keyword != ElaboratedTypeKeyword::None) {
2854df029ccSDimitry Andric       Fragments
2864df029ccSDimitry Andric           .append(ElaboratedType::getKeywordName(Keyword),
2874df029ccSDimitry Andric                   DeclarationFragments::FragmentKind::Keyword)
2884df029ccSDimitry Andric           .appendSpace();
2894df029ccSDimitry Andric     }
2904df029ccSDimitry Andric 
2914df029ccSDimitry Andric     if (const NestedNameSpecifier *NNS = ET->getQualifier())
2924df029ccSDimitry Andric       Fragments.append(getFragmentsForNNS(NNS, Context, After));
2934df029ccSDimitry Andric 
2944df029ccSDimitry Andric     // After handling the elaborated keyword or qualified name, build
2954df029ccSDimitry Andric     // declaration fragments for the desugared underlying type.
2964df029ccSDimitry Andric     return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
2974df029ccSDimitry Andric   }
2984df029ccSDimitry Andric 
2994df029ccSDimitry Andric   // If the type is a typedefed type, get the underlying TypedefNameDecl for a
3004df029ccSDimitry Andric   // direct reference to the typedef instead of the wrapped type.
3014df029ccSDimitry Andric 
3024df029ccSDimitry Andric   // 'id' type is a typedef for an ObjCObjectPointerType
3034df029ccSDimitry Andric   //  we treat it as a typedef
3044df029ccSDimitry Andric   if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
3054df029ccSDimitry Andric     const TypedefNameDecl *Decl = TypedefTy->getDecl();
3064df029ccSDimitry Andric     TypedefUnderlyingTypeResolver TypedefResolver(Context);
3074df029ccSDimitry Andric     std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));
3084df029ccSDimitry Andric 
3094df029ccSDimitry Andric     if (T->isObjCIdType()) {
3104df029ccSDimitry Andric       return Fragments.append(Decl->getName(),
3114df029ccSDimitry Andric                               DeclarationFragments::FragmentKind::Keyword);
3124df029ccSDimitry Andric     }
3134df029ccSDimitry Andric 
3144df029ccSDimitry Andric     return Fragments.append(
3154df029ccSDimitry Andric         Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,
3164df029ccSDimitry Andric         USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));
3174df029ccSDimitry Andric   }
3184df029ccSDimitry Andric 
319145449b1SDimitry Andric   // Declaration fragments of a pointer type is the declaration fragments of
3207fa27ce4SDimitry Andric   // the pointee type followed by a `*`,
321b1c73532SDimitry Andric   if (T->isPointerType() && !T->isFunctionPointerType())
322145449b1SDimitry Andric     return Fragments
323145449b1SDimitry Andric         .append(getFragmentsForType(T->getPointeeType(), Context, After))
324145449b1SDimitry Andric         .append(" *", DeclarationFragments::FragmentKind::Text);
3257fa27ce4SDimitry Andric 
3267fa27ce4SDimitry Andric   // For Objective-C `id` and `Class` pointers
3277fa27ce4SDimitry Andric   // we do not spell out the `*`.
3287fa27ce4SDimitry Andric   if (T->isObjCObjectPointerType() &&
3297fa27ce4SDimitry Andric       !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {
3307fa27ce4SDimitry Andric 
3317fa27ce4SDimitry Andric     Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After));
3327fa27ce4SDimitry Andric 
3337fa27ce4SDimitry Andric     // id<protocol> is an qualified id type
3347fa27ce4SDimitry Andric     // id<protocol>* is not an qualified id type
3357fa27ce4SDimitry Andric     if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {
3367fa27ce4SDimitry Andric       Fragments.append(" *", DeclarationFragments::FragmentKind::Text);
3377fa27ce4SDimitry Andric     }
3387fa27ce4SDimitry Andric 
3397fa27ce4SDimitry Andric     return Fragments;
340145449b1SDimitry Andric   }
341145449b1SDimitry Andric 
342145449b1SDimitry Andric   // Declaration fragments of a lvalue reference type is the declaration
343145449b1SDimitry Andric   // fragments of the underlying type followed by a `&`.
344145449b1SDimitry Andric   if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T))
345145449b1SDimitry Andric     return Fragments
346145449b1SDimitry Andric         .append(
347145449b1SDimitry Andric             getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
348145449b1SDimitry Andric         .append(" &", DeclarationFragments::FragmentKind::Text);
349145449b1SDimitry Andric 
350145449b1SDimitry Andric   // Declaration fragments of a rvalue reference type is the declaration
351145449b1SDimitry Andric   // fragments of the underlying type followed by a `&&`.
352145449b1SDimitry Andric   if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T))
353145449b1SDimitry Andric     return Fragments
354145449b1SDimitry Andric         .append(
355145449b1SDimitry Andric             getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
356145449b1SDimitry Andric         .append(" &&", DeclarationFragments::FragmentKind::Text);
357145449b1SDimitry Andric 
358145449b1SDimitry Andric   // Declaration fragments of an array-typed variable have two parts:
359145449b1SDimitry Andric   // 1. the element type of the array that appears before the variable name;
360145449b1SDimitry Andric   // 2. array brackets `[(0-9)?]` that appear after the variable name.
361145449b1SDimitry Andric   if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) {
362145449b1SDimitry Andric     // Build the "after" part first because the inner element type might also
363145449b1SDimitry Andric     // be an array-type. For example `int matrix[3][4]` which has a type of
364145449b1SDimitry Andric     // "(array 3 of (array 4 of ints))."
365145449b1SDimitry Andric     // Push the array size part first to make sure they are in the right order.
366145449b1SDimitry Andric     After.append("[", DeclarationFragments::FragmentKind::Text);
367145449b1SDimitry Andric 
368145449b1SDimitry Andric     switch (AT->getSizeModifier()) {
369b1c73532SDimitry Andric     case ArraySizeModifier::Normal:
370145449b1SDimitry Andric       break;
371b1c73532SDimitry Andric     case ArraySizeModifier::Static:
372145449b1SDimitry Andric       Fragments.append("static", DeclarationFragments::FragmentKind::Keyword);
373145449b1SDimitry Andric       break;
374b1c73532SDimitry Andric     case ArraySizeModifier::Star:
375145449b1SDimitry Andric       Fragments.append("*", DeclarationFragments::FragmentKind::Text);
376145449b1SDimitry Andric       break;
377145449b1SDimitry Andric     }
378145449b1SDimitry Andric 
379145449b1SDimitry Andric     if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
380145449b1SDimitry Andric       // FIXME: right now this would evaluate any expressions/macros written in
381145449b1SDimitry Andric       // the original source to concrete values. For example
382145449b1SDimitry Andric       // `int nums[MAX]` -> `int nums[100]`
383145449b1SDimitry Andric       // `char *str[5 + 1]` -> `char *str[6]`
384145449b1SDimitry Andric       SmallString<128> Size;
385145449b1SDimitry Andric       CAT->getSize().toStringUnsigned(Size);
386145449b1SDimitry Andric       After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral);
387145449b1SDimitry Andric     }
388145449b1SDimitry Andric 
389145449b1SDimitry Andric     After.append("]", DeclarationFragments::FragmentKind::Text);
390145449b1SDimitry Andric 
391145449b1SDimitry Andric     return Fragments.append(
392145449b1SDimitry Andric         getFragmentsForType(AT->getElementType(), Context, After));
393145449b1SDimitry Andric   }
394145449b1SDimitry Andric 
395ac9a064cSDimitry Andric   if (const TemplateSpecializationType *TemplSpecTy =
396ac9a064cSDimitry Andric           dyn_cast<TemplateSpecializationType>(T)) {
397ac9a064cSDimitry Andric     const auto TemplName = TemplSpecTy->getTemplateName();
398ac9a064cSDimitry Andric     std::string Str;
399ac9a064cSDimitry Andric     raw_string_ostream Stream(Str);
400ac9a064cSDimitry Andric     TemplName.print(Stream, Context.getPrintingPolicy(),
401ac9a064cSDimitry Andric                     TemplateName::Qualified::AsWritten);
402ac9a064cSDimitry Andric     SmallString<64> USR("");
403ac9a064cSDimitry Andric     if (const auto *TemplDecl = TemplName.getAsTemplateDecl())
404ac9a064cSDimitry Andric       index::generateUSRForDecl(TemplDecl, USR);
405ac9a064cSDimitry Andric 
406ac9a064cSDimitry Andric     return Fragments
407ac9a064cSDimitry Andric         .append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, USR)
408ac9a064cSDimitry Andric         .append("<", DeclarationFragments::FragmentKind::Text)
409ac9a064cSDimitry Andric         .append(getFragmentsForTemplateArguments(
410ac9a064cSDimitry Andric             TemplSpecTy->template_arguments(), Context, std::nullopt))
411ac9a064cSDimitry Andric         .append(">", DeclarationFragments::FragmentKind::Text);
412ac9a064cSDimitry Andric   }
413ac9a064cSDimitry Andric 
4147fa27ce4SDimitry Andric   // Everything we care about has been handled now, reduce to the canonical
4157fa27ce4SDimitry Andric   // unqualified base type.
4167fa27ce4SDimitry Andric   QualType Base = T->getCanonicalTypeUnqualified();
4177fa27ce4SDimitry Andric 
418145449b1SDimitry Andric   // If the base type is a TagType (struct/interface/union/class/enum), let's
419145449b1SDimitry Andric   // get the underlying Decl for better names and USRs.
420145449b1SDimitry Andric   if (const TagType *TagTy = dyn_cast<TagType>(Base)) {
421145449b1SDimitry Andric     const TagDecl *Decl = TagTy->getDecl();
422145449b1SDimitry Andric     // Anonymous decl, skip this fragment.
423145449b1SDimitry Andric     if (Decl->getName().empty())
424ac9a064cSDimitry Andric       return Fragments.append("{ ... }",
425ac9a064cSDimitry Andric                               DeclarationFragments::FragmentKind::Text);
426145449b1SDimitry Andric     SmallString<128> TagUSR;
427145449b1SDimitry Andric     clang::index::generateUSRForDecl(Decl, TagUSR);
428145449b1SDimitry Andric     return Fragments.append(Decl->getName(),
429145449b1SDimitry Andric                             DeclarationFragments::FragmentKind::TypeIdentifier,
430e3b55780SDimitry Andric                             TagUSR, Decl);
431145449b1SDimitry Andric   }
432145449b1SDimitry Andric 
433145449b1SDimitry Andric   // If the base type is an ObjCInterfaceType, use the underlying
434145449b1SDimitry Andric   // ObjCInterfaceDecl for the true USR.
435145449b1SDimitry Andric   if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
436145449b1SDimitry Andric     const auto *Decl = ObjCIT->getDecl();
437145449b1SDimitry Andric     SmallString<128> USR;
438145449b1SDimitry Andric     index::generateUSRForDecl(Decl, USR);
439145449b1SDimitry Andric     return Fragments.append(Decl->getName(),
440145449b1SDimitry Andric                             DeclarationFragments::FragmentKind::TypeIdentifier,
441e3b55780SDimitry Andric                             USR, Decl);
442145449b1SDimitry Andric   }
443145449b1SDimitry Andric 
444145449b1SDimitry Andric   // Default fragment builder for other kinds of types (BuiltinType etc.)
445145449b1SDimitry Andric   SmallString<128> USR;
446145449b1SDimitry Andric   clang::index::generateUSRForType(Base, Context, USR);
447145449b1SDimitry Andric   Fragments.append(Base.getAsString(),
448145449b1SDimitry Andric                    DeclarationFragments::FragmentKind::TypeIdentifier, USR);
449145449b1SDimitry Andric 
450145449b1SDimitry Andric   return Fragments;
451145449b1SDimitry Andric }
452145449b1SDimitry Andric 
453145449b1SDimitry Andric DeclarationFragments
getFragmentsForQualifiers(const Qualifiers Quals)454145449b1SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) {
455145449b1SDimitry Andric   DeclarationFragments Fragments;
456145449b1SDimitry Andric   if (Quals.hasConst())
457145449b1SDimitry Andric     Fragments.append("const", DeclarationFragments::FragmentKind::Keyword);
458145449b1SDimitry Andric   if (Quals.hasVolatile())
459145449b1SDimitry Andric     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword);
460145449b1SDimitry Andric   if (Quals.hasRestrict())
461145449b1SDimitry Andric     Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword);
462145449b1SDimitry Andric 
463145449b1SDimitry Andric   return Fragments;
464145449b1SDimitry Andric }
465145449b1SDimitry Andric 
getFragmentsForType(const QualType QT,ASTContext & Context,DeclarationFragments & After)466145449b1SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
467145449b1SDimitry Andric     const QualType QT, ASTContext &Context, DeclarationFragments &After) {
468145449b1SDimitry Andric   assert(!QT.isNull() && "invalid type");
469145449b1SDimitry Andric 
470145449b1SDimitry Andric   if (const ParenType *PT = dyn_cast<ParenType>(QT)) {
471145449b1SDimitry Andric     After.append(")", DeclarationFragments::FragmentKind::Text);
472145449b1SDimitry Andric     return getFragmentsForType(PT->getInnerType(), Context, After)
473145449b1SDimitry Andric         .append("(", DeclarationFragments::FragmentKind::Text);
474145449b1SDimitry Andric   }
475145449b1SDimitry Andric 
476145449b1SDimitry Andric   const SplitQualType SQT = QT.split();
477145449b1SDimitry Andric   DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals),
478145449b1SDimitry Andric                        TypeFragments =
479145449b1SDimitry Andric                            getFragmentsForType(SQT.Ty, Context, After);
480b1c73532SDimitry Andric   if (QT.getAsString() == "_Bool")
481b1c73532SDimitry Andric     TypeFragments.replace("bool", 0);
482b1c73532SDimitry Andric 
483145449b1SDimitry Andric   if (QualsFragments.getFragments().empty())
484145449b1SDimitry Andric     return TypeFragments;
485145449b1SDimitry Andric 
486145449b1SDimitry Andric   // Use east qualifier for pointer types
487145449b1SDimitry Andric   // For example:
488145449b1SDimitry Andric   // ```
489145449b1SDimitry Andric   // int *   const
490145449b1SDimitry Andric   // ^----   ^----
491145449b1SDimitry Andric   //  type    qualifier
492145449b1SDimitry Andric   // ^-----------------
493145449b1SDimitry Andric   //  const pointer to int
494145449b1SDimitry Andric   // ```
495145449b1SDimitry Andric   // should not be reconstructed as
496145449b1SDimitry Andric   // ```
497145449b1SDimitry Andric   // const       int       *
498145449b1SDimitry Andric   // ^----       ^--
499145449b1SDimitry Andric   //  qualifier   type
500145449b1SDimitry Andric   // ^----------------     ^
501145449b1SDimitry Andric   //  pointer to const int
502145449b1SDimitry Andric   // ```
503145449b1SDimitry Andric   if (SQT.Ty->isAnyPointerType())
504145449b1SDimitry Andric     return TypeFragments.appendSpace().append(std::move(QualsFragments));
505145449b1SDimitry Andric 
506145449b1SDimitry Andric   return QualsFragments.appendSpace().append(std::move(TypeFragments));
507145449b1SDimitry Andric }
508145449b1SDimitry Andric 
getFragmentsForNamespace(const NamespaceDecl * Decl)509b1c73532SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
510b1c73532SDimitry Andric     const NamespaceDecl *Decl) {
511b1c73532SDimitry Andric   DeclarationFragments Fragments;
512b1c73532SDimitry Andric   Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword);
513b1c73532SDimitry Andric   if (!Decl->isAnonymousNamespace())
514b1c73532SDimitry Andric     Fragments.appendSpace().append(
515b1c73532SDimitry Andric         Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
516ac9a064cSDimitry Andric   return Fragments.appendSemicolon();
517b1c73532SDimitry Andric }
518b1c73532SDimitry Andric 
519145449b1SDimitry Andric DeclarationFragments
getFragmentsForVar(const VarDecl * Var)520145449b1SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
521145449b1SDimitry Andric   DeclarationFragments Fragments;
522b1c73532SDimitry Andric   if (Var->isConstexpr())
523b1c73532SDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
524b1c73532SDimitry Andric         .appendSpace();
525b1c73532SDimitry Andric 
526145449b1SDimitry Andric   StorageClass SC = Var->getStorageClass();
527145449b1SDimitry Andric   if (SC != SC_None)
528145449b1SDimitry Andric     Fragments
529145449b1SDimitry Andric         .append(VarDecl::getStorageClassSpecifierString(SC),
530145449b1SDimitry Andric                 DeclarationFragments::FragmentKind::Keyword)
531145449b1SDimitry Andric         .appendSpace();
532145449b1SDimitry Andric 
533145449b1SDimitry Andric   // Capture potential fragments that needs to be placed after the variable name
534145449b1SDimitry Andric   // ```
535145449b1SDimitry Andric   // int nums[5];
536145449b1SDimitry Andric   // char (*ptr_to_array)[6];
537145449b1SDimitry Andric   // ```
538145449b1SDimitry Andric   DeclarationFragments After;
539b1c73532SDimitry Andric   FunctionTypeLoc BlockLoc;
540b1c73532SDimitry Andric   FunctionProtoTypeLoc BlockProtoLoc;
541b1c73532SDimitry Andric   findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc);
542b1c73532SDimitry Andric 
543b1c73532SDimitry Andric   if (!BlockLoc) {
544b1c73532SDimitry Andric     QualType T = Var->getTypeSourceInfo()
545b1c73532SDimitry Andric                      ? Var->getTypeSourceInfo()->getType()
546b1c73532SDimitry Andric                      : Var->getASTContext().getUnqualifiedObjCPointerType(
547b1c73532SDimitry Andric                            Var->getType());
548b1c73532SDimitry Andric 
549b1c73532SDimitry Andric     Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))
550b1c73532SDimitry Andric         .appendSpace();
551b1c73532SDimitry Andric   } else {
552b1c73532SDimitry Andric     Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));
553b1c73532SDimitry Andric   }
554b1c73532SDimitry Andric 
555b1c73532SDimitry Andric   return Fragments
556b1c73532SDimitry Andric       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
557b1c73532SDimitry Andric       .append(std::move(After))
558ac9a064cSDimitry Andric       .appendSemicolon();
559b1c73532SDimitry Andric }
560b1c73532SDimitry Andric 
561b1c73532SDimitry Andric DeclarationFragments
getFragmentsForVarTemplate(const VarDecl * Var)562b1c73532SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
563b1c73532SDimitry Andric   DeclarationFragments Fragments;
564b1c73532SDimitry Andric   if (Var->isConstexpr())
565b1c73532SDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
566b1c73532SDimitry Andric         .appendSpace();
567b1c73532SDimitry Andric   QualType T =
568b1c73532SDimitry Andric       Var->getTypeSourceInfo()
569b1c73532SDimitry Andric           ? Var->getTypeSourceInfo()->getType()
570b1c73532SDimitry Andric           : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());
571b1c73532SDimitry Andric 
572b1c73532SDimitry Andric   // Might be a member, so might be static.
573b1c73532SDimitry Andric   if (Var->isStaticDataMember())
574b1c73532SDimitry Andric     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
575b1c73532SDimitry Andric         .appendSpace();
576b1c73532SDimitry Andric 
577b1c73532SDimitry Andric   DeclarationFragments After;
578b1c73532SDimitry Andric   DeclarationFragments ArgumentFragment =
579b1c73532SDimitry Andric       getFragmentsForType(T, Var->getASTContext(), After);
580ac9a064cSDimitry Andric   if (StringRef(ArgumentFragment.begin()->Spelling)
581ac9a064cSDimitry Andric           .starts_with("type-parameter")) {
582ac9a064cSDimitry Andric     std::string ProperArgName = T.getAsString();
583b1c73532SDimitry Andric     ArgumentFragment.begin()->Spelling.swap(ProperArgName);
584b1c73532SDimitry Andric   }
585b1c73532SDimitry Andric   Fragments.append(std::move(ArgumentFragment))
586145449b1SDimitry Andric       .appendSpace()
587145449b1SDimitry Andric       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
588ac9a064cSDimitry Andric       .appendSemicolon();
589b1c73532SDimitry Andric   return Fragments;
590145449b1SDimitry Andric }
591145449b1SDimitry Andric 
592145449b1SDimitry Andric DeclarationFragments
getFragmentsForParam(const ParmVarDecl * Param)593145449b1SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
594145449b1SDimitry Andric   DeclarationFragments Fragments, After;
595145449b1SDimitry Andric 
596b1c73532SDimitry Andric   auto *TSInfo = Param->getTypeSourceInfo();
597b1c73532SDimitry Andric 
598b1c73532SDimitry Andric   QualType T = TSInfo ? TSInfo->getType()
599145449b1SDimitry Andric                       : Param->getASTContext().getUnqualifiedObjCPointerType(
600145449b1SDimitry Andric                             Param->getType());
601145449b1SDimitry Andric 
602b1c73532SDimitry Andric   FunctionTypeLoc BlockLoc;
603b1c73532SDimitry Andric   FunctionProtoTypeLoc BlockProtoLoc;
604b1c73532SDimitry Andric   findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);
605145449b1SDimitry Andric 
606b1c73532SDimitry Andric   DeclarationFragments TypeFragments;
607b1c73532SDimitry Andric   if (BlockLoc)
608b1c73532SDimitry Andric     TypeFragments.append(
609b1c73532SDimitry Andric         getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
610b1c73532SDimitry Andric   else
611b1c73532SDimitry Andric     TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After));
612b1c73532SDimitry Andric 
613ac9a064cSDimitry Andric   if (StringRef(TypeFragments.begin()->Spelling)
614ac9a064cSDimitry Andric           .starts_with("type-parameter")) {
615ac9a064cSDimitry Andric     std::string ProperArgName = Param->getOriginalType().getAsString();
616b1c73532SDimitry Andric     TypeFragments.begin()->Spelling.swap(ProperArgName);
617b1c73532SDimitry Andric   }
618b1c73532SDimitry Andric 
619b1c73532SDimitry Andric   if (Param->isObjCMethodParameter()) {
620145449b1SDimitry Andric     Fragments.append("(", DeclarationFragments::FragmentKind::Text)
621145449b1SDimitry Andric         .append(std::move(TypeFragments))
622b1c73532SDimitry Andric         .append(std::move(After))
623b1c73532SDimitry Andric         .append(") ", DeclarationFragments::FragmentKind::Text)
624b1c73532SDimitry Andric         .append(Param->getName(),
625b1c73532SDimitry Andric                 DeclarationFragments::FragmentKind::InternalParam);
626b1c73532SDimitry Andric   } else {
627b1c73532SDimitry Andric     Fragments.append(std::move(TypeFragments));
628b1c73532SDimitry Andric     if (!T->isBlockPointerType())
629b1c73532SDimitry Andric       Fragments.appendSpace();
630b1c73532SDimitry Andric     Fragments
631145449b1SDimitry Andric         .append(Param->getName(),
632145449b1SDimitry Andric                 DeclarationFragments::FragmentKind::InternalParam)
633145449b1SDimitry Andric         .append(std::move(After));
634145449b1SDimitry Andric   }
635b1c73532SDimitry Andric   return Fragments;
636b1c73532SDimitry Andric }
637b1c73532SDimitry Andric 
getFragmentsForBlock(const NamedDecl * BlockDecl,FunctionTypeLoc & Block,FunctionProtoTypeLoc & BlockProto,DeclarationFragments & After)638b1c73532SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock(
639b1c73532SDimitry Andric     const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
640b1c73532SDimitry Andric     FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) {
641b1c73532SDimitry Andric   DeclarationFragments Fragments;
642b1c73532SDimitry Andric 
643b1c73532SDimitry Andric   DeclarationFragments RetTyAfter;
644b1c73532SDimitry Andric   auto ReturnValueFragment = getFragmentsForType(
645b1c73532SDimitry Andric       Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After);
646b1c73532SDimitry Andric 
647b1c73532SDimitry Andric   Fragments.append(std::move(ReturnValueFragment))
648b1c73532SDimitry Andric       .append(std::move(RetTyAfter))
649b1c73532SDimitry Andric       .appendSpace()
650b1c73532SDimitry Andric       .append("(^", DeclarationFragments::FragmentKind::Text);
651b1c73532SDimitry Andric 
652b1c73532SDimitry Andric   After.append(")", DeclarationFragments::FragmentKind::Text);
653b1c73532SDimitry Andric   unsigned NumParams = Block.getNumParams();
654b1c73532SDimitry Andric 
655b1c73532SDimitry Andric   if (!BlockProto || NumParams == 0) {
656b1c73532SDimitry Andric     if (BlockProto && BlockProto.getTypePtr()->isVariadic())
657b1c73532SDimitry Andric       After.append("(...)", DeclarationFragments::FragmentKind::Text);
658b1c73532SDimitry Andric     else
659b1c73532SDimitry Andric       After.append("()", DeclarationFragments::FragmentKind::Text);
660b1c73532SDimitry Andric   } else {
661b1c73532SDimitry Andric     After.append("(", DeclarationFragments::FragmentKind::Text);
662b1c73532SDimitry Andric     for (unsigned I = 0; I != NumParams; ++I) {
663b1c73532SDimitry Andric       if (I)
664b1c73532SDimitry Andric         After.append(", ", DeclarationFragments::FragmentKind::Text);
665b1c73532SDimitry Andric       After.append(getFragmentsForParam(Block.getParam(I)));
666b1c73532SDimitry Andric       if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic())
667b1c73532SDimitry Andric         After.append(", ...", DeclarationFragments::FragmentKind::Text);
668b1c73532SDimitry Andric     }
669b1c73532SDimitry Andric     After.append(")", DeclarationFragments::FragmentKind::Text);
670b1c73532SDimitry Andric   }
671b1c73532SDimitry Andric 
672b1c73532SDimitry Andric   return Fragments;
673b1c73532SDimitry Andric }
674145449b1SDimitry Andric 
675145449b1SDimitry Andric DeclarationFragments
getFragmentsForFunction(const FunctionDecl * Func)676145449b1SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
677145449b1SDimitry Andric   DeclarationFragments Fragments;
678145449b1SDimitry Andric   switch (Func->getStorageClass()) {
679145449b1SDimitry Andric   case SC_None:
680145449b1SDimitry Andric   case SC_PrivateExtern:
681145449b1SDimitry Andric     break;
682145449b1SDimitry Andric   case SC_Extern:
683145449b1SDimitry Andric     Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword)
684145449b1SDimitry Andric         .appendSpace();
685145449b1SDimitry Andric     break;
686145449b1SDimitry Andric   case SC_Static:
687145449b1SDimitry Andric     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
688145449b1SDimitry Andric         .appendSpace();
689145449b1SDimitry Andric     break;
690145449b1SDimitry Andric   case SC_Auto:
691145449b1SDimitry Andric   case SC_Register:
692145449b1SDimitry Andric     llvm_unreachable("invalid for functions");
693145449b1SDimitry Andric   }
694b1c73532SDimitry Andric   if (Func->isConsteval()) // if consteval, it is also constexpr
695b1c73532SDimitry Andric     Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword)
696b1c73532SDimitry Andric         .appendSpace();
697b1c73532SDimitry Andric   else if (Func->isConstexpr())
698b1c73532SDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
699b1c73532SDimitry Andric         .appendSpace();
700145449b1SDimitry Andric 
701145449b1SDimitry Andric   // FIXME: Is `after` actually needed here?
702145449b1SDimitry Andric   DeclarationFragments After;
703b1c73532SDimitry Andric   auto ReturnValueFragment =
704b1c73532SDimitry Andric       getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After);
705ac9a064cSDimitry Andric   if (StringRef(ReturnValueFragment.begin()->Spelling)
706ac9a064cSDimitry Andric           .starts_with("type-parameter")) {
707ac9a064cSDimitry Andric     std::string ProperArgName = Func->getReturnType().getAsString();
708b1c73532SDimitry Andric     ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
709b1c73532SDimitry Andric   }
710b1c73532SDimitry Andric 
711b1c73532SDimitry Andric   Fragments.append(std::move(ReturnValueFragment))
712145449b1SDimitry Andric       .appendSpace()
713ac9a064cSDimitry Andric       .append(Func->getNameAsString(),
714ac9a064cSDimitry Andric               DeclarationFragments::FragmentKind::Identifier);
715b1c73532SDimitry Andric 
716b1c73532SDimitry Andric   if (Func->getTemplateSpecializationInfo()) {
717b1c73532SDimitry Andric     Fragments.append("<", DeclarationFragments::FragmentKind::Text);
718b1c73532SDimitry Andric 
719b1c73532SDimitry Andric     for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
720b1c73532SDimitry Andric       if (i)
721b1c73532SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
722b1c73532SDimitry Andric       Fragments.append(
723b1c73532SDimitry Andric           getFragmentsForType(Func->getParamDecl(i)->getType(),
724b1c73532SDimitry Andric                               Func->getParamDecl(i)->getASTContext(), After));
725b1c73532SDimitry Andric     }
726b1c73532SDimitry Andric     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
727b1c73532SDimitry Andric   }
728b1c73532SDimitry Andric   Fragments.append(std::move(After));
729145449b1SDimitry Andric 
730145449b1SDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
731b1c73532SDimitry Andric   unsigned NumParams = Func->getNumParams();
732b1c73532SDimitry Andric   for (unsigned i = 0; i != NumParams; ++i) {
733145449b1SDimitry Andric     if (i)
734145449b1SDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
735145449b1SDimitry Andric     Fragments.append(getFragmentsForParam(Func->getParamDecl(i)));
736145449b1SDimitry Andric   }
737b1c73532SDimitry Andric 
738b1c73532SDimitry Andric   if (Func->isVariadic()) {
739b1c73532SDimitry Andric     if (NumParams > 0)
740b1c73532SDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
741b1c73532SDimitry Andric     Fragments.append("...", DeclarationFragments::FragmentKind::Text);
742b1c73532SDimitry Andric   }
743145449b1SDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
744145449b1SDimitry Andric 
745b1c73532SDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
746b1c73532SDimitry Andric       Func->getExceptionSpecType()));
747b1c73532SDimitry Andric 
748ac9a064cSDimitry Andric   return Fragments.appendSemicolon();
749145449b1SDimitry Andric }
750145449b1SDimitry Andric 
getFragmentsForEnumConstant(const EnumConstantDecl * EnumConstDecl)751145449b1SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
752145449b1SDimitry Andric     const EnumConstantDecl *EnumConstDecl) {
753145449b1SDimitry Andric   DeclarationFragments Fragments;
754145449b1SDimitry Andric   return Fragments.append(EnumConstDecl->getName(),
755145449b1SDimitry Andric                           DeclarationFragments::FragmentKind::Identifier);
756145449b1SDimitry Andric }
757145449b1SDimitry Andric 
758145449b1SDimitry Andric DeclarationFragments
getFragmentsForEnum(const EnumDecl * EnumDecl)759145449b1SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
760145449b1SDimitry Andric   if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl())
761145449b1SDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
762145449b1SDimitry Andric 
763145449b1SDimitry Andric   DeclarationFragments Fragments, After;
764145449b1SDimitry Andric   Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword);
765145449b1SDimitry Andric 
766145449b1SDimitry Andric   if (!EnumDecl->getName().empty())
767145449b1SDimitry Andric     Fragments.appendSpace().append(
768145449b1SDimitry Andric         EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier);
769145449b1SDimitry Andric 
770145449b1SDimitry Andric   QualType IntegerType = EnumDecl->getIntegerType();
771145449b1SDimitry Andric   if (!IntegerType.isNull())
772ac9a064cSDimitry Andric     Fragments.appendSpace()
773ac9a064cSDimitry Andric         .append(": ", DeclarationFragments::FragmentKind::Text)
774145449b1SDimitry Andric         .append(
775145449b1SDimitry Andric             getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
776145449b1SDimitry Andric         .append(std::move(After));
777145449b1SDimitry Andric 
778ac9a064cSDimitry Andric   if (EnumDecl->getName().empty())
779ac9a064cSDimitry Andric     Fragments.appendSpace().append("{ ... }",
780ac9a064cSDimitry Andric                                    DeclarationFragments::FragmentKind::Text);
781ac9a064cSDimitry Andric 
782ac9a064cSDimitry Andric   return Fragments.appendSemicolon();
783145449b1SDimitry Andric }
784145449b1SDimitry Andric 
785145449b1SDimitry Andric DeclarationFragments
getFragmentsForField(const FieldDecl * Field)786145449b1SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
787145449b1SDimitry Andric   DeclarationFragments After;
788b1c73532SDimitry Andric   DeclarationFragments Fragments;
789b1c73532SDimitry Andric   if (Field->isMutable())
790b1c73532SDimitry Andric     Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword)
791b1c73532SDimitry Andric         .appendSpace();
792b1c73532SDimitry Andric   return Fragments
793b1c73532SDimitry Andric       .append(
794b1c73532SDimitry Andric           getFragmentsForType(Field->getType(), Field->getASTContext(), After))
795145449b1SDimitry Andric       .appendSpace()
796145449b1SDimitry Andric       .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
797b1c73532SDimitry Andric       .append(std::move(After))
798ac9a064cSDimitry Andric       .appendSemicolon();
799145449b1SDimitry Andric }
800145449b1SDimitry Andric 
getFragmentsForRecordDecl(const RecordDecl * Record)8014df029ccSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
8024df029ccSDimitry Andric     const RecordDecl *Record) {
803145449b1SDimitry Andric   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
804145449b1SDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
805145449b1SDimitry Andric 
806145449b1SDimitry Andric   DeclarationFragments Fragments;
8074df029ccSDimitry Andric   if (Record->isUnion())
8084df029ccSDimitry Andric     Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
8094df029ccSDimitry Andric   else
810145449b1SDimitry Andric     Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
811145449b1SDimitry Andric 
812ac9a064cSDimitry Andric   Fragments.appendSpace();
813145449b1SDimitry Andric   if (!Record->getName().empty())
814ac9a064cSDimitry Andric     Fragments.append(Record->getName(),
815ac9a064cSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
816ac9a064cSDimitry Andric   else
817ac9a064cSDimitry Andric     Fragments.append("{ ... }", DeclarationFragments::FragmentKind::Text);
8187fa27ce4SDimitry Andric 
819ac9a064cSDimitry Andric   return Fragments.appendSemicolon();
820145449b1SDimitry Andric }
821145449b1SDimitry Andric 
getFragmentsForCXXClass(const CXXRecordDecl * Record)822b1c73532SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
823b1c73532SDimitry Andric     const CXXRecordDecl *Record) {
824b1c73532SDimitry Andric   if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
825b1c73532SDimitry Andric     return getFragmentsForTypedef(TypedefNameDecl);
826b1c73532SDimitry Andric 
827b1c73532SDimitry Andric   DeclarationFragments Fragments;
828b1c73532SDimitry Andric   Fragments.append(DeclarationFragments::getStructureTypeFragment(Record));
829b1c73532SDimitry Andric 
830b1c73532SDimitry Andric   if (!Record->getName().empty())
831b1c73532SDimitry Andric     Fragments.appendSpace().append(
832b1c73532SDimitry Andric         Record->getName(), DeclarationFragments::FragmentKind::Identifier);
833b1c73532SDimitry Andric 
834ac9a064cSDimitry Andric   return Fragments.appendSemicolon();
835b1c73532SDimitry Andric }
836b1c73532SDimitry Andric 
837b1c73532SDimitry Andric DeclarationFragments
getFragmentsForSpecialCXXMethod(const CXXMethodDecl * Method)838b1c73532SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
839b1c73532SDimitry Andric     const CXXMethodDecl *Method) {
840b1c73532SDimitry Andric   DeclarationFragments Fragments;
841b1c73532SDimitry Andric   std::string Name;
842b1c73532SDimitry Andric   if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) {
843b1c73532SDimitry Andric     Name = Method->getNameAsString();
844b1c73532SDimitry Andric     if (Constructor->isExplicit())
845b1c73532SDimitry Andric       Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
846b1c73532SDimitry Andric           .appendSpace();
847b1c73532SDimitry Andric   } else if (isa<CXXDestructorDecl>(Method))
848b1c73532SDimitry Andric     Name = Method->getNameAsString();
849b1c73532SDimitry Andric 
850b1c73532SDimitry Andric   DeclarationFragments After;
851b1c73532SDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier)
852b1c73532SDimitry Andric       .append(std::move(After));
853b1c73532SDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
854b1c73532SDimitry Andric   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
855b1c73532SDimitry Andric     if (i)
856b1c73532SDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
857b1c73532SDimitry Andric     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
858b1c73532SDimitry Andric   }
859b1c73532SDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
860b1c73532SDimitry Andric 
861b1c73532SDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
862b1c73532SDimitry Andric       Method->getExceptionSpecType()));
863b1c73532SDimitry Andric 
864ac9a064cSDimitry Andric   return Fragments.appendSemicolon();
865b1c73532SDimitry Andric }
866b1c73532SDimitry Andric 
getFragmentsForCXXMethod(const CXXMethodDecl * Method)867b1c73532SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
868b1c73532SDimitry Andric     const CXXMethodDecl *Method) {
869b1c73532SDimitry Andric   DeclarationFragments Fragments;
870b1c73532SDimitry Andric   StringRef Name = Method->getName();
871b1c73532SDimitry Andric   if (Method->isStatic())
872b1c73532SDimitry Andric     Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
873b1c73532SDimitry Andric         .appendSpace();
874b1c73532SDimitry Andric   if (Method->isConstexpr())
875b1c73532SDimitry Andric     Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
876b1c73532SDimitry Andric         .appendSpace();
877b1c73532SDimitry Andric   if (Method->isVolatile())
878b1c73532SDimitry Andric     Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword)
879b1c73532SDimitry Andric         .appendSpace();
880b1c73532SDimitry Andric 
881b1c73532SDimitry Andric   // Build return type
882b1c73532SDimitry Andric   DeclarationFragments After;
883b1c73532SDimitry Andric   Fragments
884b1c73532SDimitry Andric       .append(getFragmentsForType(Method->getReturnType(),
885b1c73532SDimitry Andric                                   Method->getASTContext(), After))
886b1c73532SDimitry Andric       .appendSpace()
887b1c73532SDimitry Andric       .append(Name, DeclarationFragments::FragmentKind::Identifier)
888b1c73532SDimitry Andric       .append(std::move(After));
889b1c73532SDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
890b1c73532SDimitry Andric   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
891b1c73532SDimitry Andric     if (i)
892b1c73532SDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
893b1c73532SDimitry Andric     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
894b1c73532SDimitry Andric   }
895b1c73532SDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
896b1c73532SDimitry Andric 
897b1c73532SDimitry Andric   if (Method->isConst())
898b1c73532SDimitry Andric     Fragments.appendSpace().append("const",
899b1c73532SDimitry Andric                                    DeclarationFragments::FragmentKind::Keyword);
900b1c73532SDimitry Andric 
901b1c73532SDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
902b1c73532SDimitry Andric       Method->getExceptionSpecType()));
903b1c73532SDimitry Andric 
904ac9a064cSDimitry Andric   return Fragments.appendSemicolon();
905b1c73532SDimitry Andric }
906b1c73532SDimitry Andric 
907b1c73532SDimitry Andric DeclarationFragments
getFragmentsForConversionFunction(const CXXConversionDecl * ConversionFunction)908b1c73532SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
909b1c73532SDimitry Andric     const CXXConversionDecl *ConversionFunction) {
910b1c73532SDimitry Andric   DeclarationFragments Fragments;
911b1c73532SDimitry Andric 
912b1c73532SDimitry Andric   if (ConversionFunction->isExplicit())
913b1c73532SDimitry Andric     Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
914b1c73532SDimitry Andric         .appendSpace();
915b1c73532SDimitry Andric 
916b1c73532SDimitry Andric   Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword)
917b1c73532SDimitry Andric       .appendSpace();
918b1c73532SDimitry Andric 
919b1c73532SDimitry Andric   Fragments
920b1c73532SDimitry Andric       .append(ConversionFunction->getConversionType().getAsString(),
921b1c73532SDimitry Andric               DeclarationFragments::FragmentKind::TypeIdentifier)
922b1c73532SDimitry Andric       .append("(", DeclarationFragments::FragmentKind::Text);
923b1c73532SDimitry Andric   for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
924b1c73532SDimitry Andric        ++i) {
925b1c73532SDimitry Andric     if (i)
926b1c73532SDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
927b1c73532SDimitry Andric     Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
928b1c73532SDimitry Andric   }
929b1c73532SDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
930b1c73532SDimitry Andric 
931b1c73532SDimitry Andric   if (ConversionFunction->isConst())
932b1c73532SDimitry Andric     Fragments.appendSpace().append("const",
933b1c73532SDimitry Andric                                    DeclarationFragments::FragmentKind::Keyword);
934b1c73532SDimitry Andric 
935ac9a064cSDimitry Andric   return Fragments.appendSemicolon();
936b1c73532SDimitry Andric }
937b1c73532SDimitry Andric 
938b1c73532SDimitry Andric DeclarationFragments
getFragmentsForOverloadedOperator(const CXXMethodDecl * Method)939b1c73532SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
940b1c73532SDimitry Andric     const CXXMethodDecl *Method) {
941b1c73532SDimitry Andric   DeclarationFragments Fragments;
942b1c73532SDimitry Andric 
943b1c73532SDimitry Andric   // Build return type
944b1c73532SDimitry Andric   DeclarationFragments After;
945b1c73532SDimitry Andric   Fragments
946b1c73532SDimitry Andric       .append(getFragmentsForType(Method->getReturnType(),
947b1c73532SDimitry Andric                                   Method->getASTContext(), After))
948b1c73532SDimitry Andric       .appendSpace()
949b1c73532SDimitry Andric       .append(Method->getNameAsString(),
950b1c73532SDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
951b1c73532SDimitry Andric       .append(std::move(After));
952b1c73532SDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
953b1c73532SDimitry Andric   for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
954b1c73532SDimitry Andric     if (i)
955b1c73532SDimitry Andric       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
956b1c73532SDimitry Andric     Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
957b1c73532SDimitry Andric   }
958b1c73532SDimitry Andric   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
959b1c73532SDimitry Andric 
960b1c73532SDimitry Andric   if (Method->isConst())
961b1c73532SDimitry Andric     Fragments.appendSpace().append("const",
962b1c73532SDimitry Andric                                    DeclarationFragments::FragmentKind::Keyword);
963b1c73532SDimitry Andric 
964b1c73532SDimitry Andric   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
965b1c73532SDimitry Andric       Method->getExceptionSpecType()));
966b1c73532SDimitry Andric 
967ac9a064cSDimitry Andric   return Fragments.appendSemicolon();
968b1c73532SDimitry Andric }
969b1c73532SDimitry Andric 
970b1c73532SDimitry Andric // Get fragments for template parameters, e.g. T in tempalte<typename T> ...
971b1c73532SDimitry Andric DeclarationFragments
getFragmentsForTemplateParameters(ArrayRef<NamedDecl * > ParameterArray)972b1c73532SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(
973b1c73532SDimitry Andric     ArrayRef<NamedDecl *> ParameterArray) {
974b1c73532SDimitry Andric   DeclarationFragments Fragments;
975b1c73532SDimitry Andric   for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {
976b1c73532SDimitry Andric     if (i)
977b1c73532SDimitry Andric       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
978b1c73532SDimitry Andric           .appendSpace();
979b1c73532SDimitry Andric 
980ac9a064cSDimitry Andric     if (const auto *TemplateParam =
981ac9a064cSDimitry Andric             dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) {
982b1c73532SDimitry Andric       if (TemplateParam->hasTypeConstraint())
983b1c73532SDimitry Andric         Fragments.append(TemplateParam->getTypeConstraint()
984b1c73532SDimitry Andric                              ->getNamedConcept()
985b1c73532SDimitry Andric                              ->getName()
986b1c73532SDimitry Andric                              .str(),
987b1c73532SDimitry Andric                          DeclarationFragments::FragmentKind::TypeIdentifier);
988b1c73532SDimitry Andric       else if (TemplateParam->wasDeclaredWithTypename())
989ac9a064cSDimitry Andric         Fragments.append("typename",
990ac9a064cSDimitry Andric                          DeclarationFragments::FragmentKind::Keyword);
991b1c73532SDimitry Andric       else
992b1c73532SDimitry Andric         Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
993b1c73532SDimitry Andric 
994b1c73532SDimitry Andric       if (TemplateParam->isParameterPack())
995b1c73532SDimitry Andric         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
996b1c73532SDimitry Andric 
997ac9a064cSDimitry Andric       if (!TemplateParam->getName().empty())
998b1c73532SDimitry Andric         Fragments.appendSpace().append(
999b1c73532SDimitry Andric             TemplateParam->getName(),
1000b1c73532SDimitry Andric             DeclarationFragments::FragmentKind::GenericParameter);
1001ac9a064cSDimitry Andric 
1002ac9a064cSDimitry Andric       if (TemplateParam->hasDefaultArgument()) {
1003ac9a064cSDimitry Andric         const auto Default = TemplateParam->getDefaultArgument();
1004ac9a064cSDimitry Andric         Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
1005ac9a064cSDimitry Andric             .append(getFragmentsForTemplateArguments(
1006ac9a064cSDimitry Andric                 {Default.getArgument()}, TemplateParam->getASTContext(),
1007ac9a064cSDimitry Andric                 {Default}));
1008ac9a064cSDimitry Andric       }
1009ac9a064cSDimitry Andric     } else if (const auto *NTP =
1010ac9a064cSDimitry Andric                    dyn_cast<NonTypeTemplateParmDecl>(ParameterArray[i])) {
1011ac9a064cSDimitry Andric       DeclarationFragments After;
1012ac9a064cSDimitry Andric       const auto TyFragments =
1013ac9a064cSDimitry Andric           getFragmentsForType(NTP->getType(), NTP->getASTContext(), After);
1014ac9a064cSDimitry Andric       Fragments.append(std::move(TyFragments)).append(std::move(After));
1015ac9a064cSDimitry Andric 
1016ac9a064cSDimitry Andric       if (NTP->isParameterPack())
1017ac9a064cSDimitry Andric         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1018ac9a064cSDimitry Andric 
1019ac9a064cSDimitry Andric       if (!NTP->getName().empty())
1020ac9a064cSDimitry Andric         Fragments.appendSpace().append(
1021ac9a064cSDimitry Andric             NTP->getName(),
1022ac9a064cSDimitry Andric             DeclarationFragments::FragmentKind::GenericParameter);
1023ac9a064cSDimitry Andric 
1024ac9a064cSDimitry Andric       if (NTP->hasDefaultArgument()) {
1025ac9a064cSDimitry Andric         SmallString<8> ExprStr;
1026ac9a064cSDimitry Andric         raw_svector_ostream Output(ExprStr);
1027ac9a064cSDimitry Andric         NTP->getDefaultArgument().getArgument().print(
1028ac9a064cSDimitry Andric             NTP->getASTContext().getPrintingPolicy(), Output,
1029ac9a064cSDimitry Andric             /*IncludeType=*/false);
1030ac9a064cSDimitry Andric         Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
1031ac9a064cSDimitry Andric             .append(ExprStr, DeclarationFragments::FragmentKind::Text);
1032ac9a064cSDimitry Andric       }
1033ac9a064cSDimitry Andric     } else if (const auto *TTP =
1034ac9a064cSDimitry Andric                    dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) {
1035ac9a064cSDimitry Andric       Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
1036ac9a064cSDimitry Andric           .appendSpace()
1037ac9a064cSDimitry Andric           .append("<", DeclarationFragments::FragmentKind::Text)
1038ac9a064cSDimitry Andric           .append(getFragmentsForTemplateParameters(
1039ac9a064cSDimitry Andric               TTP->getTemplateParameters()->asArray()))
1040ac9a064cSDimitry Andric           .append(">", DeclarationFragments::FragmentKind::Text)
1041ac9a064cSDimitry Andric           .appendSpace()
1042ac9a064cSDimitry Andric           .append(TTP->wasDeclaredWithTypename() ? "typename" : "class",
1043ac9a064cSDimitry Andric                   DeclarationFragments::FragmentKind::Keyword);
1044ac9a064cSDimitry Andric 
1045ac9a064cSDimitry Andric       if (TTP->isParameterPack())
1046ac9a064cSDimitry Andric         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1047ac9a064cSDimitry Andric 
1048ac9a064cSDimitry Andric       if (!TTP->getName().empty())
1049ac9a064cSDimitry Andric         Fragments.appendSpace().append(
1050ac9a064cSDimitry Andric             TTP->getName(),
1051ac9a064cSDimitry Andric             DeclarationFragments::FragmentKind::GenericParameter);
1052ac9a064cSDimitry Andric       if (TTP->hasDefaultArgument()) {
1053ac9a064cSDimitry Andric         const auto Default = TTP->getDefaultArgument();
1054ac9a064cSDimitry Andric         Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
1055ac9a064cSDimitry Andric             .append(getFragmentsForTemplateArguments(
1056ac9a064cSDimitry Andric                 {Default.getArgument()}, TTP->getASTContext(), {Default}));
1057ac9a064cSDimitry Andric       }
1058ac9a064cSDimitry Andric     }
1059b1c73532SDimitry Andric   }
1060b1c73532SDimitry Andric   return Fragments;
1061b1c73532SDimitry Andric }
1062b1c73532SDimitry Andric 
1063b1c73532SDimitry Andric // Get fragments for template arguments, e.g. int in template<typename T>
1064b1c73532SDimitry Andric // Foo<int>;
1065b1c73532SDimitry Andric //
1066b1c73532SDimitry Andric // Note: TemplateParameters is only necessary if the Decl is a
1067b1c73532SDimitry Andric // PartialSpecialization, where we need the parameters to deduce the name of the
1068b1c73532SDimitry Andric // generic arguments.
1069b1c73532SDimitry Andric DeclarationFragments
getFragmentsForTemplateArguments(const ArrayRef<TemplateArgument> TemplateArguments,ASTContext & Context,const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs)1070b1c73532SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateArguments(
1071b1c73532SDimitry Andric     const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context,
1072ac9a064cSDimitry Andric     const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs) {
1073b1c73532SDimitry Andric   DeclarationFragments Fragments;
1074b1c73532SDimitry Andric   for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
1075b1c73532SDimitry Andric     if (i)
1076b1c73532SDimitry Andric       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
1077b1c73532SDimitry Andric           .appendSpace();
1078b1c73532SDimitry Andric 
1079ac9a064cSDimitry Andric     const auto &CTA = TemplateArguments[i];
1080ac9a064cSDimitry Andric     switch (CTA.getKind()) {
1081ac9a064cSDimitry Andric     case TemplateArgument::Type: {
1082b1c73532SDimitry Andric       DeclarationFragments After;
1083b1c73532SDimitry Andric       DeclarationFragments ArgumentFragment =
1084ac9a064cSDimitry Andric           getFragmentsForType(CTA.getAsType(), Context, After);
1085b1c73532SDimitry Andric 
1086ac9a064cSDimitry Andric       if (StringRef(ArgumentFragment.begin()->Spelling)
1087ac9a064cSDimitry Andric               .starts_with("type-parameter")) {
1088ac9a064cSDimitry Andric         if (TemplateArgumentLocs.has_value() &&
1089ac9a064cSDimitry Andric             TemplateArgumentLocs->size() > i) {
1090ac9a064cSDimitry Andric           std::string ProperArgName = TemplateArgumentLocs.value()[i]
1091ac9a064cSDimitry Andric                                           .getTypeSourceInfo()
1092ac9a064cSDimitry Andric                                           ->getType()
1093ac9a064cSDimitry Andric                                           .getAsString();
1094b1c73532SDimitry Andric           ArgumentFragment.begin()->Spelling.swap(ProperArgName);
1095ac9a064cSDimitry Andric         } else {
1096ac9a064cSDimitry Andric           auto &Spelling = ArgumentFragment.begin()->Spelling;
1097ac9a064cSDimitry Andric           Spelling.clear();
1098ac9a064cSDimitry Andric           raw_string_ostream OutStream(Spelling);
1099ac9a064cSDimitry Andric           CTA.print(Context.getPrintingPolicy(), OutStream, false);
1100ac9a064cSDimitry Andric           OutStream.flush();
1101b1c73532SDimitry Andric         }
1102ac9a064cSDimitry Andric       }
1103b1c73532SDimitry Andric 
1104ac9a064cSDimitry Andric       Fragments.append(std::move(ArgumentFragment));
1105ac9a064cSDimitry Andric       break;
1106ac9a064cSDimitry Andric     }
1107ac9a064cSDimitry Andric     case TemplateArgument::Declaration: {
1108ac9a064cSDimitry Andric       const auto *VD = CTA.getAsDecl();
1109ac9a064cSDimitry Andric       SmallString<128> USR;
1110ac9a064cSDimitry Andric       index::generateUSRForDecl(VD, USR);
1111ac9a064cSDimitry Andric       Fragments.append(VD->getNameAsString(),
1112ac9a064cSDimitry Andric                        DeclarationFragments::FragmentKind::Identifier, USR);
1113ac9a064cSDimitry Andric       break;
1114ac9a064cSDimitry Andric     }
1115ac9a064cSDimitry Andric     case TemplateArgument::NullPtr:
1116ac9a064cSDimitry Andric       Fragments.append("nullptr", DeclarationFragments::FragmentKind::Keyword);
1117ac9a064cSDimitry Andric       break;
1118ac9a064cSDimitry Andric 
1119ac9a064cSDimitry Andric     case TemplateArgument::Integral: {
1120ac9a064cSDimitry Andric       SmallString<4> Str;
1121ac9a064cSDimitry Andric       CTA.getAsIntegral().toString(Str);
1122ac9a064cSDimitry Andric       Fragments.append(Str, DeclarationFragments::FragmentKind::Text);
1123ac9a064cSDimitry Andric       break;
1124ac9a064cSDimitry Andric     }
1125ac9a064cSDimitry Andric 
1126ac9a064cSDimitry Andric     case TemplateArgument::StructuralValue: {
1127ac9a064cSDimitry Andric       const auto SVTy = CTA.getStructuralValueType();
1128ac9a064cSDimitry Andric       Fragments.append(CTA.getAsStructuralValue().getAsString(Context, SVTy),
1129ac9a064cSDimitry Andric                        DeclarationFragments::FragmentKind::Text);
1130ac9a064cSDimitry Andric       break;
1131ac9a064cSDimitry Andric     }
1132ac9a064cSDimitry Andric 
1133ac9a064cSDimitry Andric     case TemplateArgument::TemplateExpansion:
1134ac9a064cSDimitry Andric     case TemplateArgument::Template: {
1135ac9a064cSDimitry Andric       std::string Str;
1136ac9a064cSDimitry Andric       raw_string_ostream Stream(Str);
1137ac9a064cSDimitry Andric       CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy());
1138ac9a064cSDimitry Andric       SmallString<64> USR("");
1139ac9a064cSDimitry Andric       if (const auto *TemplDecl =
1140ac9a064cSDimitry Andric               CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
1141ac9a064cSDimitry Andric         index::generateUSRForDecl(TemplDecl, USR);
1142ac9a064cSDimitry Andric       Fragments.append(Str, DeclarationFragments::FragmentKind::TypeIdentifier,
1143ac9a064cSDimitry Andric                        USR);
1144ac9a064cSDimitry Andric       if (CTA.getKind() == TemplateArgument::TemplateExpansion)
1145b1c73532SDimitry Andric         Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1146ac9a064cSDimitry Andric       break;
1147ac9a064cSDimitry Andric     }
1148ac9a064cSDimitry Andric 
1149ac9a064cSDimitry Andric     case TemplateArgument::Pack:
1150ac9a064cSDimitry Andric       Fragments.append("<", DeclarationFragments::FragmentKind::Text)
1151ac9a064cSDimitry Andric           .append(getFragmentsForTemplateArguments(CTA.pack_elements(), Context,
1152ac9a064cSDimitry Andric                                                    {}))
1153ac9a064cSDimitry Andric           .append(">", DeclarationFragments::FragmentKind::Text);
1154ac9a064cSDimitry Andric       break;
1155ac9a064cSDimitry Andric 
1156ac9a064cSDimitry Andric     case TemplateArgument::Expression: {
1157ac9a064cSDimitry Andric       SmallString<8> ExprStr;
1158ac9a064cSDimitry Andric       raw_svector_ostream Output(ExprStr);
1159ac9a064cSDimitry Andric       CTA.getAsExpr()->printPretty(Output, nullptr,
1160ac9a064cSDimitry Andric                                    Context.getPrintingPolicy());
1161ac9a064cSDimitry Andric       Fragments.append(ExprStr, DeclarationFragments::FragmentKind::Text);
1162ac9a064cSDimitry Andric       break;
1163ac9a064cSDimitry Andric     }
1164ac9a064cSDimitry Andric 
1165ac9a064cSDimitry Andric     case TemplateArgument::Null:
1166ac9a064cSDimitry Andric       break;
1167ac9a064cSDimitry Andric     }
1168b1c73532SDimitry Andric   }
1169b1c73532SDimitry Andric   return Fragments;
1170b1c73532SDimitry Andric }
1171b1c73532SDimitry Andric 
getFragmentsForConcept(const ConceptDecl * Concept)1172b1c73532SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
1173b1c73532SDimitry Andric     const ConceptDecl *Concept) {
1174b1c73532SDimitry Andric   DeclarationFragments Fragments;
1175b1c73532SDimitry Andric   return Fragments
1176b1c73532SDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1177ac9a064cSDimitry Andric       .appendSpace()
1178b1c73532SDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1179b1c73532SDimitry Andric       .append(getFragmentsForTemplateParameters(
1180b1c73532SDimitry Andric           Concept->getTemplateParameters()->asArray()))
1181b1c73532SDimitry Andric       .append("> ", DeclarationFragments::FragmentKind::Text)
1182ac9a064cSDimitry Andric       .appendSpace()
1183b1c73532SDimitry Andric       .append("concept", DeclarationFragments::FragmentKind::Keyword)
1184b1c73532SDimitry Andric       .appendSpace()
1185b1c73532SDimitry Andric       .append(Concept->getName().str(),
1186b1c73532SDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
1187ac9a064cSDimitry Andric       .appendSemicolon();
1188b1c73532SDimitry Andric }
1189b1c73532SDimitry Andric 
1190b1c73532SDimitry Andric DeclarationFragments
getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl * RedeclarableTemplate)1191b1c73532SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
1192b1c73532SDimitry Andric     const RedeclarableTemplateDecl *RedeclarableTemplate) {
1193b1c73532SDimitry Andric   DeclarationFragments Fragments;
1194b1c73532SDimitry Andric   Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
1195ac9a064cSDimitry Andric       .appendSpace()
1196b1c73532SDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1197b1c73532SDimitry Andric       .append(getFragmentsForTemplateParameters(
1198b1c73532SDimitry Andric           RedeclarableTemplate->getTemplateParameters()->asArray()))
1199b1c73532SDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1200b1c73532SDimitry Andric       .appendSpace();
1201b1c73532SDimitry Andric 
1202b1c73532SDimitry Andric   if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate))
1203b1c73532SDimitry Andric     Fragments.appendSpace()
1204b1c73532SDimitry Andric         .append("using", DeclarationFragments::FragmentKind::Keyword)
1205b1c73532SDimitry Andric         .appendSpace()
1206b1c73532SDimitry Andric         .append(RedeclarableTemplate->getName(),
1207b1c73532SDimitry Andric                 DeclarationFragments::FragmentKind::Identifier);
1208b1c73532SDimitry Andric   // the templated records will be resposbible for injecting their templates
1209b1c73532SDimitry Andric   return Fragments.appendSpace();
1210b1c73532SDimitry Andric }
1211b1c73532SDimitry Andric 
1212b1c73532SDimitry Andric DeclarationFragments
getFragmentsForClassTemplateSpecialization(const ClassTemplateSpecializationDecl * Decl)1213b1c73532SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
1214b1c73532SDimitry Andric     const ClassTemplateSpecializationDecl *Decl) {
1215b1c73532SDimitry Andric   DeclarationFragments Fragments;
1216b1c73532SDimitry Andric   return Fragments
1217b1c73532SDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1218ac9a064cSDimitry Andric       .appendSpace()
1219b1c73532SDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1220b1c73532SDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1221b1c73532SDimitry Andric       .appendSpace()
1222b1c73532SDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
1223b1c73532SDimitry Andric           cast<CXXRecordDecl>(Decl)))
1224b1c73532SDimitry Andric       .pop_back() // there is an extra semicolon now
1225b1c73532SDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1226ac9a064cSDimitry Andric       .append(getFragmentsForTemplateArguments(
1227ac9a064cSDimitry Andric           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1228ac9a064cSDimitry Andric           Decl->getTemplateArgsAsWritten()->arguments()))
1229b1c73532SDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1230ac9a064cSDimitry Andric       .appendSemicolon();
1231b1c73532SDimitry Andric }
1232b1c73532SDimitry Andric 
1233b1c73532SDimitry Andric DeclarationFragments
getFragmentsForClassTemplatePartialSpecialization(const ClassTemplatePartialSpecializationDecl * Decl)1234b1c73532SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
1235b1c73532SDimitry Andric     const ClassTemplatePartialSpecializationDecl *Decl) {
1236b1c73532SDimitry Andric   DeclarationFragments Fragments;
1237b1c73532SDimitry Andric   return Fragments
1238b1c73532SDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1239ac9a064cSDimitry Andric       .appendSpace()
1240b1c73532SDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1241b1c73532SDimitry Andric       .append(getFragmentsForTemplateParameters(
1242b1c73532SDimitry Andric           Decl->getTemplateParameters()->asArray()))
1243b1c73532SDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1244b1c73532SDimitry Andric       .appendSpace()
1245b1c73532SDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
1246b1c73532SDimitry Andric           cast<CXXRecordDecl>(Decl)))
1247b1c73532SDimitry Andric       .pop_back() // there is an extra semicolon now
1248b1c73532SDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1249b1c73532SDimitry Andric       .append(getFragmentsForTemplateArguments(
1250b1c73532SDimitry Andric           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1251ac9a064cSDimitry Andric           Decl->getTemplateArgsAsWritten()->arguments()))
1252b1c73532SDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1253ac9a064cSDimitry Andric       .appendSemicolon();
1254b1c73532SDimitry Andric }
1255b1c73532SDimitry Andric 
1256b1c73532SDimitry Andric DeclarationFragments
getFragmentsForVarTemplateSpecialization(const VarTemplateSpecializationDecl * Decl)1257b1c73532SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
1258b1c73532SDimitry Andric     const VarTemplateSpecializationDecl *Decl) {
1259b1c73532SDimitry Andric   DeclarationFragments Fragments;
1260b1c73532SDimitry Andric   return Fragments
1261b1c73532SDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1262ac9a064cSDimitry Andric       .appendSpace()
1263b1c73532SDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1264b1c73532SDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1265b1c73532SDimitry Andric       .appendSpace()
1266b1c73532SDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
1267b1c73532SDimitry Andric       .pop_back() // there is an extra semicolon now
1268b1c73532SDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1269ac9a064cSDimitry Andric       .append(getFragmentsForTemplateArguments(
1270ac9a064cSDimitry Andric           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1271ac9a064cSDimitry Andric           Decl->getTemplateArgsAsWritten()->arguments()))
1272b1c73532SDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1273ac9a064cSDimitry Andric       .appendSemicolon();
1274b1c73532SDimitry Andric }
1275b1c73532SDimitry Andric 
1276b1c73532SDimitry Andric DeclarationFragments
getFragmentsForVarTemplatePartialSpecialization(const VarTemplatePartialSpecializationDecl * Decl)1277b1c73532SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
1278b1c73532SDimitry Andric     const VarTemplatePartialSpecializationDecl *Decl) {
1279b1c73532SDimitry Andric   DeclarationFragments Fragments;
1280b1c73532SDimitry Andric   return Fragments
1281b1c73532SDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1282ac9a064cSDimitry Andric       .appendSpace()
1283b1c73532SDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1284b1c73532SDimitry Andric       // Partial specs may have new params.
1285b1c73532SDimitry Andric       .append(getFragmentsForTemplateParameters(
1286b1c73532SDimitry Andric           Decl->getTemplateParameters()->asArray()))
1287b1c73532SDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1288b1c73532SDimitry Andric       .appendSpace()
1289b1c73532SDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
1290b1c73532SDimitry Andric       .pop_back() // there is an extra semicolon now
1291b1c73532SDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1292b1c73532SDimitry Andric       .append(getFragmentsForTemplateArguments(
1293b1c73532SDimitry Andric           Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1294ac9a064cSDimitry Andric           Decl->getTemplateArgsAsWritten()->arguments()))
1295b1c73532SDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1296ac9a064cSDimitry Andric       .appendSemicolon();
1297b1c73532SDimitry Andric }
1298b1c73532SDimitry Andric 
1299b1c73532SDimitry Andric DeclarationFragments
getFragmentsForFunctionTemplate(const FunctionTemplateDecl * Decl)1300b1c73532SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
1301b1c73532SDimitry Andric     const FunctionTemplateDecl *Decl) {
1302b1c73532SDimitry Andric   DeclarationFragments Fragments;
1303b1c73532SDimitry Andric   return Fragments
1304b1c73532SDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1305ac9a064cSDimitry Andric       .appendSpace()
1306b1c73532SDimitry Andric       .append("<", DeclarationFragments::FragmentKind::Text)
1307b1c73532SDimitry Andric       // Partial specs may have new params.
1308b1c73532SDimitry Andric       .append(getFragmentsForTemplateParameters(
1309b1c73532SDimitry Andric           Decl->getTemplateParameters()->asArray()))
1310b1c73532SDimitry Andric       .append(">", DeclarationFragments::FragmentKind::Text)
1311b1c73532SDimitry Andric       .appendSpace()
1312b1c73532SDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForFunction(
1313b1c73532SDimitry Andric           Decl->getAsFunction()));
1314b1c73532SDimitry Andric }
1315b1c73532SDimitry Andric 
1316b1c73532SDimitry Andric DeclarationFragments
getFragmentsForFunctionTemplateSpecialization(const FunctionDecl * Decl)1317b1c73532SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(
1318b1c73532SDimitry Andric     const FunctionDecl *Decl) {
1319b1c73532SDimitry Andric   DeclarationFragments Fragments;
1320b1c73532SDimitry Andric   return Fragments
1321b1c73532SDimitry Andric       .append("template", DeclarationFragments::FragmentKind::Keyword)
1322ac9a064cSDimitry Andric       .appendSpace()
1323b1c73532SDimitry Andric       .append("<>", DeclarationFragments::FragmentKind::Text)
1324b1c73532SDimitry Andric       .appendSpace()
1325b1c73532SDimitry Andric       .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl));
1326b1c73532SDimitry Andric }
1327b1c73532SDimitry Andric 
1328145449b1SDimitry Andric DeclarationFragments
getFragmentsForMacro(StringRef Name,const MacroDirective * MD)1329145449b1SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,
1330145449b1SDimitry Andric                                                   const MacroDirective *MD) {
1331145449b1SDimitry Andric   DeclarationFragments Fragments;
1332145449b1SDimitry Andric   Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword)
1333145449b1SDimitry Andric       .appendSpace();
1334145449b1SDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
1335145449b1SDimitry Andric 
1336145449b1SDimitry Andric   auto *MI = MD->getMacroInfo();
1337145449b1SDimitry Andric 
1338145449b1SDimitry Andric   if (MI->isFunctionLike()) {
1339145449b1SDimitry Andric     Fragments.append("(", DeclarationFragments::FragmentKind::Text);
1340145449b1SDimitry Andric     unsigned numParameters = MI->getNumParams();
1341145449b1SDimitry Andric     if (MI->isC99Varargs())
1342145449b1SDimitry Andric       --numParameters;
1343145449b1SDimitry Andric     for (unsigned i = 0; i < numParameters; ++i) {
1344145449b1SDimitry Andric       if (i)
1345145449b1SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
1346145449b1SDimitry Andric       Fragments.append(MI->params()[i]->getName(),
1347145449b1SDimitry Andric                        DeclarationFragments::FragmentKind::InternalParam);
1348145449b1SDimitry Andric     }
1349145449b1SDimitry Andric     if (MI->isVariadic()) {
1350145449b1SDimitry Andric       if (numParameters && MI->isC99Varargs())
1351145449b1SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
1352145449b1SDimitry Andric       Fragments.append("...", DeclarationFragments::FragmentKind::Text);
1353145449b1SDimitry Andric     }
1354145449b1SDimitry Andric     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
1355145449b1SDimitry Andric   }
1356145449b1SDimitry Andric   return Fragments;
1357145449b1SDimitry Andric }
1358145449b1SDimitry Andric 
getFragmentsForObjCCategory(const ObjCCategoryDecl * Category)1359145449b1SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
1360145449b1SDimitry Andric     const ObjCCategoryDecl *Category) {
1361145449b1SDimitry Andric   DeclarationFragments Fragments;
1362145449b1SDimitry Andric 
1363e3b55780SDimitry Andric   auto *Interface = Category->getClassInterface();
1364145449b1SDimitry Andric   SmallString<128> InterfaceUSR;
1365e3b55780SDimitry Andric   index::generateUSRForDecl(Interface, InterfaceUSR);
1366145449b1SDimitry Andric 
1367145449b1SDimitry Andric   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
1368145449b1SDimitry Andric       .appendSpace()
1369ac9a064cSDimitry Andric       .append(Interface->getName(),
1370e3b55780SDimitry Andric               DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
1371e3b55780SDimitry Andric               Interface)
1372145449b1SDimitry Andric       .append(" (", DeclarationFragments::FragmentKind::Text)
1373145449b1SDimitry Andric       .append(Category->getName(),
1374145449b1SDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
1375145449b1SDimitry Andric       .append(")", DeclarationFragments::FragmentKind::Text);
1376145449b1SDimitry Andric 
1377145449b1SDimitry Andric   return Fragments;
1378145449b1SDimitry Andric }
1379145449b1SDimitry Andric 
getFragmentsForObjCInterface(const ObjCInterfaceDecl * Interface)1380145449b1SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface(
1381145449b1SDimitry Andric     const ObjCInterfaceDecl *Interface) {
1382145449b1SDimitry Andric   DeclarationFragments Fragments;
1383145449b1SDimitry Andric   // Build the base of the Objective-C interface declaration.
1384145449b1SDimitry Andric   Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
1385145449b1SDimitry Andric       .appendSpace()
1386145449b1SDimitry Andric       .append(Interface->getName(),
1387145449b1SDimitry Andric               DeclarationFragments::FragmentKind::Identifier);
1388145449b1SDimitry Andric 
1389145449b1SDimitry Andric   // Build the inheritance part of the declaration.
1390145449b1SDimitry Andric   if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {
1391145449b1SDimitry Andric     SmallString<128> SuperUSR;
1392145449b1SDimitry Andric     index::generateUSRForDecl(SuperClass, SuperUSR);
1393145449b1SDimitry Andric     Fragments.append(" : ", DeclarationFragments::FragmentKind::Text)
1394145449b1SDimitry Andric         .append(SuperClass->getName(),
1395e3b55780SDimitry Andric                 DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR,
1396e3b55780SDimitry Andric                 SuperClass);
1397145449b1SDimitry Andric   }
1398145449b1SDimitry Andric 
1399145449b1SDimitry Andric   return Fragments;
1400145449b1SDimitry Andric }
1401145449b1SDimitry Andric 
getFragmentsForObjCMethod(const ObjCMethodDecl * Method)1402145449b1SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
1403145449b1SDimitry Andric     const ObjCMethodDecl *Method) {
1404145449b1SDimitry Andric   DeclarationFragments Fragments, After;
1405145449b1SDimitry Andric   // Build the instance/class method indicator.
1406145449b1SDimitry Andric   if (Method->isClassMethod())
1407145449b1SDimitry Andric     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
1408145449b1SDimitry Andric   else if (Method->isInstanceMethod())
1409145449b1SDimitry Andric     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
1410145449b1SDimitry Andric 
1411145449b1SDimitry Andric   // Build the return type.
1412145449b1SDimitry Andric   Fragments.append("(", DeclarationFragments::FragmentKind::Text)
1413145449b1SDimitry Andric       .append(getFragmentsForType(Method->getReturnType(),
1414145449b1SDimitry Andric                                   Method->getASTContext(), After))
1415145449b1SDimitry Andric       .append(std::move(After))
1416145449b1SDimitry Andric       .append(")", DeclarationFragments::FragmentKind::Text);
1417145449b1SDimitry Andric 
1418145449b1SDimitry Andric   // Build the selector part.
1419145449b1SDimitry Andric   Selector Selector = Method->getSelector();
1420145449b1SDimitry Andric   if (Selector.getNumArgs() == 0)
1421145449b1SDimitry Andric     // For Objective-C methods that don't take arguments, the first (and only)
1422145449b1SDimitry Andric     // slot of the selector is the method name.
1423145449b1SDimitry Andric     Fragments.appendSpace().append(
1424145449b1SDimitry Andric         Selector.getNameForSlot(0),
1425145449b1SDimitry Andric         DeclarationFragments::FragmentKind::Identifier);
1426145449b1SDimitry Andric 
1427145449b1SDimitry Andric   // For Objective-C methods that take arguments, build the selector slots.
1428145449b1SDimitry Andric   for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {
1429145449b1SDimitry Andric     // Objective-C method selector parts are considered as identifiers instead
1430145449b1SDimitry Andric     // of "external parameters" as in Swift. This is because Objective-C method
1431145449b1SDimitry Andric     // symbols are referenced with the entire selector, instead of just the
1432145449b1SDimitry Andric     // method name in Swift.
1433145449b1SDimitry Andric     SmallString<32> ParamID(Selector.getNameForSlot(i));
1434145449b1SDimitry Andric     ParamID.append(":");
1435145449b1SDimitry Andric     Fragments.appendSpace().append(
1436145449b1SDimitry Andric         ParamID, DeclarationFragments::FragmentKind::Identifier);
1437145449b1SDimitry Andric 
1438145449b1SDimitry Andric     // Build the internal parameter.
1439145449b1SDimitry Andric     const ParmVarDecl *Param = Method->getParamDecl(i);
1440145449b1SDimitry Andric     Fragments.append(getFragmentsForParam(Param));
1441145449b1SDimitry Andric   }
1442145449b1SDimitry Andric 
1443ac9a064cSDimitry Andric   return Fragments.appendSemicolon();
1444145449b1SDimitry Andric }
1445145449b1SDimitry Andric 
getFragmentsForObjCProperty(const ObjCPropertyDecl * Property)1446145449b1SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
1447145449b1SDimitry Andric     const ObjCPropertyDecl *Property) {
1448145449b1SDimitry Andric   DeclarationFragments Fragments, After;
1449145449b1SDimitry Andric 
1450145449b1SDimitry Andric   // Build the Objective-C property keyword.
1451145449b1SDimitry Andric   Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword);
1452145449b1SDimitry Andric 
14537fa27ce4SDimitry Andric   const auto Attributes = Property->getPropertyAttributesAsWritten();
1454145449b1SDimitry Andric   // Build the attributes if there is any associated with the property.
1455145449b1SDimitry Andric   if (Attributes != ObjCPropertyAttribute::kind_noattr) {
1456145449b1SDimitry Andric     // No leading comma for the first attribute.
1457145449b1SDimitry Andric     bool First = true;
1458145449b1SDimitry Andric     Fragments.append(" (", DeclarationFragments::FragmentKind::Text);
1459145449b1SDimitry Andric     // Helper function to render the attribute.
1460145449b1SDimitry Andric     auto RenderAttribute =
1461145449b1SDimitry Andric         [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,
1462145449b1SDimitry Andric             StringRef Arg = "",
1463145449b1SDimitry Andric             DeclarationFragments::FragmentKind ArgKind =
1464145449b1SDimitry Andric                 DeclarationFragments::FragmentKind::Identifier) {
1465145449b1SDimitry Andric           // Check if the `Kind` attribute is set for this property.
1466145449b1SDimitry Andric           if ((Attributes & Kind) && !Spelling.empty()) {
1467145449b1SDimitry Andric             // Add a leading comma if this is not the first attribute rendered.
1468145449b1SDimitry Andric             if (!First)
1469145449b1SDimitry Andric               Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
1470145449b1SDimitry Andric             // Render the spelling of this attribute `Kind` as a keyword.
1471145449b1SDimitry Andric             Fragments.append(Spelling,
1472145449b1SDimitry Andric                              DeclarationFragments::FragmentKind::Keyword);
1473145449b1SDimitry Andric             // If this attribute takes in arguments (e.g. `getter=getterName`),
1474145449b1SDimitry Andric             // render the arguments.
1475145449b1SDimitry Andric             if (!Arg.empty())
1476145449b1SDimitry Andric               Fragments.append("=", DeclarationFragments::FragmentKind::Text)
1477145449b1SDimitry Andric                   .append(Arg, ArgKind);
1478145449b1SDimitry Andric             First = false;
1479145449b1SDimitry Andric           }
1480145449b1SDimitry Andric         };
1481145449b1SDimitry Andric 
1482145449b1SDimitry Andric     // Go through all possible Objective-C property attributes and render set
1483145449b1SDimitry Andric     // ones.
1484145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_class, "class");
1485145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");
1486145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");
1487145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");
1488145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");
1489145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");
1490145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");
1491145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");
1492145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");
1493145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained,
1494145449b1SDimitry Andric                     "unsafe_unretained");
1495145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");
1496145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");
1497145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",
1498145449b1SDimitry Andric                     Property->getGetterName().getAsString());
1499145449b1SDimitry Andric     RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",
1500145449b1SDimitry Andric                     Property->getSetterName().getAsString());
1501145449b1SDimitry Andric 
1502145449b1SDimitry Andric     // Render nullability attributes.
1503145449b1SDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_nullability) {
1504145449b1SDimitry Andric       QualType Type = Property->getType();
1505145449b1SDimitry Andric       if (const auto Nullability =
1506145449b1SDimitry Andric               AttributedType::stripOuterNullability(Type)) {
1507145449b1SDimitry Andric         if (!First)
1508145449b1SDimitry Andric           Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
1509145449b1SDimitry Andric         if (*Nullability == NullabilityKind::Unspecified &&
1510145449b1SDimitry Andric             (Attributes & ObjCPropertyAttribute::kind_null_resettable))
1511145449b1SDimitry Andric           Fragments.append("null_resettable",
1512145449b1SDimitry Andric                            DeclarationFragments::FragmentKind::Keyword);
1513145449b1SDimitry Andric         else
1514145449b1SDimitry Andric           Fragments.append(
1515145449b1SDimitry Andric               getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),
1516145449b1SDimitry Andric               DeclarationFragments::FragmentKind::Keyword);
1517145449b1SDimitry Andric         First = false;
1518145449b1SDimitry Andric       }
1519145449b1SDimitry Andric     }
1520145449b1SDimitry Andric 
1521145449b1SDimitry Andric     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
1522145449b1SDimitry Andric   }
1523145449b1SDimitry Andric 
1524b1c73532SDimitry Andric   Fragments.appendSpace();
1525b1c73532SDimitry Andric 
1526b1c73532SDimitry Andric   FunctionTypeLoc BlockLoc;
1527b1c73532SDimitry Andric   FunctionProtoTypeLoc BlockProtoLoc;
1528b1c73532SDimitry Andric   findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc,
1529b1c73532SDimitry Andric                           BlockProtoLoc);
1530b1c73532SDimitry Andric 
1531b1c73532SDimitry Andric   auto PropType = Property->getType();
1532b1c73532SDimitry Andric   if (!BlockLoc)
1533b1c73532SDimitry Andric     Fragments
1534b1c73532SDimitry Andric         .append(getFragmentsForType(PropType, Property->getASTContext(), After))
1535b1c73532SDimitry Andric         .appendSpace();
1536b1c73532SDimitry Andric   else
1537b1c73532SDimitry Andric     Fragments.append(
1538b1c73532SDimitry Andric         getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After));
1539b1c73532SDimitry Andric 
1540b1c73532SDimitry Andric   return Fragments
1541145449b1SDimitry Andric       .append(Property->getName(),
1542145449b1SDimitry Andric               DeclarationFragments::FragmentKind::Identifier)
1543b1c73532SDimitry Andric       .append(std::move(After))
1544ac9a064cSDimitry Andric       .appendSemicolon();
1545145449b1SDimitry Andric }
1546145449b1SDimitry Andric 
getFragmentsForObjCProtocol(const ObjCProtocolDecl * Protocol)1547145449b1SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
1548145449b1SDimitry Andric     const ObjCProtocolDecl *Protocol) {
1549145449b1SDimitry Andric   DeclarationFragments Fragments;
1550145449b1SDimitry Andric   // Build basic protocol declaration.
1551145449b1SDimitry Andric   Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword)
1552145449b1SDimitry Andric       .appendSpace()
1553145449b1SDimitry Andric       .append(Protocol->getName(),
1554145449b1SDimitry Andric               DeclarationFragments::FragmentKind::Identifier);
1555145449b1SDimitry Andric 
1556145449b1SDimitry Andric   // If this protocol conforms to other protocols, build the conformance list.
1557145449b1SDimitry Andric   if (!Protocol->protocols().empty()) {
1558145449b1SDimitry Andric     Fragments.append(" <", DeclarationFragments::FragmentKind::Text);
1559145449b1SDimitry Andric     for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();
1560145449b1SDimitry Andric          It != Protocol->protocol_end(); It++) {
1561145449b1SDimitry Andric       // Add a leading comma if this is not the first protocol rendered.
1562145449b1SDimitry Andric       if (It != Protocol->protocol_begin())
1563145449b1SDimitry Andric         Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
1564145449b1SDimitry Andric 
1565145449b1SDimitry Andric       SmallString<128> USR;
1566145449b1SDimitry Andric       index::generateUSRForDecl(*It, USR);
1567145449b1SDimitry Andric       Fragments.append((*It)->getName(),
1568e3b55780SDimitry Andric                        DeclarationFragments::FragmentKind::TypeIdentifier, USR,
1569e3b55780SDimitry Andric                        *It);
1570145449b1SDimitry Andric     }
1571145449b1SDimitry Andric     Fragments.append(">", DeclarationFragments::FragmentKind::Text);
1572145449b1SDimitry Andric   }
1573145449b1SDimitry Andric 
1574145449b1SDimitry Andric   return Fragments;
1575145449b1SDimitry Andric }
1576145449b1SDimitry Andric 
getFragmentsForTypedef(const TypedefNameDecl * Decl)1577145449b1SDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
1578145449b1SDimitry Andric     const TypedefNameDecl *Decl) {
1579145449b1SDimitry Andric   DeclarationFragments Fragments, After;
1580145449b1SDimitry Andric   Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword)
1581145449b1SDimitry Andric       .appendSpace()
1582145449b1SDimitry Andric       .append(getFragmentsForType(Decl->getUnderlyingType(),
1583145449b1SDimitry Andric                                   Decl->getASTContext(), After))
1584145449b1SDimitry Andric       .append(std::move(After))
1585145449b1SDimitry Andric       .appendSpace()
1586145449b1SDimitry Andric       .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
1587145449b1SDimitry Andric 
1588ac9a064cSDimitry Andric   return Fragments.appendSemicolon();
1589145449b1SDimitry Andric }
1590145449b1SDimitry Andric 
1591145449b1SDimitry Andric // Instantiate template for FunctionDecl.
1592145449b1SDimitry Andric template FunctionSignature
1593145449b1SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);
1594145449b1SDimitry Andric 
1595145449b1SDimitry Andric // Instantiate template for ObjCMethodDecl.
1596145449b1SDimitry Andric template FunctionSignature
1597145449b1SDimitry Andric DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);
1598145449b1SDimitry Andric 
1599145449b1SDimitry Andric // Subheading of a symbol defaults to its name.
1600145449b1SDimitry Andric DeclarationFragments
getSubHeading(const NamedDecl * Decl)1601145449b1SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
1602145449b1SDimitry Andric   DeclarationFragments Fragments;
1603b1c73532SDimitry Andric   if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))
1604b1c73532SDimitry Andric     Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(),
1605b1c73532SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
1606b1c73532SDimitry Andric   else if (isa<CXXConversionDecl>(Decl)) {
1607b1c73532SDimitry Andric     Fragments.append(
1608b1c73532SDimitry Andric         cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(),
1609b1c73532SDimitry Andric         DeclarationFragments::FragmentKind::Identifier);
1610b1c73532SDimitry Andric   } else if (isa<CXXMethodDecl>(Decl) &&
1611b1c73532SDimitry Andric              cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) {
1612b1c73532SDimitry Andric     Fragments.append(Decl->getNameAsString(),
1613b1c73532SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
1614ac9a064cSDimitry Andric   } else if (Decl->getIdentifier()) {
1615145449b1SDimitry Andric     Fragments.append(Decl->getName(),
1616145449b1SDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
1617ac9a064cSDimitry Andric   } else
1618ac9a064cSDimitry Andric     Fragments.append(Decl->getDeclName().getAsString(),
1619ac9a064cSDimitry Andric                      DeclarationFragments::FragmentKind::Identifier);
1620145449b1SDimitry Andric   return Fragments;
1621145449b1SDimitry Andric }
1622145449b1SDimitry Andric 
1623145449b1SDimitry Andric // Subheading of an Objective-C method is a `+` or `-` sign indicating whether
1624145449b1SDimitry Andric // it's a class method or an instance method, followed by the selector name.
1625145449b1SDimitry Andric DeclarationFragments
getSubHeading(const ObjCMethodDecl * Method)1626145449b1SDimitry Andric DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) {
1627145449b1SDimitry Andric   DeclarationFragments Fragments;
1628145449b1SDimitry Andric   if (Method->isClassMethod())
1629145449b1SDimitry Andric     Fragments.append("+ ", DeclarationFragments::FragmentKind::Text);
1630145449b1SDimitry Andric   else if (Method->isInstanceMethod())
1631145449b1SDimitry Andric     Fragments.append("- ", DeclarationFragments::FragmentKind::Text);
1632145449b1SDimitry Andric 
1633145449b1SDimitry Andric   return Fragments.append(Method->getNameAsString(),
1634145449b1SDimitry Andric                           DeclarationFragments::FragmentKind::Identifier);
1635145449b1SDimitry Andric }
1636145449b1SDimitry Andric 
1637145449b1SDimitry Andric // Subheading of a symbol defaults to its name.
1638145449b1SDimitry Andric DeclarationFragments
getSubHeadingForMacro(StringRef Name)1639145449b1SDimitry Andric DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) {
1640145449b1SDimitry Andric   DeclarationFragments Fragments;
1641145449b1SDimitry Andric   Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
1642145449b1SDimitry Andric   return Fragments;
1643145449b1SDimitry Andric }
1644