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