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 record declaration RecordDecl. 299 static DeclarationFragments getFragmentsForStruct(const RecordDecl *); 300 301 static DeclarationFragments getFragmentsForCXXClass(const CXXRecordDecl *); 302 303 static DeclarationFragments 304 getFragmentsForSpecialCXXMethod(const CXXMethodDecl *); 305 306 static DeclarationFragments getFragmentsForCXXMethod(const CXXMethodDecl *); 307 308 static DeclarationFragments 309 getFragmentsForConversionFunction(const CXXConversionDecl *); 310 311 static DeclarationFragments 312 getFragmentsForOverloadedOperator(const CXXMethodDecl *); 313 314 static DeclarationFragments 315 getFragmentsForTemplateParameters(ArrayRef<NamedDecl *>); 316 317 static std::string 318 getNameForTemplateArgument(const ArrayRef<NamedDecl *>, std::string); 319 320 static DeclarationFragments 321 getFragmentsForTemplateArguments(const ArrayRef<TemplateArgument>, 322 ASTContext &, 323 const std::optional<ArrayRef<NamedDecl *>>); 324 325 static DeclarationFragments getFragmentsForConcept(const ConceptDecl *); 326 327 static DeclarationFragments 328 getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl *); 329 330 static DeclarationFragments getFragmentsForClassTemplateSpecialization( 331 const ClassTemplateSpecializationDecl *); 332 333 static DeclarationFragments getFragmentsForClassTemplatePartialSpecialization( 334 const ClassTemplatePartialSpecializationDecl *); 335 336 static DeclarationFragments getFragmentsForVarTemplateSpecialization( 337 const VarTemplateSpecializationDecl *); 338 339 static DeclarationFragments getFragmentsForVarTemplatePartialSpecialization( 340 const VarTemplatePartialSpecializationDecl *); 341 342 static DeclarationFragments 343 getFragmentsForFunctionTemplate(const FunctionTemplateDecl *Decl); 344 345 static DeclarationFragments 346 getFragmentsForFunctionTemplateSpecialization(const FunctionDecl *Decl); 347 348 /// Build DeclarationFragments for an Objective-C category declaration 349 /// ObjCCategoryDecl. 350 static DeclarationFragments 351 getFragmentsForObjCCategory(const ObjCCategoryDecl *); 352 353 /// Build DeclarationFragments for an Objective-C interface declaration 354 /// ObjCInterfaceDecl. 355 static DeclarationFragments 356 getFragmentsForObjCInterface(const ObjCInterfaceDecl *); 357 358 /// Build DeclarationFragments for an Objective-C method declaration 359 /// ObjCMethodDecl. 360 static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *); 361 362 /// Build DeclarationFragments for an Objective-C property declaration 363 /// ObjCPropertyDecl. 364 static DeclarationFragments 365 getFragmentsForObjCProperty(const ObjCPropertyDecl *); 366 367 /// Build DeclarationFragments for an Objective-C protocol declaration 368 /// ObjCProtocolDecl. 369 static DeclarationFragments 370 getFragmentsForObjCProtocol(const ObjCProtocolDecl *); 371 372 /// Build DeclarationFragments for a macro. 373 /// 374 /// \param Name name of the macro. 375 /// \param MD the associated MacroDirective. 376 static DeclarationFragments getFragmentsForMacro(StringRef Name, 377 const MacroDirective *MD); 378 379 /// Build DeclarationFragments for a typedef \p TypedefNameDecl. 380 static DeclarationFragments 381 getFragmentsForTypedef(const TypedefNameDecl *Decl); 382 383 /// Build sub-heading fragments for a NamedDecl. 384 static DeclarationFragments getSubHeading(const NamedDecl *); 385 386 /// Build sub-heading fragments for an Objective-C method. 387 static DeclarationFragments getSubHeading(const ObjCMethodDecl *); 388 389 /// Build a sub-heading for macro \p Name. 390 static DeclarationFragments getSubHeadingForMacro(StringRef Name); 391 392 private: 393 DeclarationFragmentsBuilder() = delete; 394 395 /// Build DeclarationFragments for a QualType. 396 static DeclarationFragments getFragmentsForType(const QualType, ASTContext &, 397 DeclarationFragments &); 398 399 /// Build DeclarationFragments for a Type. 400 static DeclarationFragments getFragmentsForType(const Type *, ASTContext &, 401 DeclarationFragments &); 402 403 /// Build DeclarationFragments for a NestedNameSpecifier. 404 static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *, 405 ASTContext &, 406 DeclarationFragments &); 407 408 /// Build DeclarationFragments for Qualifiers. 409 static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals); 410 411 /// Build DeclarationFragments for a parameter variable declaration 412 /// ParmVarDecl. 413 static DeclarationFragments getFragmentsForParam(const ParmVarDecl *); 414 415 static DeclarationFragments 416 getFragmentsForBlock(const NamedDecl *BlockDecl, FunctionTypeLoc &Block, 417 FunctionProtoTypeLoc &BlockProto, 418 DeclarationFragments &After); 419 }; 420 421 template <typename FunctionT> 422 FunctionSignature 423 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) { 424 FunctionSignature Signature; 425 426 DeclarationFragments ReturnType, After; 427 ReturnType = getFragmentsForType(Function->getReturnType(), 428 Function->getASTContext(), After); 429 if (isa<FunctionDecl>(Function) && 430 dyn_cast<FunctionDecl>(Function)->getDescribedFunctionTemplate() && 431 ReturnType.begin()->Spelling.substr(0, 14).compare("type-parameter") == 432 0) { 433 std::string ProperArgName = 434 getNameForTemplateArgument(dyn_cast<FunctionDecl>(Function) 435 ->getDescribedFunctionTemplate() 436 ->getTemplateParameters() 437 ->asArray(), 438 ReturnType.begin()->Spelling); 439 ReturnType.begin()->Spelling.swap(ProperArgName); 440 } 441 ReturnType.append(std::move(After)); 442 Signature.setReturnType(ReturnType); 443 444 for (const auto *Param : Function->parameters()) 445 Signature.addParameter(Param->getName(), getFragmentsForParam(Param)); 446 447 return Signature; 448 } 449 450 } // namespace extractapi 451 } // namespace clang 452 453 #endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H 454