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