1 //===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file implements Declaration Fragments related classes. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/ExtractAPI/DeclarationFragments.h" 15 #include "clang/Index/USRGeneration.h" 16 #include "llvm/ADT/StringSwitch.h" 17 18 using namespace clang::extractapi; 19 using namespace llvm; 20 21 DeclarationFragments &DeclarationFragments::appendSpace() { 22 if (!Fragments.empty()) { 23 Fragment Last = Fragments.back(); 24 if (Last.Kind == FragmentKind::Text) { 25 // Merge the extra space into the last fragment if the last fragment is 26 // also text. 27 if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces. 28 Last.Spelling.push_back(' '); 29 } 30 } else { 31 append(" ", FragmentKind::Text); 32 } 33 } 34 35 return *this; 36 } 37 38 StringRef DeclarationFragments::getFragmentKindString( 39 DeclarationFragments::FragmentKind Kind) { 40 switch (Kind) { 41 case DeclarationFragments::FragmentKind::None: 42 return "none"; 43 case DeclarationFragments::FragmentKind::Keyword: 44 return "keyword"; 45 case DeclarationFragments::FragmentKind::Attribute: 46 return "attribute"; 47 case DeclarationFragments::FragmentKind::NumberLiteral: 48 return "number"; 49 case DeclarationFragments::FragmentKind::StringLiteral: 50 return "string"; 51 case DeclarationFragments::FragmentKind::Identifier: 52 return "identifier"; 53 case DeclarationFragments::FragmentKind::TypeIdentifier: 54 return "typeIdentifier"; 55 case DeclarationFragments::FragmentKind::GenericParameter: 56 return "genericParameter"; 57 case DeclarationFragments::FragmentKind::ExternalParam: 58 return "externalParam"; 59 case DeclarationFragments::FragmentKind::InternalParam: 60 return "internalParam"; 61 case DeclarationFragments::FragmentKind::Text: 62 return "text"; 63 } 64 65 llvm_unreachable("Unhandled FragmentKind"); 66 } 67 68 DeclarationFragments::FragmentKind 69 DeclarationFragments::parseFragmentKindFromString(StringRef S) { 70 return llvm::StringSwitch<FragmentKind>(S) 71 .Case("keyword", DeclarationFragments::FragmentKind::Keyword) 72 .Case("attribute", DeclarationFragments::FragmentKind::Attribute) 73 .Case("number", DeclarationFragments::FragmentKind::NumberLiteral) 74 .Case("string", DeclarationFragments::FragmentKind::StringLiteral) 75 .Case("identifier", DeclarationFragments::FragmentKind::Identifier) 76 .Case("typeIdentifier", 77 DeclarationFragments::FragmentKind::TypeIdentifier) 78 .Case("genericParameter", 79 DeclarationFragments::FragmentKind::GenericParameter) 80 .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam) 81 .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam) 82 .Case("text", DeclarationFragments::FragmentKind::Text) 83 .Default(DeclarationFragments::FragmentKind::None); 84 } 85 86 // NNS stores C++ nested name specifiers, which are prefixes to qualified names. 87 // Build declaration fragments for NNS recursively so that we have the USR for 88 // every part in a qualified name, and also leaves the actual underlying type 89 // cleaner for its own fragment. 90 DeclarationFragments 91 DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS, 92 ASTContext &Context, 93 DeclarationFragments &After) { 94 DeclarationFragments Fragments; 95 if (NNS->getPrefix()) 96 Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After)); 97 98 switch (NNS->getKind()) { 99 case NestedNameSpecifier::Identifier: 100 Fragments.append(NNS->getAsIdentifier()->getName(), 101 DeclarationFragments::FragmentKind::Identifier); 102 break; 103 104 case NestedNameSpecifier::Namespace: { 105 const NamespaceDecl *NS = NNS->getAsNamespace(); 106 if (NS->isAnonymousNamespace()) 107 return Fragments; 108 SmallString<128> USR; 109 index::generateUSRForDecl(NS, USR); 110 Fragments.append(NS->getName(), 111 DeclarationFragments::FragmentKind::Identifier, USR); 112 break; 113 } 114 115 case NestedNameSpecifier::NamespaceAlias: { 116 const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias(); 117 SmallString<128> USR; 118 index::generateUSRForDecl(Alias, USR); 119 Fragments.append(Alias->getName(), 120 DeclarationFragments::FragmentKind::Identifier, USR); 121 break; 122 } 123 124 case NestedNameSpecifier::Global: 125 // The global specifier `::` at the beginning. No stored value. 126 break; 127 128 case NestedNameSpecifier::Super: 129 // Microsoft's `__super` specifier. 130 Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword); 131 break; 132 133 case NestedNameSpecifier::TypeSpecWithTemplate: 134 // A type prefixed by the `template` keyword. 135 Fragments.append("template", DeclarationFragments::FragmentKind::Keyword); 136 Fragments.appendSpace(); 137 // Fallthrough after adding the keyword to handle the actual type. 138 LLVM_FALLTHROUGH; 139 140 case NestedNameSpecifier::TypeSpec: { 141 const Type *T = NNS->getAsType(); 142 // FIXME: Handle C++ template specialization type 143 Fragments.append(getFragmentsForType(T, Context, After)); 144 break; 145 } 146 } 147 148 // Add the separator text `::` for this segment. 149 return Fragments.append("::", DeclarationFragments::FragmentKind::Text); 150 } 151 152 // Recursively build the declaration fragments for an underlying `Type` with 153 // qualifiers removed. 154 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 155 const Type *T, ASTContext &Context, DeclarationFragments &After) { 156 assert(T && "invalid type"); 157 158 DeclarationFragments Fragments; 159 160 // Declaration fragments of a pointer type is the declaration fragments of 161 // the pointee type followed by a `*`, except for Objective-C `id` and `Class` 162 // pointers, where we do not spell out the `*`. 163 if (T->isPointerType() || 164 (T->isObjCObjectPointerType() && 165 !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType())) { 166 return Fragments 167 .append(getFragmentsForType(T->getPointeeType(), Context, After)) 168 .append(" *", DeclarationFragments::FragmentKind::Text); 169 } 170 171 // Declaration fragments of a lvalue reference type is the declaration 172 // fragments of the underlying type followed by a `&`. 173 if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T)) 174 return Fragments 175 .append( 176 getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After)) 177 .append(" &", DeclarationFragments::FragmentKind::Text); 178 179 // Declaration fragments of a rvalue reference type is the declaration 180 // fragments of the underlying type followed by a `&&`. 181 if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T)) 182 return Fragments 183 .append( 184 getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After)) 185 .append(" &&", DeclarationFragments::FragmentKind::Text); 186 187 // Declaration fragments of an array-typed variable have two parts: 188 // 1. the element type of the array that appears before the variable name; 189 // 2. array brackets `[(0-9)?]` that appear after the variable name. 190 if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) { 191 // Build the "after" part first because the inner element type might also 192 // be an array-type. For example `int matrix[3][4]` which has a type of 193 // "(array 3 of (array 4 of ints))." 194 // Push the array size part first to make sure they are in the right order. 195 After.append("[", DeclarationFragments::FragmentKind::Text); 196 197 switch (AT->getSizeModifier()) { 198 case ArrayType::Normal: 199 break; 200 case ArrayType::Static: 201 Fragments.append("static", DeclarationFragments::FragmentKind::Keyword); 202 break; 203 case ArrayType::Star: 204 Fragments.append("*", DeclarationFragments::FragmentKind::Text); 205 break; 206 } 207 208 if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { 209 // FIXME: right now this would evaluate any expressions/macros written in 210 // the original source to concrete values. For example 211 // `int nums[MAX]` -> `int nums[100]` 212 // `char *str[5 + 1]` -> `char *str[6]` 213 SmallString<128> Size; 214 CAT->getSize().toStringUnsigned(Size); 215 After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral); 216 } 217 218 After.append("]", DeclarationFragments::FragmentKind::Text); 219 220 return Fragments.append( 221 getFragmentsForType(AT->getElementType(), Context, After)); 222 } 223 224 // An ElaboratedType is a sugar for types that are referred to using an 225 // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a 226 // qualified name, e.g., `N::M::type`, or both. 227 if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) { 228 ElaboratedTypeKeyword Keyword = ET->getKeyword(); 229 if (Keyword != ETK_None) { 230 Fragments 231 .append(ElaboratedType::getKeywordName(Keyword), 232 DeclarationFragments::FragmentKind::Keyword) 233 .appendSpace(); 234 } 235 236 if (const NestedNameSpecifier *NNS = ET->getQualifier()) 237 Fragments.append(getFragmentsForNNS(NNS, Context, After)); 238 239 // After handling the elaborated keyword or qualified name, build 240 // declaration fragments for the desugared underlying type. 241 return Fragments.append(getFragmentsForType(ET->desugar(), Context, After)); 242 } 243 244 // Everything we care about has been handled now, reduce to the canonical 245 // unqualified base type. 246 QualType Base = T->getCanonicalTypeUnqualified(); 247 248 // Default fragment builder for other kinds of types (BuiltinType etc.) 249 SmallString<128> USR; 250 clang::index::generateUSRForType(Base, Context, USR); 251 Fragments.append(Base.getAsString(), 252 DeclarationFragments::FragmentKind::TypeIdentifier, USR); 253 254 return Fragments; 255 } 256 257 DeclarationFragments 258 DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) { 259 DeclarationFragments Fragments; 260 if (Quals.hasConst()) 261 Fragments.append("const", DeclarationFragments::FragmentKind::Keyword); 262 if (Quals.hasVolatile()) 263 Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword); 264 if (Quals.hasRestrict()) 265 Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword); 266 267 return Fragments; 268 } 269 270 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( 271 const QualType QT, ASTContext &Context, DeclarationFragments &After) { 272 assert(!QT.isNull() && "invalid type"); 273 274 if (const ParenType *PT = dyn_cast<ParenType>(QT)) { 275 After.append(")", DeclarationFragments::FragmentKind::Text); 276 return getFragmentsForType(PT->getInnerType(), Context, After) 277 .append("(", DeclarationFragments::FragmentKind::Text); 278 } 279 280 const SplitQualType SQT = QT.split(); 281 DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals), 282 TypeFragments = 283 getFragmentsForType(SQT.Ty, Context, After); 284 if (QualsFragments.getFragments().empty()) 285 return TypeFragments; 286 287 // Use east qualifier for pointer types 288 // For example: 289 // ``` 290 // int * const 291 // ^---- ^---- 292 // type qualifier 293 // ^----------------- 294 // const pointer to int 295 // ``` 296 // should not be reconstructed as 297 // ``` 298 // const int * 299 // ^---- ^-- 300 // qualifier type 301 // ^---------------- ^ 302 // pointer to const int 303 // ``` 304 if (SQT.Ty->isAnyPointerType()) 305 return TypeFragments.appendSpace().append(std::move(QualsFragments)); 306 307 return QualsFragments.appendSpace().append(std::move(TypeFragments)); 308 } 309 310 DeclarationFragments 311 DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { 312 DeclarationFragments Fragments; 313 StorageClass SC = Var->getStorageClass(); 314 if (SC != SC_None) 315 Fragments 316 .append(VarDecl::getStorageClassSpecifierString(SC), 317 DeclarationFragments::FragmentKind::Keyword) 318 .appendSpace(); 319 QualType T = 320 Var->getTypeSourceInfo() 321 ? Var->getTypeSourceInfo()->getType() 322 : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); 323 324 // Capture potential fragments that needs to be placed after the variable name 325 // ``` 326 // int nums[5]; 327 // char (*ptr_to_array)[6]; 328 // ``` 329 DeclarationFragments After; 330 return Fragments.append(getFragmentsForType(T, Var->getASTContext(), After)) 331 .appendSpace() 332 .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) 333 .append(std::move(After)); 334 } 335 336 DeclarationFragments 337 DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { 338 DeclarationFragments Fragments, After; 339 340 QualType T = Param->getTypeSourceInfo() 341 ? Param->getTypeSourceInfo()->getType() 342 : Param->getASTContext().getUnqualifiedObjCPointerType( 343 Param->getType()); 344 345 DeclarationFragments TypeFragments = 346 getFragmentsForType(T, Param->getASTContext(), After); 347 348 if (Param->isObjCMethodParameter()) 349 Fragments.append("(", DeclarationFragments::FragmentKind::Text) 350 .append(std::move(TypeFragments)) 351 .append(")", DeclarationFragments::FragmentKind::Text); 352 else 353 Fragments.append(std::move(TypeFragments)).appendSpace(); 354 355 return Fragments 356 .append(Param->getName(), 357 DeclarationFragments::FragmentKind::InternalParam) 358 .append(std::move(After)); 359 } 360 361 DeclarationFragments 362 DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { 363 DeclarationFragments Fragments; 364 // FIXME: Handle template specialization 365 switch (Func->getStorageClass()) { 366 case SC_None: 367 case SC_PrivateExtern: 368 break; 369 case SC_Extern: 370 Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword) 371 .appendSpace(); 372 break; 373 case SC_Static: 374 Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) 375 .appendSpace(); 376 break; 377 case SC_Auto: 378 case SC_Register: 379 llvm_unreachable("invalid for functions"); 380 } 381 // FIXME: Handle C++ function specifiers: constexpr, consteval, explicit, etc. 382 383 // FIXME: Is `after` actually needed here? 384 DeclarationFragments After; 385 Fragments 386 .append(getFragmentsForType(Func->getReturnType(), Func->getASTContext(), 387 After)) 388 .appendSpace() 389 .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier) 390 .append(std::move(After)); 391 392 Fragments.append("(", DeclarationFragments::FragmentKind::Text); 393 for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) { 394 if (i) 395 Fragments.append(", ", DeclarationFragments::FragmentKind::Text); 396 Fragments.append(getFragmentsForParam(Func->getParamDecl(i))); 397 } 398 Fragments.append(")", DeclarationFragments::FragmentKind::Text); 399 400 // FIXME: Handle exception specifiers: throw, noexcept 401 return Fragments; 402 } 403 404 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant( 405 const EnumConstantDecl *EnumConstDecl) { 406 DeclarationFragments Fragments; 407 return Fragments.append(EnumConstDecl->getName(), 408 DeclarationFragments::FragmentKind::Identifier); 409 } 410 411 DeclarationFragments 412 DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) { 413 // TODO: After we support typedef records, if there's a typedef for this enum 414 // just use the declaration fragments of the typedef decl. 415 416 DeclarationFragments Fragments, After; 417 Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword); 418 419 if (!EnumDecl->getName().empty()) 420 Fragments.appendSpace().append( 421 EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier); 422 423 QualType IntegerType = EnumDecl->getIntegerType(); 424 if (!IntegerType.isNull()) 425 Fragments.append(": ", DeclarationFragments::FragmentKind::Text) 426 .append( 427 getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After)) 428 .append(std::move(After)); 429 430 return Fragments; 431 } 432 433 DeclarationFragments 434 DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) { 435 DeclarationFragments After; 436 return getFragmentsForType(Field->getType(), Field->getASTContext(), After) 437 .appendSpace() 438 .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier) 439 .append(std::move(After)); 440 } 441 442 DeclarationFragments 443 DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) { 444 // TODO: After we support typedef records, if there's a typedef for this 445 // struct just use the declaration fragments of the typedef decl. 446 447 DeclarationFragments Fragments; 448 Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); 449 450 if (!Record->getName().empty()) 451 Fragments.appendSpace().append( 452 Record->getName(), DeclarationFragments::FragmentKind::Identifier); 453 454 return Fragments; 455 } 456 457 FunctionSignature 458 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *Func) { 459 FunctionSignature Signature; 460 461 for (const auto *Param : Func->parameters()) { 462 StringRef Name = Param->getName(); 463 DeclarationFragments Fragments = getFragmentsForParam(Param); 464 465 Signature.addParameter(Name, Fragments); 466 } 467 468 DeclarationFragments After; 469 DeclarationFragments Returns = 470 getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After) 471 .append(std::move(After)); 472 473 Signature.setReturnType(Returns); 474 475 return Signature; 476 } 477 478 // Subheading of a symbol defaults to its name. 479 DeclarationFragments 480 DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { 481 DeclarationFragments Fragments; 482 if (!Decl->getName().empty()) 483 Fragments.append(Decl->getName(), 484 DeclarationFragments::FragmentKind::Identifier); 485 return Fragments; 486 } 487