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 "llvm/ADT/SmallVector.h" 31 #include "llvm/ADT/StringRef.h" 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 // Add a new Fragment at an arbitrary offset. 119 DeclarationFragments &insert(FragmentIterator It, StringRef Spelling, 120 FragmentKind Kind, 121 StringRef PreciseIdentifier = "", 122 const Decl *Declaration = nullptr) { 123 Fragments.insert(It, 124 Fragment(Spelling, Kind, PreciseIdentifier, Declaration)); 125 return *this; 126 } 127 128 DeclarationFragments &insert(FragmentIterator It, 129 DeclarationFragments &&Other) { 130 Fragments.insert(It, std::make_move_iterator(Other.Fragments.begin()), 131 std::make_move_iterator(Other.Fragments.end())); 132 Other.Fragments.clear(); 133 return *this; 134 } 135 136 /// Append a new Fragment to the end of the Fragments. 137 /// 138 /// \returns a reference to the DeclarationFragments object itself after 139 /// appending to chain up consecutive appends. 140 DeclarationFragments &append(StringRef Spelling, FragmentKind Kind, 141 StringRef PreciseIdentifier = "", 142 const Decl *Declaration = nullptr) { 143 if (Kind == FragmentKind::Text && !Fragments.empty() && 144 Fragments.back().Kind == FragmentKind::Text) { 145 // If appending a text fragment, and the last fragment is also text, 146 // merge into the last fragment. 147 Fragments.back().Spelling.append(Spelling.data(), Spelling.size()); 148 } else { 149 Fragments.emplace_back(Spelling, Kind, PreciseIdentifier, Declaration); 150 } 151 return *this; 152 } 153 154 /// Append another DeclarationFragments to the end. 155 /// 156 /// Note: \p Other is moved from and cannot be used after a call to this 157 /// method. 158 /// 159 /// \returns a reference to the DeclarationFragments object itself after 160 /// appending to chain up consecutive appends. 161 DeclarationFragments &append(DeclarationFragments &&Other) { 162 Fragments.insert(Fragments.end(), 163 std::make_move_iterator(Other.Fragments.begin()), 164 std::make_move_iterator(Other.Fragments.end())); 165 Other.Fragments.clear(); 166 return *this; 167 } 168 169 DeclarationFragments &pop_back() { 170 Fragments.pop_back(); 171 return *this; 172 } 173 174 DeclarationFragments &replace(std::string NewSpelling, unsigned Position) { 175 Fragments.at(Position).Spelling = NewSpelling; 176 return *this; 177 } 178 179 /// Append a text Fragment of a space character. 180 /// 181 /// \returns a reference to the DeclarationFragments object itself after 182 /// appending to chain up consecutive appends. 183 DeclarationFragments &appendSpace(); 184 185 /// Get the string description of a FragmentKind \p Kind. 186 static StringRef getFragmentKindString(FragmentKind Kind); 187 188 /// Get the corresponding FragmentKind from string \p S. 189 static FragmentKind parseFragmentKindFromString(StringRef S); 190 191 static DeclarationFragments 192 getExceptionSpecificationString(ExceptionSpecificationType ExceptionSpec); 193 194 static DeclarationFragments getStructureTypeFragment(const RecordDecl *Decl); 195 196 private: 197 std::vector<Fragment> Fragments; 198 }; 199 200 class AccessControl { 201 public: 202 AccessControl(std::string Access) : Access(Access) {} 203 204 const std::string &getAccess() const { return Access; } 205 206 bool empty() const { return Access.empty(); } 207 208 private: 209 std::string Access; 210 }; 211 212 /// Store function signature information with DeclarationFragments of the 213 /// return type and parameters. 214 class FunctionSignature { 215 public: 216 FunctionSignature() = default; 217 218 /// Parameter holds the name and DeclarationFragments of a single parameter. 219 struct Parameter { 220 std::string Name; 221 DeclarationFragments Fragments; 222 223 Parameter(StringRef Name, DeclarationFragments Fragments) 224 : Name(Name), Fragments(Fragments) {} 225 }; 226 227 const std::vector<Parameter> &getParameters() const { return Parameters; } 228 const DeclarationFragments &getReturnType() const { return ReturnType; } 229 230 FunctionSignature &addParameter(StringRef Name, 231 DeclarationFragments Fragments) { 232 Parameters.emplace_back(Name, Fragments); 233 return *this; 234 } 235 236 void setReturnType(DeclarationFragments RT) { ReturnType = RT; } 237 238 /// Determine if the FunctionSignature is empty. 239 /// 240 /// \returns true if the return type DeclarationFragments is empty and there 241 /// is no parameter, otherwise false. 242 bool empty() const { 243 return Parameters.empty() && ReturnType.getFragments().empty(); 244 } 245 246 private: 247 std::vector<Parameter> Parameters; 248 DeclarationFragments ReturnType; 249 }; 250 251 /// A factory class to build DeclarationFragments for different kinds of Decl. 252 class DeclarationFragmentsBuilder { 253 public: 254 /// Build FunctionSignature for a function-like declaration \c FunctionT like 255 /// FunctionDecl, ObjCMethodDecl, or CXXMethodDecl. 256 /// 257 /// The logic and implementation of building a signature for a FunctionDecl, 258 /// CXXMethodDecl, and ObjCMethodDecl are exactly the same, but they do not 259 /// share a common base. This template helps reuse the code. 260 template <typename FunctionT> 261 static FunctionSignature getFunctionSignature(const FunctionT *Function); 262 263 static AccessControl getAccessControl(const Decl *Decl) { 264 switch (Decl->getAccess()) { 265 case AS_public: 266 case AS_none: 267 return AccessControl("public"); 268 case AS_private: 269 return AccessControl("private"); 270 case AS_protected: 271 return AccessControl("protected"); 272 } 273 llvm_unreachable("Unhandled access control"); 274 } 275 276 static DeclarationFragments 277 getFragmentsForNamespace(const NamespaceDecl *Decl); 278 279 /// Build DeclarationFragments for a variable declaration VarDecl. 280 static DeclarationFragments getFragmentsForVar(const VarDecl *); 281 282 static DeclarationFragments getFragmentsForVarTemplate(const VarDecl *); 283 284 /// Build DeclarationFragments for a function declaration FunctionDecl. 285 static DeclarationFragments getFragmentsForFunction(const FunctionDecl *); 286 287 /// Build DeclarationFragments for an enum constant declaration 288 /// EnumConstantDecl. 289 static DeclarationFragments 290 getFragmentsForEnumConstant(const EnumConstantDecl *); 291 292 /// Build DeclarationFragments for an enum declaration EnumDecl. 293 static DeclarationFragments getFragmentsForEnum(const EnumDecl *); 294 295 /// Build DeclarationFragments for a field declaration FieldDecl. 296 static DeclarationFragments getFragmentsForField(const FieldDecl *); 297 298 /// Build DeclarationFragments for a struct/union record declaration 299 /// RecordDecl. 300 static DeclarationFragments getFragmentsForRecordDecl(const RecordDecl *); 301 302 static DeclarationFragments getFragmentsForCXXClass(const CXXRecordDecl *); 303 304 static DeclarationFragments 305 getFragmentsForSpecialCXXMethod(const CXXMethodDecl *); 306 307 static DeclarationFragments getFragmentsForCXXMethod(const CXXMethodDecl *); 308 309 static DeclarationFragments 310 getFragmentsForConversionFunction(const CXXConversionDecl *); 311 312 static DeclarationFragments 313 getFragmentsForOverloadedOperator(const CXXMethodDecl *); 314 315 static DeclarationFragments 316 getFragmentsForTemplateParameters(ArrayRef<NamedDecl *>); 317 318 static std::string 319 getNameForTemplateArgument(const ArrayRef<NamedDecl *>, std::string); 320 321 static DeclarationFragments 322 getFragmentsForTemplateArguments(const ArrayRef<TemplateArgument>, 323 ASTContext &, 324 const std::optional<ArrayRef<NamedDecl *>>); 325 326 static DeclarationFragments getFragmentsForConcept(const ConceptDecl *); 327 328 static DeclarationFragments 329 getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl *); 330 331 static DeclarationFragments getFragmentsForClassTemplateSpecialization( 332 const ClassTemplateSpecializationDecl *); 333 334 static DeclarationFragments getFragmentsForClassTemplatePartialSpecialization( 335 const ClassTemplatePartialSpecializationDecl *); 336 337 static DeclarationFragments getFragmentsForVarTemplateSpecialization( 338 const VarTemplateSpecializationDecl *); 339 340 static DeclarationFragments getFragmentsForVarTemplatePartialSpecialization( 341 const VarTemplatePartialSpecializationDecl *); 342 343 static DeclarationFragments 344 getFragmentsForFunctionTemplate(const FunctionTemplateDecl *Decl); 345 346 static DeclarationFragments 347 getFragmentsForFunctionTemplateSpecialization(const FunctionDecl *Decl); 348 349 /// Build DeclarationFragments for an Objective-C category declaration 350 /// ObjCCategoryDecl. 351 static DeclarationFragments 352 getFragmentsForObjCCategory(const ObjCCategoryDecl *); 353 354 /// Build DeclarationFragments for an Objective-C interface declaration 355 /// ObjCInterfaceDecl. 356 static DeclarationFragments 357 getFragmentsForObjCInterface(const ObjCInterfaceDecl *); 358 359 /// Build DeclarationFragments for an Objective-C method declaration 360 /// ObjCMethodDecl. 361 static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *); 362 363 /// Build DeclarationFragments for an Objective-C property declaration 364 /// ObjCPropertyDecl. 365 static DeclarationFragments 366 getFragmentsForObjCProperty(const ObjCPropertyDecl *); 367 368 /// Build DeclarationFragments for an Objective-C protocol declaration 369 /// ObjCProtocolDecl. 370 static DeclarationFragments 371 getFragmentsForObjCProtocol(const ObjCProtocolDecl *); 372 373 /// Build DeclarationFragments for a macro. 374 /// 375 /// \param Name name of the macro. 376 /// \param MD the associated MacroDirective. 377 static DeclarationFragments getFragmentsForMacro(StringRef Name, 378 const MacroDirective *MD); 379 380 /// Build DeclarationFragments for a typedef \p TypedefNameDecl. 381 static DeclarationFragments 382 getFragmentsForTypedef(const TypedefNameDecl *Decl); 383 384 /// Build sub-heading fragments for a NamedDecl. 385 static DeclarationFragments getSubHeading(const NamedDecl *); 386 387 /// Build sub-heading fragments for an Objective-C method. 388 static DeclarationFragments getSubHeading(const ObjCMethodDecl *); 389 390 /// Build a sub-heading for macro \p Name. 391 static DeclarationFragments getSubHeadingForMacro(StringRef Name); 392 393 private: 394 DeclarationFragmentsBuilder() = delete; 395 396 /// Build DeclarationFragments for a QualType. 397 static DeclarationFragments getFragmentsForType(const QualType, ASTContext &, 398 DeclarationFragments &); 399 400 /// Build DeclarationFragments for a Type. 401 static DeclarationFragments getFragmentsForType(const Type *, ASTContext &, 402 DeclarationFragments &); 403 404 /// Build DeclarationFragments for a NestedNameSpecifier. 405 static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *, 406 ASTContext &, 407 DeclarationFragments &); 408 409 /// Build DeclarationFragments for Qualifiers. 410 static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals); 411 412 /// Build DeclarationFragments for a parameter variable declaration 413 /// ParmVarDecl. 414 static DeclarationFragments getFragmentsForParam(const ParmVarDecl *); 415 416 static DeclarationFragments 417 getFragmentsForBlock(const NamedDecl *BlockDecl, FunctionTypeLoc &Block, 418 FunctionProtoTypeLoc &BlockProto, 419 DeclarationFragments &After); 420 }; 421 422 template <typename FunctionT> 423 FunctionSignature 424 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) { 425 FunctionSignature Signature; 426 427 DeclarationFragments ReturnType, After; 428 ReturnType = getFragmentsForType(Function->getReturnType(), 429 Function->getASTContext(), After); 430 if (isa<FunctionDecl>(Function) && 431 dyn_cast<FunctionDecl>(Function)->getDescribedFunctionTemplate() && 432 ReturnType.begin()->Spelling.substr(0, 14).compare("type-parameter") == 433 0) { 434 std::string ProperArgName = 435 getNameForTemplateArgument(dyn_cast<FunctionDecl>(Function) 436 ->getDescribedFunctionTemplate() 437 ->getTemplateParameters() 438 ->asArray(), 439 ReturnType.begin()->Spelling); 440 ReturnType.begin()->Spelling.swap(ProperArgName); 441 } 442 ReturnType.append(std::move(After)); 443 Signature.setReturnType(ReturnType); 444 445 for (const auto *Param : Function->parameters()) 446 Signature.addParameter(Param->getName(), getFragmentsForParam(Param)); 447 448 return Signature; 449 } 450 451 } // namespace extractapi 452 } // namespace clang 453 454 #endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H 455