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