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"
155f757f3fSDimitry Andric #include "clang/AST/Decl.h"
165f757f3fSDimitry Andric #include "clang/AST/DeclCXX.h"
175f757f3fSDimitry Andric #include "clang/AST/QualTypeNames.h"
185f757f3fSDimitry Andric #include "clang/AST/Type.h"
195f757f3fSDimitry Andric #include "clang/AST/TypeLoc.h"
205f757f3fSDimitry Andric #include "clang/Basic/OperatorKinds.h"
2106c3fb27SDimitry Andric #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
2281ad6265SDimitry Andric #include "clang/Index/USRGeneration.h"
2381ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h"
245f757f3fSDimitry Andric #include <typeinfo>
2581ad6265SDimitry Andric
2681ad6265SDimitry Andric using namespace clang::extractapi;
2781ad6265SDimitry Andric using namespace llvm;
2881ad6265SDimitry Andric
295f757f3fSDimitry Andric namespace {
305f757f3fSDimitry Andric
findTypeLocForBlockDecl(const clang::TypeSourceInfo * TSInfo,clang::FunctionTypeLoc & Block,clang::FunctionProtoTypeLoc & BlockProto)315f757f3fSDimitry Andric void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
325f757f3fSDimitry Andric clang::FunctionTypeLoc &Block,
335f757f3fSDimitry Andric clang::FunctionProtoTypeLoc &BlockProto) {
345f757f3fSDimitry Andric if (!TSInfo)
355f757f3fSDimitry Andric return;
365f757f3fSDimitry Andric
375f757f3fSDimitry Andric clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
385f757f3fSDimitry Andric while (true) {
395f757f3fSDimitry Andric // Look through qualified types
405f757f3fSDimitry Andric if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) {
415f757f3fSDimitry Andric TL = QualifiedTL.getUnqualifiedLoc();
425f757f3fSDimitry Andric continue;
435f757f3fSDimitry Andric }
445f757f3fSDimitry Andric
455f757f3fSDimitry Andric if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) {
465f757f3fSDimitry Andric TL = AttrTL.getModifiedLoc();
475f757f3fSDimitry Andric continue;
485f757f3fSDimitry Andric }
495f757f3fSDimitry Andric
505f757f3fSDimitry Andric // Try to get the function prototype behind the block pointer type,
515f757f3fSDimitry Andric // then we're done.
525f757f3fSDimitry Andric if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) {
535f757f3fSDimitry Andric TL = BlockPtr.getPointeeLoc().IgnoreParens();
545f757f3fSDimitry Andric Block = TL.getAs<clang::FunctionTypeLoc>();
555f757f3fSDimitry Andric BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>();
565f757f3fSDimitry Andric }
575f757f3fSDimitry Andric break;
585f757f3fSDimitry Andric }
595f757f3fSDimitry Andric }
605f757f3fSDimitry Andric
615f757f3fSDimitry Andric } // namespace
625f757f3fSDimitry 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)1285f757f3fSDimitry Andric DeclarationFragments DeclarationFragments::getExceptionSpecificationString(
1295f757f3fSDimitry Andric ExceptionSpecificationType ExceptionSpec) {
1305f757f3fSDimitry Andric DeclarationFragments Fragments;
1315f757f3fSDimitry Andric switch (ExceptionSpec) {
1325f757f3fSDimitry Andric case ExceptionSpecificationType::EST_None:
1335f757f3fSDimitry Andric return Fragments;
1345f757f3fSDimitry Andric case ExceptionSpecificationType::EST_DynamicNone:
1355f757f3fSDimitry Andric return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
1365f757f3fSDimitry Andric .append("throw", DeclarationFragments::FragmentKind::Keyword)
1375f757f3fSDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text)
1385f757f3fSDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text);
1395f757f3fSDimitry Andric case ExceptionSpecificationType::EST_Dynamic:
1405f757f3fSDimitry Andric // FIXME: throw(int), get types of inner expression
1415f757f3fSDimitry Andric return Fragments;
1425f757f3fSDimitry Andric case ExceptionSpecificationType::EST_BasicNoexcept:
1435f757f3fSDimitry Andric return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
1445f757f3fSDimitry Andric .append("noexcept", DeclarationFragments::FragmentKind::Keyword);
1455f757f3fSDimitry Andric case ExceptionSpecificationType::EST_DependentNoexcept:
1465f757f3fSDimitry Andric // FIXME: throw(conditional-expression), get expression
1475f757f3fSDimitry Andric break;
1485f757f3fSDimitry Andric case ExceptionSpecificationType::EST_NoexceptFalse:
1495f757f3fSDimitry Andric return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
1505f757f3fSDimitry Andric .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
1515f757f3fSDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text)
1525f757f3fSDimitry Andric .append("false", DeclarationFragments::FragmentKind::Keyword)
1535f757f3fSDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text);
1545f757f3fSDimitry Andric case ExceptionSpecificationType::EST_NoexceptTrue:
1555f757f3fSDimitry Andric return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
1565f757f3fSDimitry Andric .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
1575f757f3fSDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text)
1585f757f3fSDimitry Andric .append("true", DeclarationFragments::FragmentKind::Keyword)
1595f757f3fSDimitry Andric .append(")", DeclarationFragments::FragmentKind::Text);
1605f757f3fSDimitry Andric default:
1615f757f3fSDimitry Andric return Fragments;
1625f757f3fSDimitry Andric }
1635f757f3fSDimitry Andric
1645f757f3fSDimitry Andric llvm_unreachable("Unhandled exception specification");
1655f757f3fSDimitry Andric }
1665f757f3fSDimitry Andric
1675f757f3fSDimitry Andric DeclarationFragments
getStructureTypeFragment(const RecordDecl * Record)1685f757f3fSDimitry Andric DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {
1695f757f3fSDimitry Andric DeclarationFragments Fragments;
1705f757f3fSDimitry Andric if (Record->isStruct())
1715f757f3fSDimitry Andric Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
1725f757f3fSDimitry Andric else if (Record->isUnion())
1735f757f3fSDimitry Andric Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
1745f757f3fSDimitry Andric else
1755f757f3fSDimitry Andric Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
1765f757f3fSDimitry Andric
1775f757f3fSDimitry Andric return Fragments;
1785f757f3fSDimitry Andric }
1795f757f3fSDimitry 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*7a6dacacSDimitry Andric // An ElaboratedType is a sugar for types that are referred to using an
256*7a6dacacSDimitry Andric // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a
257*7a6dacacSDimitry Andric // qualified name, e.g., `N::M::type`, or both.
258*7a6dacacSDimitry Andric if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
259*7a6dacacSDimitry Andric ElaboratedTypeKeyword Keyword = ET->getKeyword();
260*7a6dacacSDimitry Andric if (Keyword != ElaboratedTypeKeyword::None) {
261*7a6dacacSDimitry Andric Fragments
262*7a6dacacSDimitry Andric .append(ElaboratedType::getKeywordName(Keyword),
263*7a6dacacSDimitry Andric DeclarationFragments::FragmentKind::Keyword)
264*7a6dacacSDimitry Andric .appendSpace();
265*7a6dacacSDimitry Andric }
266*7a6dacacSDimitry Andric
267*7a6dacacSDimitry Andric if (const NestedNameSpecifier *NNS = ET->getQualifier())
268*7a6dacacSDimitry Andric Fragments.append(getFragmentsForNNS(NNS, Context, After));
269*7a6dacacSDimitry Andric
270*7a6dacacSDimitry Andric // After handling the elaborated keyword or qualified name, build
271*7a6dacacSDimitry Andric // declaration fragments for the desugared underlying type.
272*7a6dacacSDimitry Andric return Fragments.append(getFragmentsForType(ET->desugar(), Context, After));
273*7a6dacacSDimitry Andric }
274*7a6dacacSDimitry Andric
275*7a6dacacSDimitry Andric // If the type is a typedefed type, get the underlying TypedefNameDecl for a
276*7a6dacacSDimitry Andric // direct reference to the typedef instead of the wrapped type.
277*7a6dacacSDimitry Andric
278*7a6dacacSDimitry Andric // 'id' type is a typedef for an ObjCObjectPointerType
279*7a6dacacSDimitry Andric // we treat it as a typedef
280*7a6dacacSDimitry Andric if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
281*7a6dacacSDimitry Andric const TypedefNameDecl *Decl = TypedefTy->getDecl();
282*7a6dacacSDimitry Andric TypedefUnderlyingTypeResolver TypedefResolver(Context);
283*7a6dacacSDimitry Andric std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));
284*7a6dacacSDimitry Andric
285*7a6dacacSDimitry Andric if (T->isObjCIdType()) {
286*7a6dacacSDimitry Andric return Fragments.append(Decl->getName(),
287*7a6dacacSDimitry Andric DeclarationFragments::FragmentKind::Keyword);
288*7a6dacacSDimitry Andric }
289*7a6dacacSDimitry Andric
290*7a6dacacSDimitry Andric return Fragments.append(
291*7a6dacacSDimitry Andric Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier,
292*7a6dacacSDimitry Andric USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));
293*7a6dacacSDimitry Andric }
294*7a6dacacSDimitry Andric
29581ad6265SDimitry Andric // Declaration fragments of a pointer type is the declaration fragments of
29606c3fb27SDimitry Andric // the pointee type followed by a `*`,
2975f757f3fSDimitry Andric if (T->isPointerType() && !T->isFunctionPointerType())
29881ad6265SDimitry Andric return Fragments
29981ad6265SDimitry Andric .append(getFragmentsForType(T->getPointeeType(), Context, After))
30081ad6265SDimitry Andric .append(" *", DeclarationFragments::FragmentKind::Text);
30106c3fb27SDimitry Andric
30206c3fb27SDimitry Andric // For Objective-C `id` and `Class` pointers
30306c3fb27SDimitry Andric // we do not spell out the `*`.
30406c3fb27SDimitry Andric if (T->isObjCObjectPointerType() &&
30506c3fb27SDimitry Andric !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {
30606c3fb27SDimitry Andric
30706c3fb27SDimitry Andric Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After));
30806c3fb27SDimitry Andric
30906c3fb27SDimitry Andric // id<protocol> is an qualified id type
31006c3fb27SDimitry Andric // id<protocol>* is not an qualified id type
31106c3fb27SDimitry Andric if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {
31206c3fb27SDimitry Andric Fragments.append(" *", DeclarationFragments::FragmentKind::Text);
31306c3fb27SDimitry Andric }
31406c3fb27SDimitry Andric
31506c3fb27SDimitry 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()) {
3455f757f3fSDimitry Andric case ArraySizeModifier::Normal:
34681ad6265SDimitry Andric break;
3475f757f3fSDimitry Andric case ArraySizeModifier::Static:
34881ad6265SDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword);
34981ad6265SDimitry Andric break;
3505f757f3fSDimitry 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
37106c3fb27SDimitry Andric // Everything we care about has been handled now, reduce to the canonical
37206c3fb27SDimitry Andric // unqualified base type.
37306c3fb27SDimitry Andric QualType Base = T->getCanonicalTypeUnqualified();
37406c3fb27SDimitry Andric
37581ad6265SDimitry Andric // If the base type is a TagType (struct/interface/union/class/enum), let's
37681ad6265SDimitry Andric // get the underlying Decl for better names and USRs.
37781ad6265SDimitry Andric if (const TagType *TagTy = dyn_cast<TagType>(Base)) {
37881ad6265SDimitry Andric const TagDecl *Decl = TagTy->getDecl();
37981ad6265SDimitry Andric // Anonymous decl, skip this fragment.
38081ad6265SDimitry Andric if (Decl->getName().empty())
38181ad6265SDimitry Andric return Fragments;
38281ad6265SDimitry Andric SmallString<128> TagUSR;
38381ad6265SDimitry Andric clang::index::generateUSRForDecl(Decl, TagUSR);
38481ad6265SDimitry Andric return Fragments.append(Decl->getName(),
38581ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier,
386bdd1243dSDimitry Andric TagUSR, Decl);
38781ad6265SDimitry Andric }
38881ad6265SDimitry Andric
38981ad6265SDimitry Andric // If the base type is an ObjCInterfaceType, use the underlying
39081ad6265SDimitry Andric // ObjCInterfaceDecl for the true USR.
39181ad6265SDimitry Andric if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
39281ad6265SDimitry Andric const auto *Decl = ObjCIT->getDecl();
39381ad6265SDimitry Andric SmallString<128> USR;
39481ad6265SDimitry Andric index::generateUSRForDecl(Decl, USR);
39581ad6265SDimitry Andric return Fragments.append(Decl->getName(),
39681ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier,
397bdd1243dSDimitry Andric USR, Decl);
39881ad6265SDimitry Andric }
39981ad6265SDimitry Andric
40081ad6265SDimitry Andric // Default fragment builder for other kinds of types (BuiltinType etc.)
40181ad6265SDimitry Andric SmallString<128> USR;
40281ad6265SDimitry Andric clang::index::generateUSRForType(Base, Context, USR);
40381ad6265SDimitry Andric Fragments.append(Base.getAsString(),
40481ad6265SDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier, USR);
40581ad6265SDimitry Andric
40681ad6265SDimitry Andric return Fragments;
40781ad6265SDimitry Andric }
40881ad6265SDimitry Andric
40981ad6265SDimitry Andric DeclarationFragments
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);
4365f757f3fSDimitry Andric if (QT.getAsString() == "_Bool")
4375f757f3fSDimitry Andric TypeFragments.replace("bool", 0);
4385f757f3fSDimitry 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)4655f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
4665f757f3fSDimitry Andric const NamespaceDecl *Decl) {
4675f757f3fSDimitry Andric DeclarationFragments Fragments;
4685f757f3fSDimitry Andric Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword);
4695f757f3fSDimitry Andric if (!Decl->isAnonymousNamespace())
4705f757f3fSDimitry Andric Fragments.appendSpace().append(
4715f757f3fSDimitry Andric Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
4725f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
4735f757f3fSDimitry Andric }
4745f757f3fSDimitry Andric
47581ad6265SDimitry Andric DeclarationFragments
getFragmentsForVar(const VarDecl * Var)47681ad6265SDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
47781ad6265SDimitry Andric DeclarationFragments Fragments;
4785f757f3fSDimitry Andric if (Var->isConstexpr())
4795f757f3fSDimitry Andric Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
4805f757f3fSDimitry Andric .appendSpace();
4815f757f3fSDimitry 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;
4955f757f3fSDimitry Andric FunctionTypeLoc BlockLoc;
4965f757f3fSDimitry Andric FunctionProtoTypeLoc BlockProtoLoc;
4975f757f3fSDimitry Andric findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc);
4985f757f3fSDimitry Andric
4995f757f3fSDimitry Andric if (!BlockLoc) {
5005f757f3fSDimitry Andric QualType T = Var->getTypeSourceInfo()
5015f757f3fSDimitry Andric ? Var->getTypeSourceInfo()->getType()
5025f757f3fSDimitry Andric : Var->getASTContext().getUnqualifiedObjCPointerType(
5035f757f3fSDimitry Andric Var->getType());
5045f757f3fSDimitry Andric
5055f757f3fSDimitry Andric Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))
5065f757f3fSDimitry Andric .appendSpace();
5075f757f3fSDimitry Andric } else {
5085f757f3fSDimitry Andric Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));
5095f757f3fSDimitry Andric }
5105f757f3fSDimitry Andric
5115f757f3fSDimitry Andric return Fragments
5125f757f3fSDimitry Andric .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
5135f757f3fSDimitry Andric .append(std::move(After))
5145f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text);
5155f757f3fSDimitry Andric }
5165f757f3fSDimitry Andric
5175f757f3fSDimitry Andric DeclarationFragments
getFragmentsForVarTemplate(const VarDecl * Var)5185f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
5195f757f3fSDimitry Andric DeclarationFragments Fragments;
5205f757f3fSDimitry Andric if (Var->isConstexpr())
5215f757f3fSDimitry Andric Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
5225f757f3fSDimitry Andric .appendSpace();
5235f757f3fSDimitry Andric QualType T =
5245f757f3fSDimitry Andric Var->getTypeSourceInfo()
5255f757f3fSDimitry Andric ? Var->getTypeSourceInfo()->getType()
5265f757f3fSDimitry Andric : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());
5275f757f3fSDimitry Andric
5285f757f3fSDimitry Andric // Might be a member, so might be static.
5295f757f3fSDimitry Andric if (Var->isStaticDataMember())
5305f757f3fSDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
5315f757f3fSDimitry Andric .appendSpace();
5325f757f3fSDimitry Andric
5335f757f3fSDimitry Andric DeclarationFragments After;
5345f757f3fSDimitry Andric DeclarationFragments ArgumentFragment =
5355f757f3fSDimitry Andric getFragmentsForType(T, Var->getASTContext(), After);
5365f757f3fSDimitry Andric if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare(
5375f757f3fSDimitry Andric "type-parameter") == 0) {
5385f757f3fSDimitry Andric std::string ProperArgName = getNameForTemplateArgument(
5395f757f3fSDimitry Andric Var->getDescribedVarTemplate()->getTemplateParameters()->asArray(),
5405f757f3fSDimitry Andric ArgumentFragment.begin()->Spelling);
5415f757f3fSDimitry Andric ArgumentFragment.begin()->Spelling.swap(ProperArgName);
5425f757f3fSDimitry Andric }
5435f757f3fSDimitry Andric Fragments.append(std::move(ArgumentFragment))
54481ad6265SDimitry Andric .appendSpace()
54581ad6265SDimitry Andric .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
5465f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text);
5475f757f3fSDimitry 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
5545f757f3fSDimitry Andric auto *TSInfo = Param->getTypeSourceInfo();
5555f757f3fSDimitry Andric
5565f757f3fSDimitry Andric QualType T = TSInfo ? TSInfo->getType()
55781ad6265SDimitry Andric : Param->getASTContext().getUnqualifiedObjCPointerType(
55881ad6265SDimitry Andric Param->getType());
55981ad6265SDimitry Andric
5605f757f3fSDimitry Andric FunctionTypeLoc BlockLoc;
5615f757f3fSDimitry Andric FunctionProtoTypeLoc BlockProtoLoc;
5625f757f3fSDimitry Andric findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);
56381ad6265SDimitry Andric
5645f757f3fSDimitry Andric DeclarationFragments TypeFragments;
5655f757f3fSDimitry Andric if (BlockLoc)
5665f757f3fSDimitry Andric TypeFragments.append(
5675f757f3fSDimitry Andric getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
5685f757f3fSDimitry Andric else
5695f757f3fSDimitry Andric TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After));
5705f757f3fSDimitry Andric
5715f757f3fSDimitry Andric if (TypeFragments.begin()->Spelling.substr(0, 14).compare("type-parameter") ==
5725f757f3fSDimitry Andric 0) {
5735f757f3fSDimitry Andric std::string ProperArgName = getNameForTemplateArgument(
5745f757f3fSDimitry Andric dyn_cast<FunctionDecl>(Param->getDeclContext())
5755f757f3fSDimitry Andric ->getDescribedFunctionTemplate()
5765f757f3fSDimitry Andric ->getTemplateParameters()
5775f757f3fSDimitry Andric ->asArray(),
5785f757f3fSDimitry Andric TypeFragments.begin()->Spelling);
5795f757f3fSDimitry Andric TypeFragments.begin()->Spelling.swap(ProperArgName);
5805f757f3fSDimitry Andric }
5815f757f3fSDimitry Andric
5825f757f3fSDimitry Andric if (Param->isObjCMethodParameter()) {
58381ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text)
58481ad6265SDimitry Andric .append(std::move(TypeFragments))
5855f757f3fSDimitry Andric .append(std::move(After))
5865f757f3fSDimitry Andric .append(") ", DeclarationFragments::FragmentKind::Text)
5875f757f3fSDimitry Andric .append(Param->getName(),
5885f757f3fSDimitry Andric DeclarationFragments::FragmentKind::InternalParam);
5895f757f3fSDimitry Andric } else {
5905f757f3fSDimitry Andric Fragments.append(std::move(TypeFragments));
5915f757f3fSDimitry Andric if (!T->isBlockPointerType())
5925f757f3fSDimitry Andric Fragments.appendSpace();
5935f757f3fSDimitry Andric Fragments
59481ad6265SDimitry Andric .append(Param->getName(),
59581ad6265SDimitry Andric DeclarationFragments::FragmentKind::InternalParam)
59681ad6265SDimitry Andric .append(std::move(After));
59781ad6265SDimitry Andric }
5985f757f3fSDimitry Andric return Fragments;
5995f757f3fSDimitry Andric }
6005f757f3fSDimitry Andric
getFragmentsForBlock(const NamedDecl * BlockDecl,FunctionTypeLoc & Block,FunctionProtoTypeLoc & BlockProto,DeclarationFragments & After)6015f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock(
6025f757f3fSDimitry Andric const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
6035f757f3fSDimitry Andric FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) {
6045f757f3fSDimitry Andric DeclarationFragments Fragments;
6055f757f3fSDimitry Andric
6065f757f3fSDimitry Andric DeclarationFragments RetTyAfter;
6075f757f3fSDimitry Andric auto ReturnValueFragment = getFragmentsForType(
6085f757f3fSDimitry Andric Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After);
6095f757f3fSDimitry Andric
6105f757f3fSDimitry Andric Fragments.append(std::move(ReturnValueFragment))
6115f757f3fSDimitry Andric .append(std::move(RetTyAfter))
6125f757f3fSDimitry Andric .appendSpace()
6135f757f3fSDimitry Andric .append("(^", DeclarationFragments::FragmentKind::Text);
6145f757f3fSDimitry Andric
6155f757f3fSDimitry Andric After.append(")", DeclarationFragments::FragmentKind::Text);
6165f757f3fSDimitry Andric unsigned NumParams = Block.getNumParams();
6175f757f3fSDimitry Andric
6185f757f3fSDimitry Andric if (!BlockProto || NumParams == 0) {
6195f757f3fSDimitry Andric if (BlockProto && BlockProto.getTypePtr()->isVariadic())
6205f757f3fSDimitry Andric After.append("(...)", DeclarationFragments::FragmentKind::Text);
6215f757f3fSDimitry Andric else
6225f757f3fSDimitry Andric After.append("()", DeclarationFragments::FragmentKind::Text);
6235f757f3fSDimitry Andric } else {
6245f757f3fSDimitry Andric After.append("(", DeclarationFragments::FragmentKind::Text);
6255f757f3fSDimitry Andric for (unsigned I = 0; I != NumParams; ++I) {
6265f757f3fSDimitry Andric if (I)
6275f757f3fSDimitry Andric After.append(", ", DeclarationFragments::FragmentKind::Text);
6285f757f3fSDimitry Andric After.append(getFragmentsForParam(Block.getParam(I)));
6295f757f3fSDimitry Andric if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic())
6305f757f3fSDimitry Andric After.append(", ...", DeclarationFragments::FragmentKind::Text);
6315f757f3fSDimitry Andric }
6325f757f3fSDimitry Andric After.append(")", DeclarationFragments::FragmentKind::Text);
6335f757f3fSDimitry Andric }
6345f757f3fSDimitry Andric
6355f757f3fSDimitry Andric return Fragments;
6365f757f3fSDimitry 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 }
6585f757f3fSDimitry Andric if (Func->isConsteval()) // if consteval, it is also constexpr
6595f757f3fSDimitry Andric Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword)
6605f757f3fSDimitry Andric .appendSpace();
6615f757f3fSDimitry Andric else if (Func->isConstexpr())
6625f757f3fSDimitry Andric Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
6635f757f3fSDimitry Andric .appendSpace();
66481ad6265SDimitry Andric
66581ad6265SDimitry Andric // FIXME: Is `after` actually needed here?
66681ad6265SDimitry Andric DeclarationFragments After;
6675f757f3fSDimitry Andric auto ReturnValueFragment =
6685f757f3fSDimitry Andric getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After);
6695f757f3fSDimitry Andric if (ReturnValueFragment.begin()->Spelling.substr(0, 14).compare(
6705f757f3fSDimitry Andric "type-parameter") == 0) {
6715f757f3fSDimitry Andric std::string ProperArgName =
6725f757f3fSDimitry Andric getNameForTemplateArgument(Func->getDescribedFunctionTemplate()
6735f757f3fSDimitry Andric ->getTemplateParameters()
6745f757f3fSDimitry Andric ->asArray(),
6755f757f3fSDimitry Andric ReturnValueFragment.begin()->Spelling);
6765f757f3fSDimitry Andric ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
6775f757f3fSDimitry Andric }
6785f757f3fSDimitry Andric
6795f757f3fSDimitry Andric Fragments.append(std::move(ReturnValueFragment))
68081ad6265SDimitry Andric .appendSpace()
6815f757f3fSDimitry Andric .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier);
6825f757f3fSDimitry Andric
6835f757f3fSDimitry Andric if (Func->getTemplateSpecializationInfo()) {
6845f757f3fSDimitry Andric Fragments.append("<", DeclarationFragments::FragmentKind::Text);
6855f757f3fSDimitry Andric
6865f757f3fSDimitry Andric for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
6875f757f3fSDimitry Andric if (i)
6885f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
6895f757f3fSDimitry Andric Fragments.append(
6905f757f3fSDimitry Andric getFragmentsForType(Func->getParamDecl(i)->getType(),
6915f757f3fSDimitry Andric Func->getParamDecl(i)->getASTContext(), After));
6925f757f3fSDimitry Andric }
6935f757f3fSDimitry Andric Fragments.append(">", DeclarationFragments::FragmentKind::Text);
6945f757f3fSDimitry Andric }
6955f757f3fSDimitry Andric Fragments.append(std::move(After));
69681ad6265SDimitry Andric
69781ad6265SDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text);
6985f757f3fSDimitry Andric unsigned NumParams = Func->getNumParams();
6995f757f3fSDimitry 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 }
7045f757f3fSDimitry Andric
7055f757f3fSDimitry Andric if (Func->isVariadic()) {
7065f757f3fSDimitry Andric if (NumParams > 0)
7075f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
7085f757f3fSDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text);
7095f757f3fSDimitry Andric }
71081ad6265SDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text);
71181ad6265SDimitry Andric
7125f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getExceptionSpecificationString(
7135f757f3fSDimitry Andric Func->getExceptionSpecType()));
7145f757f3fSDimitry Andric
71506c3fb27SDimitry 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
74406c3fb27SDimitry 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;
7505f757f3fSDimitry Andric DeclarationFragments Fragments;
7515f757f3fSDimitry Andric if (Field->isMutable())
7525f757f3fSDimitry Andric Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword)
7535f757f3fSDimitry Andric .appendSpace();
7545f757f3fSDimitry Andric return Fragments
7555f757f3fSDimitry Andric .append(
7565f757f3fSDimitry Andric getFragmentsForType(Field->getType(), Field->getASTContext(), After))
75781ad6265SDimitry Andric .appendSpace()
75881ad6265SDimitry Andric .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
7595f757f3fSDimitry Andric .append(std::move(After))
7605f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text);
76181ad6265SDimitry Andric }
76281ad6265SDimitry Andric
getFragmentsForRecordDecl(const RecordDecl * Record)763*7a6dacacSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
764*7a6dacacSDimitry Andric const RecordDecl *Record) {
76581ad6265SDimitry Andric if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
76681ad6265SDimitry Andric return getFragmentsForTypedef(TypedefNameDecl);
76781ad6265SDimitry Andric
76881ad6265SDimitry Andric DeclarationFragments Fragments;
769*7a6dacacSDimitry Andric if (Record->isUnion())
770*7a6dacacSDimitry Andric Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
771*7a6dacacSDimitry 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);
77706c3fb27SDimitry Andric
77806c3fb27SDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
77981ad6265SDimitry Andric }
78081ad6265SDimitry Andric
getFragmentsForCXXClass(const CXXRecordDecl * Record)7815f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
7825f757f3fSDimitry Andric const CXXRecordDecl *Record) {
7835f757f3fSDimitry Andric if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
7845f757f3fSDimitry Andric return getFragmentsForTypedef(TypedefNameDecl);
7855f757f3fSDimitry Andric
7865f757f3fSDimitry Andric DeclarationFragments Fragments;
7875f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getStructureTypeFragment(Record));
7885f757f3fSDimitry Andric
7895f757f3fSDimitry Andric if (!Record->getName().empty())
7905f757f3fSDimitry Andric Fragments.appendSpace().append(
7915f757f3fSDimitry Andric Record->getName(), DeclarationFragments::FragmentKind::Identifier);
7925f757f3fSDimitry Andric
7935f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
7945f757f3fSDimitry Andric }
7955f757f3fSDimitry Andric
7965f757f3fSDimitry Andric DeclarationFragments
getFragmentsForSpecialCXXMethod(const CXXMethodDecl * Method)7975f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
7985f757f3fSDimitry Andric const CXXMethodDecl *Method) {
7995f757f3fSDimitry Andric DeclarationFragments Fragments;
8005f757f3fSDimitry Andric std::string Name;
8015f757f3fSDimitry Andric if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) {
8025f757f3fSDimitry Andric Name = Method->getNameAsString();
8035f757f3fSDimitry Andric if (Constructor->isExplicit())
8045f757f3fSDimitry Andric Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
8055f757f3fSDimitry Andric .appendSpace();
8065f757f3fSDimitry Andric } else if (isa<CXXDestructorDecl>(Method))
8075f757f3fSDimitry Andric Name = Method->getNameAsString();
8085f757f3fSDimitry Andric
8095f757f3fSDimitry Andric DeclarationFragments After;
8105f757f3fSDimitry Andric Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier)
8115f757f3fSDimitry Andric .append(std::move(After));
8125f757f3fSDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text);
8135f757f3fSDimitry Andric for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
8145f757f3fSDimitry Andric if (i)
8155f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
8165f757f3fSDimitry Andric Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
8175f757f3fSDimitry Andric }
8185f757f3fSDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text);
8195f757f3fSDimitry Andric
8205f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getExceptionSpecificationString(
8215f757f3fSDimitry Andric Method->getExceptionSpecType()));
8225f757f3fSDimitry Andric
8235f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
8245f757f3fSDimitry Andric }
8255f757f3fSDimitry Andric
getFragmentsForCXXMethod(const CXXMethodDecl * Method)8265f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
8275f757f3fSDimitry Andric const CXXMethodDecl *Method) {
8285f757f3fSDimitry Andric DeclarationFragments Fragments;
8295f757f3fSDimitry Andric StringRef Name = Method->getName();
8305f757f3fSDimitry Andric if (Method->isStatic())
8315f757f3fSDimitry Andric Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
8325f757f3fSDimitry Andric .appendSpace();
8335f757f3fSDimitry Andric if (Method->isConstexpr())
8345f757f3fSDimitry Andric Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
8355f757f3fSDimitry Andric .appendSpace();
8365f757f3fSDimitry Andric if (Method->isVolatile())
8375f757f3fSDimitry Andric Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword)
8385f757f3fSDimitry Andric .appendSpace();
8395f757f3fSDimitry Andric
8405f757f3fSDimitry Andric // Build return type
8415f757f3fSDimitry Andric DeclarationFragments After;
8425f757f3fSDimitry Andric Fragments
8435f757f3fSDimitry Andric .append(getFragmentsForType(Method->getReturnType(),
8445f757f3fSDimitry Andric Method->getASTContext(), After))
8455f757f3fSDimitry Andric .appendSpace()
8465f757f3fSDimitry Andric .append(Name, DeclarationFragments::FragmentKind::Identifier)
8475f757f3fSDimitry Andric .append(std::move(After));
8485f757f3fSDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text);
8495f757f3fSDimitry Andric for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
8505f757f3fSDimitry Andric if (i)
8515f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
8525f757f3fSDimitry Andric Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
8535f757f3fSDimitry Andric }
8545f757f3fSDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text);
8555f757f3fSDimitry Andric
8565f757f3fSDimitry Andric if (Method->isConst())
8575f757f3fSDimitry Andric Fragments.appendSpace().append("const",
8585f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Keyword);
8595f757f3fSDimitry Andric
8605f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getExceptionSpecificationString(
8615f757f3fSDimitry Andric Method->getExceptionSpecType()));
8625f757f3fSDimitry Andric
8635f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
8645f757f3fSDimitry Andric }
8655f757f3fSDimitry Andric
8665f757f3fSDimitry Andric DeclarationFragments
getFragmentsForConversionFunction(const CXXConversionDecl * ConversionFunction)8675f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
8685f757f3fSDimitry Andric const CXXConversionDecl *ConversionFunction) {
8695f757f3fSDimitry Andric DeclarationFragments Fragments;
8705f757f3fSDimitry Andric
8715f757f3fSDimitry Andric if (ConversionFunction->isExplicit())
8725f757f3fSDimitry Andric Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
8735f757f3fSDimitry Andric .appendSpace();
8745f757f3fSDimitry Andric
8755f757f3fSDimitry Andric Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword)
8765f757f3fSDimitry Andric .appendSpace();
8775f757f3fSDimitry Andric
8785f757f3fSDimitry Andric Fragments
8795f757f3fSDimitry Andric .append(ConversionFunction->getConversionType().getAsString(),
8805f757f3fSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier)
8815f757f3fSDimitry Andric .append("(", DeclarationFragments::FragmentKind::Text);
8825f757f3fSDimitry Andric for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
8835f757f3fSDimitry Andric ++i) {
8845f757f3fSDimitry Andric if (i)
8855f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
8865f757f3fSDimitry Andric Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
8875f757f3fSDimitry Andric }
8885f757f3fSDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text);
8895f757f3fSDimitry Andric
8905f757f3fSDimitry Andric if (ConversionFunction->isConst())
8915f757f3fSDimitry Andric Fragments.appendSpace().append("const",
8925f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Keyword);
8935f757f3fSDimitry Andric
8945f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
8955f757f3fSDimitry Andric }
8965f757f3fSDimitry Andric
8975f757f3fSDimitry Andric DeclarationFragments
getFragmentsForOverloadedOperator(const CXXMethodDecl * Method)8985f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
8995f757f3fSDimitry Andric const CXXMethodDecl *Method) {
9005f757f3fSDimitry Andric DeclarationFragments Fragments;
9015f757f3fSDimitry Andric
9025f757f3fSDimitry Andric // Build return type
9035f757f3fSDimitry Andric DeclarationFragments After;
9045f757f3fSDimitry Andric Fragments
9055f757f3fSDimitry Andric .append(getFragmentsForType(Method->getReturnType(),
9065f757f3fSDimitry Andric Method->getASTContext(), After))
9075f757f3fSDimitry Andric .appendSpace()
9085f757f3fSDimitry Andric .append(Method->getNameAsString(),
9095f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier)
9105f757f3fSDimitry Andric .append(std::move(After));
9115f757f3fSDimitry Andric Fragments.append("(", DeclarationFragments::FragmentKind::Text);
9125f757f3fSDimitry Andric for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
9135f757f3fSDimitry Andric if (i)
9145f757f3fSDimitry Andric Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
9155f757f3fSDimitry Andric Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
9165f757f3fSDimitry Andric }
9175f757f3fSDimitry Andric Fragments.append(")", DeclarationFragments::FragmentKind::Text);
9185f757f3fSDimitry Andric
9195f757f3fSDimitry Andric if (Method->isConst())
9205f757f3fSDimitry Andric Fragments.appendSpace().append("const",
9215f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Keyword);
9225f757f3fSDimitry Andric
9235f757f3fSDimitry Andric Fragments.append(DeclarationFragments::getExceptionSpecificationString(
9245f757f3fSDimitry Andric Method->getExceptionSpecType()));
9255f757f3fSDimitry Andric
9265f757f3fSDimitry Andric return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
9275f757f3fSDimitry Andric }
9285f757f3fSDimitry Andric
9295f757f3fSDimitry Andric // Get fragments for template parameters, e.g. T in tempalte<typename T> ...
9305f757f3fSDimitry Andric DeclarationFragments
getFragmentsForTemplateParameters(ArrayRef<NamedDecl * > ParameterArray)9315f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(
9325f757f3fSDimitry Andric ArrayRef<NamedDecl *> ParameterArray) {
9335f757f3fSDimitry Andric DeclarationFragments Fragments;
9345f757f3fSDimitry Andric for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {
9355f757f3fSDimitry Andric if (i)
9365f757f3fSDimitry Andric Fragments.append(",", DeclarationFragments::FragmentKind::Text)
9375f757f3fSDimitry Andric .appendSpace();
9385f757f3fSDimitry Andric
9395f757f3fSDimitry Andric const auto *TemplateParam =
9405f757f3fSDimitry Andric dyn_cast<TemplateTypeParmDecl>(ParameterArray[i]);
9415f757f3fSDimitry Andric if (!TemplateParam)
9425f757f3fSDimitry Andric continue;
9435f757f3fSDimitry Andric if (TemplateParam->hasTypeConstraint())
9445f757f3fSDimitry Andric Fragments.append(TemplateParam->getTypeConstraint()
9455f757f3fSDimitry Andric ->getNamedConcept()
9465f757f3fSDimitry Andric ->getName()
9475f757f3fSDimitry Andric .str(),
9485f757f3fSDimitry Andric DeclarationFragments::FragmentKind::TypeIdentifier);
9495f757f3fSDimitry Andric else if (TemplateParam->wasDeclaredWithTypename())
9505f757f3fSDimitry Andric Fragments.append("typename", DeclarationFragments::FragmentKind::Keyword);
9515f757f3fSDimitry Andric else
9525f757f3fSDimitry Andric Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
9535f757f3fSDimitry Andric
9545f757f3fSDimitry Andric if (TemplateParam->isParameterPack())
9555f757f3fSDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text);
9565f757f3fSDimitry Andric
9575f757f3fSDimitry Andric Fragments.appendSpace().append(
9585f757f3fSDimitry Andric TemplateParam->getName(),
9595f757f3fSDimitry Andric DeclarationFragments::FragmentKind::GenericParameter);
9605f757f3fSDimitry Andric }
9615f757f3fSDimitry Andric return Fragments;
9625f757f3fSDimitry Andric }
9635f757f3fSDimitry Andric
9645f757f3fSDimitry Andric // Find the name of a template argument from the template's parameters.
getNameForTemplateArgument(const ArrayRef<NamedDecl * > TemplateParameters,std::string TypeParameter)9655f757f3fSDimitry Andric std::string DeclarationFragmentsBuilder::getNameForTemplateArgument(
9665f757f3fSDimitry Andric const ArrayRef<NamedDecl *> TemplateParameters, std::string TypeParameter) {
9675f757f3fSDimitry Andric // The arg is a generic parameter from a partial spec, e.g.
9685f757f3fSDimitry Andric // T in template<typename T> Foo<T, int>.
9695f757f3fSDimitry Andric //
9705f757f3fSDimitry Andric // Those names appear as "type-parameter-<index>-<depth>", so we must find its
9715f757f3fSDimitry Andric // name from the template's parameter list.
9725f757f3fSDimitry Andric for (unsigned i = 0; i < TemplateParameters.size(); ++i) {
9735f757f3fSDimitry Andric const auto *Parameter =
9745f757f3fSDimitry Andric dyn_cast<TemplateTypeParmDecl>(TemplateParameters[i]);
9755f757f3fSDimitry Andric if (TypeParameter.compare("type-parameter-" +
9765f757f3fSDimitry Andric std::to_string(Parameter->getDepth()) + "-" +
9775f757f3fSDimitry Andric std::to_string(Parameter->getIndex())) == 0)
9785f757f3fSDimitry Andric return std::string(TemplateParameters[i]->getName());
9795f757f3fSDimitry Andric }
9805f757f3fSDimitry Andric llvm_unreachable("Could not find the name of a template argument.");
9815f757f3fSDimitry Andric }
9825f757f3fSDimitry Andric
9835f757f3fSDimitry Andric // Get fragments for template arguments, e.g. int in template<typename T>
9845f757f3fSDimitry Andric // Foo<int>;
9855f757f3fSDimitry Andric //
9865f757f3fSDimitry Andric // Note: TemplateParameters is only necessary if the Decl is a
9875f757f3fSDimitry Andric // PartialSpecialization, where we need the parameters to deduce the name of the
9885f757f3fSDimitry Andric // generic arguments.
9895f757f3fSDimitry Andric DeclarationFragments
getFragmentsForTemplateArguments(const ArrayRef<TemplateArgument> TemplateArguments,ASTContext & Context,const std::optional<ArrayRef<NamedDecl * >> TemplateParameters)9905f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForTemplateArguments(
9915f757f3fSDimitry Andric const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context,
9925f757f3fSDimitry Andric const std::optional<ArrayRef<NamedDecl *>> TemplateParameters) {
9935f757f3fSDimitry Andric DeclarationFragments Fragments;
9945f757f3fSDimitry Andric for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
9955f757f3fSDimitry Andric if (i)
9965f757f3fSDimitry Andric Fragments.append(",", DeclarationFragments::FragmentKind::Text)
9975f757f3fSDimitry Andric .appendSpace();
9985f757f3fSDimitry Andric
9995f757f3fSDimitry Andric std::string Type = TemplateArguments[i].getAsType().getAsString();
10005f757f3fSDimitry Andric DeclarationFragments After;
10015f757f3fSDimitry Andric DeclarationFragments ArgumentFragment =
10025f757f3fSDimitry Andric getFragmentsForType(TemplateArguments[i].getAsType(), Context, After);
10035f757f3fSDimitry Andric
10045f757f3fSDimitry Andric if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare(
10055f757f3fSDimitry Andric "type-parameter") == 0) {
10065f757f3fSDimitry Andric std::string ProperArgName = getNameForTemplateArgument(
10075f757f3fSDimitry Andric TemplateParameters.value(), ArgumentFragment.begin()->Spelling);
10085f757f3fSDimitry Andric ArgumentFragment.begin()->Spelling.swap(ProperArgName);
10095f757f3fSDimitry Andric }
10105f757f3fSDimitry Andric Fragments.append(std::move(ArgumentFragment));
10115f757f3fSDimitry Andric
10125f757f3fSDimitry Andric if (TemplateArguments[i].isPackExpansion())
10135f757f3fSDimitry Andric Fragments.append("...", DeclarationFragments::FragmentKind::Text);
10145f757f3fSDimitry Andric }
10155f757f3fSDimitry Andric return Fragments;
10165f757f3fSDimitry Andric }
10175f757f3fSDimitry Andric
getFragmentsForConcept(const ConceptDecl * Concept)10185f757f3fSDimitry Andric DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
10195f757f3fSDimitry Andric const ConceptDecl *Concept) {
10205f757f3fSDimitry Andric DeclarationFragments Fragments;
10215f757f3fSDimitry Andric return Fragments
10225f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword)
10235f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text)
10245f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters(
10255f757f3fSDimitry Andric Concept->getTemplateParameters()->asArray()))
10265f757f3fSDimitry Andric .append("> ", DeclarationFragments::FragmentKind::Text)
10275f757f3fSDimitry Andric .append("concept", DeclarationFragments::FragmentKind::Keyword)
10285f757f3fSDimitry Andric .appendSpace()
10295f757f3fSDimitry Andric .append(Concept->getName().str(),
10305f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier)
10315f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text);
10325f757f3fSDimitry Andric }
10335f757f3fSDimitry Andric
10345f757f3fSDimitry Andric DeclarationFragments
getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl * RedeclarableTemplate)10355f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
10365f757f3fSDimitry Andric const RedeclarableTemplateDecl *RedeclarableTemplate) {
10375f757f3fSDimitry Andric DeclarationFragments Fragments;
10385f757f3fSDimitry Andric Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
10395f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text)
10405f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters(
10415f757f3fSDimitry Andric RedeclarableTemplate->getTemplateParameters()->asArray()))
10425f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text)
10435f757f3fSDimitry Andric .appendSpace();
10445f757f3fSDimitry Andric
10455f757f3fSDimitry Andric if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate))
10465f757f3fSDimitry Andric Fragments.appendSpace()
10475f757f3fSDimitry Andric .append("using", DeclarationFragments::FragmentKind::Keyword)
10485f757f3fSDimitry Andric .appendSpace()
10495f757f3fSDimitry Andric .append(RedeclarableTemplate->getName(),
10505f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier);
10515f757f3fSDimitry Andric // the templated records will be resposbible for injecting their templates
10525f757f3fSDimitry Andric return Fragments.appendSpace();
10535f757f3fSDimitry Andric }
10545f757f3fSDimitry Andric
10555f757f3fSDimitry Andric DeclarationFragments
getFragmentsForClassTemplateSpecialization(const ClassTemplateSpecializationDecl * Decl)10565f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
10575f757f3fSDimitry Andric const ClassTemplateSpecializationDecl *Decl) {
10585f757f3fSDimitry Andric DeclarationFragments Fragments;
10595f757f3fSDimitry Andric return Fragments
10605f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword)
10615f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text)
10625f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text)
10635f757f3fSDimitry Andric .appendSpace()
10645f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
10655f757f3fSDimitry Andric cast<CXXRecordDecl>(Decl)))
10665f757f3fSDimitry Andric .pop_back() // there is an extra semicolon now
10675f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text)
10685f757f3fSDimitry Andric .append(
10695f757f3fSDimitry Andric getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
10705f757f3fSDimitry Andric Decl->getASTContext(), std::nullopt))
10715f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text)
10725f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text);
10735f757f3fSDimitry Andric }
10745f757f3fSDimitry Andric
10755f757f3fSDimitry Andric DeclarationFragments
getFragmentsForClassTemplatePartialSpecialization(const ClassTemplatePartialSpecializationDecl * Decl)10765f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
10775f757f3fSDimitry Andric const ClassTemplatePartialSpecializationDecl *Decl) {
10785f757f3fSDimitry Andric DeclarationFragments Fragments;
10795f757f3fSDimitry Andric return Fragments
10805f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword)
10815f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text)
10825f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters(
10835f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray()))
10845f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text)
10855f757f3fSDimitry Andric .appendSpace()
10865f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass(
10875f757f3fSDimitry Andric cast<CXXRecordDecl>(Decl)))
10885f757f3fSDimitry Andric .pop_back() // there is an extra semicolon now
10895f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text)
10905f757f3fSDimitry Andric .append(getFragmentsForTemplateArguments(
10915f757f3fSDimitry Andric Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
10925f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray()))
10935f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text)
10945f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text);
10955f757f3fSDimitry Andric }
10965f757f3fSDimitry Andric
10975f757f3fSDimitry Andric DeclarationFragments
getFragmentsForVarTemplateSpecialization(const VarTemplateSpecializationDecl * Decl)10985f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
10995f757f3fSDimitry Andric const VarTemplateSpecializationDecl *Decl) {
11005f757f3fSDimitry Andric DeclarationFragments Fragments;
11015f757f3fSDimitry Andric return Fragments
11025f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword)
11035f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text)
11045f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text)
11055f757f3fSDimitry Andric .appendSpace()
11065f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
11075f757f3fSDimitry Andric .pop_back() // there is an extra semicolon now
11085f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text)
11095f757f3fSDimitry Andric .append(
11105f757f3fSDimitry Andric getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
11115f757f3fSDimitry Andric Decl->getASTContext(), std::nullopt))
11125f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text)
11135f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text);
11145f757f3fSDimitry Andric }
11155f757f3fSDimitry Andric
11165f757f3fSDimitry Andric DeclarationFragments
getFragmentsForVarTemplatePartialSpecialization(const VarTemplatePartialSpecializationDecl * Decl)11175f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
11185f757f3fSDimitry Andric const VarTemplatePartialSpecializationDecl *Decl) {
11195f757f3fSDimitry Andric DeclarationFragments Fragments;
11205f757f3fSDimitry Andric return Fragments
11215f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword)
11225f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text)
11235f757f3fSDimitry Andric // Partial specs may have new params.
11245f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters(
11255f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray()))
11265f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text)
11275f757f3fSDimitry Andric .appendSpace()
11285f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl))
11295f757f3fSDimitry Andric .pop_back() // there is an extra semicolon now
11305f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text)
11315f757f3fSDimitry Andric .append(getFragmentsForTemplateArguments(
11325f757f3fSDimitry Andric Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
11335f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray()))
11345f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text)
11355f757f3fSDimitry Andric .append(";", DeclarationFragments::FragmentKind::Text);
11365f757f3fSDimitry Andric }
11375f757f3fSDimitry Andric
11385f757f3fSDimitry Andric DeclarationFragments
getFragmentsForFunctionTemplate(const FunctionTemplateDecl * Decl)11395f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
11405f757f3fSDimitry Andric const FunctionTemplateDecl *Decl) {
11415f757f3fSDimitry Andric DeclarationFragments Fragments;
11425f757f3fSDimitry Andric return Fragments
11435f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword)
11445f757f3fSDimitry Andric .append("<", DeclarationFragments::FragmentKind::Text)
11455f757f3fSDimitry Andric // Partial specs may have new params.
11465f757f3fSDimitry Andric .append(getFragmentsForTemplateParameters(
11475f757f3fSDimitry Andric Decl->getTemplateParameters()->asArray()))
11485f757f3fSDimitry Andric .append(">", DeclarationFragments::FragmentKind::Text)
11495f757f3fSDimitry Andric .appendSpace()
11505f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForFunction(
11515f757f3fSDimitry Andric Decl->getAsFunction()));
11525f757f3fSDimitry Andric }
11535f757f3fSDimitry Andric
11545f757f3fSDimitry Andric DeclarationFragments
getFragmentsForFunctionTemplateSpecialization(const FunctionDecl * Decl)11555f757f3fSDimitry Andric DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(
11565f757f3fSDimitry Andric const FunctionDecl *Decl) {
11575f757f3fSDimitry Andric DeclarationFragments Fragments;
11585f757f3fSDimitry Andric return Fragments
11595f757f3fSDimitry Andric .append("template", DeclarationFragments::FragmentKind::Keyword)
11605f757f3fSDimitry Andric .append("<>", DeclarationFragments::FragmentKind::Text)
11615f757f3fSDimitry Andric .appendSpace()
11625f757f3fSDimitry Andric .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl));
11635f757f3fSDimitry Andric }
11645f757f3fSDimitry 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
129006c3fb27SDimitry 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
13615f757f3fSDimitry Andric Fragments.appendSpace();
13625f757f3fSDimitry Andric
13635f757f3fSDimitry Andric FunctionTypeLoc BlockLoc;
13645f757f3fSDimitry Andric FunctionProtoTypeLoc BlockProtoLoc;
13655f757f3fSDimitry Andric findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc,
13665f757f3fSDimitry Andric BlockProtoLoc);
13675f757f3fSDimitry Andric
13685f757f3fSDimitry Andric auto PropType = Property->getType();
13695f757f3fSDimitry Andric if (!BlockLoc)
13705f757f3fSDimitry Andric Fragments
13715f757f3fSDimitry Andric .append(getFragmentsForType(PropType, Property->getASTContext(), After))
13725f757f3fSDimitry Andric .appendSpace();
13735f757f3fSDimitry Andric else
13745f757f3fSDimitry Andric Fragments.append(
13755f757f3fSDimitry Andric getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After));
13765f757f3fSDimitry Andric
13775f757f3fSDimitry Andric return Fragments
137881ad6265SDimitry Andric .append(Property->getName(),
137981ad6265SDimitry Andric DeclarationFragments::FragmentKind::Identifier)
13805f757f3fSDimitry Andric .append(std::move(After))
13815f757f3fSDimitry 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
142506c3fb27SDimitry 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;
14405f757f3fSDimitry Andric if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))
14415f757f3fSDimitry Andric Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(),
14425f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier);
14435f757f3fSDimitry Andric else if (isa<CXXConversionDecl>(Decl)) {
14445f757f3fSDimitry Andric Fragments.append(
14455f757f3fSDimitry Andric cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(),
14465f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier);
14475f757f3fSDimitry Andric } else if (isa<CXXMethodDecl>(Decl) &&
14485f757f3fSDimitry Andric cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) {
14495f757f3fSDimitry Andric Fragments.append(Decl->getNameAsString(),
14505f757f3fSDimitry Andric DeclarationFragments::FragmentKind::Identifier);
14515f757f3fSDimitry 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