1 //===- ExtractAPI/DeclarationFragments.h ------------------------*- 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 defines the Declaration Fragments related classes. 11 /// 12 /// Declaration Fragments represent parts of a symbol declaration tagged with 13 /// syntactic/semantic information. 14 /// See https://github.com/apple/swift-docc-symbolkit 15 /// 16 //===----------------------------------------------------------------------===// 17 18 #ifndef LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H 19 #define LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H 20 21 #include "clang/AST/ASTContext.h" 22 #include "clang/AST/Decl.h" 23 #include "clang/AST/DeclCXX.h" 24 #include "clang/AST/DeclObjC.h" 25 #include "clang/AST/DeclTemplate.h" 26 #include "clang/AST/ExprCXX.h" 27 #include "clang/AST/TypeLoc.h" 28 #include "clang/Basic/Specifiers.h" 29 #include "clang/Lex/MacroInfo.h" 30 #include <iterator> 31 #include <utility> 32 #include <vector> 33 34 namespace clang { 35 namespace extractapi { 36 37 /// DeclarationFragments is a vector of tagged important parts of a symbol's 38 /// declaration. 39 /// 40 /// The fragments sequence can be joined to form spans of declaration text, with 41 /// attached information useful for purposes like syntax-highlighting etc. 42 /// For example: 43 /// \code 44 /// const -> keyword "const" 45 /// int -> type "int" 46 /// pi; -> identifier "pi" 47 /// \endcode 48 class DeclarationFragments { 49 public: 50 DeclarationFragments() = default; 51 52 /// The kind of a fragment. 53 enum class FragmentKind { 54 /// Unknown fragment kind. 55 None, 56 57 Keyword, 58 Attribute, 59 NumberLiteral, 60 StringLiteral, 61 Identifier, 62 63 /// Identifier that refers to a type in the context. 64 TypeIdentifier, 65 66 /// Parameter that's used as generics in the context. For example template 67 /// parameters. 68 GenericParameter, 69 70 /// External parameters in Objective-C methods. 71 /// For example, \c forKey in 72 /// \code{.m} 73 /// - (void) setValue:(Value)value forKey(Key)key 74 /// \endcode 75 ExternalParam, 76 77 /// Internal/local parameters in Objective-C methods. 78 /// For example, \c key in 79 /// \code{.m} 80 /// - (void) setValue:(Value)value forKey(Key)key 81 /// \endcode 82 InternalParam, 83 84 Text, 85 }; 86 87 /// Fragment holds information of a single fragment. 88 struct Fragment { 89 std::string Spelling; 90 FragmentKind Kind; 91 92 /// The USR of the fragment symbol, if applicable. 93 std::string PreciseIdentifier; 94 95 /// The associated declaration, if applicable. This is not intended to be 96 /// used outside of libclang. 97 const Decl *Declaration; 98 99 Fragment(StringRef Spelling, FragmentKind Kind, StringRef PreciseIdentifier, 100 const Decl *Declaration) 101 : Spelling(Spelling), Kind(Kind), PreciseIdentifier(PreciseIdentifier), 102 Declaration(Declaration) {} 103 }; 104 105 using FragmentIterator = std::vector<Fragment>::iterator; 106 using ConstFragmentIterator = std::vector<Fragment>::const_iterator; 107 108 const std::vector<Fragment> &getFragments() const { return Fragments; } 109 110 FragmentIterator begin() { return Fragments.begin(); } 111 112 FragmentIterator end() { return Fragments.end(); } 113 114 ConstFragmentIterator cbegin() const { return Fragments.cbegin(); } 115 116 ConstFragmentIterator cend() const { return Fragments.cend(); } 117 118 /// Prepend another DeclarationFragments to the beginning. 119 /// 120 /// \returns a reference to the DeclarationFragments object itself after 121 /// appending to chain up consecutive operations. 122 DeclarationFragments &prepend(DeclarationFragments Other) { 123 return insert(begin(), std::move(Other)); 124 } 125 126 /// Append another DeclarationFragments to the end. 127 /// 128 /// \returns a reference to the DeclarationFragments object itself after 129 /// appending to chain up consecutive operations. 130 DeclarationFragments &append(DeclarationFragments Other) { 131 return insert(end(), std::move(Other)); 132 } 133 134 /// Append a new Fragment to the end of the Fragments. 135 /// 136 /// \returns a reference to the DeclarationFragments object itself after 137 /// appending to chain up consecutive operations. 138 DeclarationFragments &append(StringRef Spelling, FragmentKind Kind, 139 StringRef PreciseIdentifier = "", 140 const Decl *Declaration = nullptr) { 141 if (Kind == FragmentKind::Text && !Fragments.empty() && 142 Fragments.back().Kind == FragmentKind::Text) { 143 // If appending a text fragment, and the last fragment is also text, 144 // merge into the last fragment. 145 Fragments.back().Spelling.append(Spelling.data(), Spelling.size()); 146 } else { 147 Fragments.emplace_back(Spelling, Kind, PreciseIdentifier, Declaration); 148 } 149 return *this; 150 } 151 152 /// Inserts another DeclarationFragments at \p It. 153 /// 154 /// \returns a reference to the DeclarationFragments object itself after 155 /// appending to chain up consecutive operations. 156 DeclarationFragments &insert(FragmentIterator It, 157 DeclarationFragments Other) { 158 if (Other.Fragments.empty()) 159 return *this; 160 161 if (Fragments.empty()) { 162 Fragments = std::move(Other.Fragments); 163 return *this; 164 } 165 166 const auto &OtherFrags = Other.Fragments; 167 auto ToInsertBegin = std::make_move_iterator(Other.begin()); 168 auto ToInsertEnd = std::make_move_iterator(Other.end()); 169 170 // If we aren't inserting at the end let's make sure that we merge their 171 // last fragment with It if both are text fragments. 172 if (It != end() && It->Kind == FragmentKind::Text && 173 OtherFrags.back().Kind == FragmentKind::Text) { 174 auto &TheirBackSpelling = OtherFrags.back().Spelling; 175 It->Spelling.reserve(It->Spelling.size() + TheirBackSpelling.size()); 176 It->Spelling.insert(It->Spelling.begin(), TheirBackSpelling.begin(), 177 TheirBackSpelling.end()); 178 --ToInsertEnd; 179 } 180 181 // If we aren't inserting at the beginning we want to merge their first 182 // fragment with the fragment before It if both are text fragments. 183 if (It != begin() && std::prev(It)->Kind == FragmentKind::Text && 184 OtherFrags.front().Kind == FragmentKind::Text) { 185 auto PrevIt = std::prev(It); 186 auto &TheirFrontSpelling = OtherFrags.front().Spelling; 187 PrevIt->Spelling.reserve(PrevIt->Spelling.size() + 188 TheirFrontSpelling.size()); 189 PrevIt->Spelling.append(TheirFrontSpelling); 190 ++ToInsertBegin; 191 } 192 193 Fragments.insert(It, ToInsertBegin, ToInsertEnd); 194 return *this; 195 } 196 197 DeclarationFragments &pop_back() { 198 Fragments.pop_back(); 199 return *this; 200 } 201 202 DeclarationFragments &replace(std::string NewSpelling, unsigned Position) { 203 Fragments.at(Position).Spelling = NewSpelling; 204 return *this; 205 } 206 207 /// Append a text Fragment of a space character. 208 /// 209 /// \returns a reference to the DeclarationFragments object itself after 210 /// appending to chain up consecutive operations. 211 DeclarationFragments &appendSpace(); 212 213 /// Append a text Fragment of a semicolon character. 214 /// 215 /// \returns a reference to the DeclarationFragments object itself after 216 /// appending to chain up consecutive operations. 217 DeclarationFragments &appendSemicolon(); 218 219 /// Removes a trailing semicolon character if present. 220 /// 221 /// \returns a reference to the DeclarationFragments object itself after 222 /// removing to chain up consecutive operations. 223 DeclarationFragments &removeTrailingSemicolon(); 224 225 /// Get the string description of a FragmentKind \p Kind. 226 static StringRef getFragmentKindString(FragmentKind Kind); 227 228 /// Get the corresponding FragmentKind from string \p S. 229 static FragmentKind parseFragmentKindFromString(StringRef S); 230 231 static DeclarationFragments 232 getExceptionSpecificationString(ExceptionSpecificationType ExceptionSpec); 233 234 static DeclarationFragments getStructureTypeFragment(const RecordDecl *Decl); 235 236 private: 237 DeclarationFragments &appendUnduplicatedTextCharacter(char Character); 238 std::vector<Fragment> Fragments; 239 }; 240 241 class AccessControl { 242 public: 243 AccessControl(std::string Access) : Access(Access) {} 244 AccessControl() : Access("public") {} 245 246 const std::string &getAccess() const { return Access; } 247 248 bool empty() const { return Access.empty(); } 249 250 private: 251 std::string Access; 252 }; 253 254 /// Store function signature information with DeclarationFragments of the 255 /// return type and parameters. 256 class FunctionSignature { 257 public: 258 FunctionSignature() = default; 259 260 /// Parameter holds the name and DeclarationFragments of a single parameter. 261 struct Parameter { 262 std::string Name; 263 DeclarationFragments Fragments; 264 265 Parameter(StringRef Name, DeclarationFragments Fragments) 266 : Name(Name), Fragments(Fragments) {} 267 }; 268 269 const std::vector<Parameter> &getParameters() const { return Parameters; } 270 const DeclarationFragments &getReturnType() const { return ReturnType; } 271 272 FunctionSignature &addParameter(StringRef Name, 273 DeclarationFragments Fragments) { 274 Parameters.emplace_back(Name, Fragments); 275 return *this; 276 } 277 278 void setReturnType(DeclarationFragments RT) { ReturnType = RT; } 279 280 /// Determine if the FunctionSignature is empty. 281 /// 282 /// \returns true if the return type DeclarationFragments is empty and there 283 /// is no parameter, otherwise false. 284 bool empty() const { 285 return Parameters.empty() && ReturnType.getFragments().empty(); 286 } 287 288 private: 289 std::vector<Parameter> Parameters; 290 DeclarationFragments ReturnType; 291 }; 292 293 /// A factory class to build DeclarationFragments for different kinds of Decl. 294 class DeclarationFragmentsBuilder { 295 public: 296 /// Build FunctionSignature for a function-like declaration \c FunctionT like 297 /// FunctionDecl, ObjCMethodDecl, or CXXMethodDecl. 298 /// 299 /// The logic and implementation of building a signature for a FunctionDecl, 300 /// CXXMethodDecl, and ObjCMethodDecl are exactly the same, but they do not 301 /// share a common base. This template helps reuse the code. 302 template <typename FunctionT> 303 static FunctionSignature getFunctionSignature(const FunctionT *Function); 304 305 static AccessControl getAccessControl(const Decl *Decl) { 306 switch (Decl->getAccess()) { 307 case AS_public: 308 case AS_none: 309 return AccessControl("public"); 310 case AS_private: 311 return AccessControl("private"); 312 case AS_protected: 313 return AccessControl("protected"); 314 } 315 llvm_unreachable("Unhandled access control"); 316 } 317 318 static DeclarationFragments 319 getFragmentsForNamespace(const NamespaceDecl *Decl); 320 321 /// Build DeclarationFragments for a variable declaration VarDecl. 322 static DeclarationFragments getFragmentsForVar(const VarDecl *); 323 324 static DeclarationFragments getFragmentsForVarTemplate(const VarDecl *); 325 326 /// Build DeclarationFragments for a function declaration FunctionDecl. 327 static DeclarationFragments getFragmentsForFunction(const FunctionDecl *); 328 329 /// Build DeclarationFragments for an enum constant declaration 330 /// EnumConstantDecl. 331 static DeclarationFragments 332 getFragmentsForEnumConstant(const EnumConstantDecl *); 333 334 /// Build DeclarationFragments for an enum declaration EnumDecl. 335 static DeclarationFragments getFragmentsForEnum(const EnumDecl *); 336 337 /// Build DeclarationFragments for a field declaration FieldDecl. 338 static DeclarationFragments getFragmentsForField(const FieldDecl *); 339 340 /// Build DeclarationFragments for a struct/union record declaration 341 /// RecordDecl. 342 static DeclarationFragments getFragmentsForRecordDecl(const RecordDecl *); 343 344 static DeclarationFragments getFragmentsForCXXClass(const CXXRecordDecl *); 345 346 static DeclarationFragments 347 getFragmentsForSpecialCXXMethod(const CXXMethodDecl *); 348 349 static DeclarationFragments getFragmentsForCXXMethod(const CXXMethodDecl *); 350 351 static DeclarationFragments 352 getFragmentsForConversionFunction(const CXXConversionDecl *); 353 354 static DeclarationFragments 355 getFragmentsForOverloadedOperator(const CXXMethodDecl *); 356 357 static DeclarationFragments 358 getFragmentsForTemplateParameters(ArrayRef<NamedDecl *>); 359 360 static DeclarationFragments getFragmentsForTemplateArguments( 361 const ArrayRef<TemplateArgument>, ASTContext &, 362 const std::optional<ArrayRef<TemplateArgumentLoc>>); 363 364 static DeclarationFragments getFragmentsForConcept(const ConceptDecl *); 365 366 static DeclarationFragments 367 getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl *); 368 369 static DeclarationFragments getFragmentsForClassTemplateSpecialization( 370 const ClassTemplateSpecializationDecl *); 371 372 static DeclarationFragments getFragmentsForClassTemplatePartialSpecialization( 373 const ClassTemplatePartialSpecializationDecl *); 374 375 static DeclarationFragments getFragmentsForVarTemplateSpecialization( 376 const VarTemplateSpecializationDecl *); 377 378 static DeclarationFragments getFragmentsForVarTemplatePartialSpecialization( 379 const VarTemplatePartialSpecializationDecl *); 380 381 static DeclarationFragments 382 getFragmentsForFunctionTemplate(const FunctionTemplateDecl *Decl); 383 384 static DeclarationFragments 385 getFragmentsForFunctionTemplateSpecialization(const FunctionDecl *Decl); 386 387 /// Build DeclarationFragments for an Objective-C category declaration 388 /// ObjCCategoryDecl. 389 static DeclarationFragments 390 getFragmentsForObjCCategory(const ObjCCategoryDecl *); 391 392 /// Build DeclarationFragments for an Objective-C interface declaration 393 /// ObjCInterfaceDecl. 394 static DeclarationFragments 395 getFragmentsForObjCInterface(const ObjCInterfaceDecl *); 396 397 /// Build DeclarationFragments for an Objective-C method declaration 398 /// ObjCMethodDecl. 399 static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *); 400 401 /// Build DeclarationFragments for an Objective-C property declaration 402 /// ObjCPropertyDecl. 403 static DeclarationFragments 404 getFragmentsForObjCProperty(const ObjCPropertyDecl *); 405 406 /// Build DeclarationFragments for an Objective-C protocol declaration 407 /// ObjCProtocolDecl. 408 static DeclarationFragments 409 getFragmentsForObjCProtocol(const ObjCProtocolDecl *); 410 411 /// Build DeclarationFragments for a macro. 412 /// 413 /// \param Name name of the macro. 414 /// \param MD the associated MacroDirective. 415 static DeclarationFragments getFragmentsForMacro(StringRef Name, 416 const MacroDirective *MD); 417 418 /// Build DeclarationFragments for a typedef \p TypedefNameDecl. 419 static DeclarationFragments 420 getFragmentsForTypedef(const TypedefNameDecl *Decl); 421 422 /// Build sub-heading fragments for a NamedDecl. 423 static DeclarationFragments getSubHeading(const NamedDecl *); 424 425 /// Build sub-heading fragments for an Objective-C method. 426 static DeclarationFragments getSubHeading(const ObjCMethodDecl *); 427 428 /// Build a sub-heading for macro \p Name. 429 static DeclarationFragments getSubHeadingForMacro(StringRef Name); 430 431 private: 432 DeclarationFragmentsBuilder() = delete; 433 434 /// Build DeclarationFragments for a QualType. 435 static DeclarationFragments getFragmentsForType(const QualType, ASTContext &, 436 DeclarationFragments &); 437 438 /// Build DeclarationFragments for a Type. 439 static DeclarationFragments getFragmentsForType(const Type *, ASTContext &, 440 DeclarationFragments &); 441 442 /// Build DeclarationFragments for a NestedNameSpecifier. 443 static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *, 444 ASTContext &, 445 DeclarationFragments &); 446 447 /// Build DeclarationFragments for Qualifiers. 448 static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals); 449 450 /// Build DeclarationFragments for a parameter variable declaration 451 /// ParmVarDecl. 452 static DeclarationFragments getFragmentsForParam(const ParmVarDecl *); 453 454 static DeclarationFragments 455 getFragmentsForBlock(const NamedDecl *BlockDecl, FunctionTypeLoc &Block, 456 FunctionProtoTypeLoc &BlockProto, 457 DeclarationFragments &After); 458 }; 459 460 template <typename FunctionT> 461 FunctionSignature 462 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) { 463 FunctionSignature Signature; 464 465 DeclarationFragments ReturnType, After; 466 ReturnType = getFragmentsForType(Function->getReturnType(), 467 Function->getASTContext(), After); 468 if (isa<FunctionDecl>(Function) && 469 dyn_cast<FunctionDecl>(Function)->getDescribedFunctionTemplate() && 470 StringRef(ReturnType.begin()->Spelling).starts_with("type-parameter")) { 471 std::string ProperArgName = Function->getReturnType().getAsString(); 472 ReturnType.begin()->Spelling.swap(ProperArgName); 473 } 474 ReturnType.append(std::move(After)); 475 Signature.setReturnType(ReturnType); 476 477 for (const auto *Param : Function->parameters()) 478 Signature.addParameter(Param->getName(), getFragmentsForParam(Param)); 479 480 return Signature; 481 } 482 483 } // namespace extractapi 484 } // namespace clang 485 486 #endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H 487