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/Lex/MacroInfo.h" 26 #include "llvm/ADT/StringRef.h" 27 #include <vector> 28 29 namespace clang { 30 namespace extractapi { 31 32 /// DeclarationFragments is a vector of tagged important parts of a symbol's 33 /// declaration. 34 /// 35 /// The fragments sequence can be joined to form spans of declaration text, with 36 /// attached information useful for purposes like syntax-highlighting etc. 37 /// For example: 38 /// \code 39 /// const -> keyword "const" 40 /// int -> type "int" 41 /// pi; -> identifier "pi" 42 /// \endcode 43 class DeclarationFragments { 44 public: 45 DeclarationFragments() = default; 46 47 /// The kind of a fragment. 48 enum class FragmentKind { 49 /// Unknown fragment kind. 50 None, 51 52 Keyword, 53 Attribute, 54 NumberLiteral, 55 StringLiteral, 56 Identifier, 57 58 /// Identifier that refers to a type in the context. 59 TypeIdentifier, 60 61 /// Parameter that's used as generics in the context. For example template 62 /// parameters. 63 GenericParameter, 64 65 /// External parameters in Objective-C methods. 66 /// For example, \c forKey in 67 /// \code{.m} 68 /// - (void) setValue:(Value)value forKey(Key)key 69 /// \endcode 70 ExternalParam, 71 72 /// Internal/local parameters in Objective-C methods. 73 /// For example, \c key in 74 /// \code{.m} 75 /// - (void) setValue:(Value)value forKey(Key)key 76 /// \endcode 77 InternalParam, 78 79 Text, 80 }; 81 82 /// Fragment holds information of a single fragment. 83 struct Fragment { 84 std::string Spelling; 85 FragmentKind Kind; 86 87 /// The USR of the fragment symbol, if applicable. 88 std::string PreciseIdentifier; 89 90 /// The associated declaration, if applicable. This is not intended to be 91 /// used outside of libclang. 92 const Decl *Declaration; 93 94 Fragment(StringRef Spelling, FragmentKind Kind, StringRef PreciseIdentifier, 95 const Decl *Declaration) 96 : Spelling(Spelling), Kind(Kind), PreciseIdentifier(PreciseIdentifier), 97 Declaration(Declaration) {} 98 }; 99 100 using FragmentIterator = std::vector<Fragment>::iterator; 101 using ConstFragmentIterator = std::vector<Fragment>::const_iterator; 102 103 const std::vector<Fragment> &getFragments() const { return Fragments; } 104 105 FragmentIterator begin() { return Fragments.begin(); } 106 107 FragmentIterator end() { return Fragments.end(); } 108 109 ConstFragmentIterator cbegin() const { return Fragments.cbegin(); } 110 111 ConstFragmentIterator cend() const { return Fragments.cend(); } 112 113 // Add a new Fragment at an arbitrary offset. 114 DeclarationFragments &insert(FragmentIterator It, StringRef Spelling, 115 FragmentKind Kind, 116 StringRef PreciseIdentifier = "", 117 const Decl *Declaration = nullptr) { 118 Fragments.insert(It, 119 Fragment(Spelling, Kind, PreciseIdentifier, Declaration)); 120 return *this; 121 } 122 123 DeclarationFragments &insert(FragmentIterator It, 124 DeclarationFragments &&Other) { 125 Fragments.insert(It, std::make_move_iterator(Other.Fragments.begin()), 126 std::make_move_iterator(Other.Fragments.end())); 127 Other.Fragments.clear(); 128 return *this; 129 } 130 131 /// Append a new Fragment to the end of the Fragments. 132 /// 133 /// \returns a reference to the DeclarationFragments object itself after 134 /// appending to chain up consecutive appends. 135 DeclarationFragments &append(StringRef Spelling, FragmentKind Kind, 136 StringRef PreciseIdentifier = "", 137 const Decl *Declaration = nullptr) { 138 if (Kind == FragmentKind::Text && !Fragments.empty() && 139 Fragments.back().Kind == FragmentKind::Text) { 140 // If appending a text fragment, and the last fragment is also text, 141 // merge into the last fragment. 142 Fragments.back().Spelling.append(Spelling.data(), Spelling.size()); 143 } else { 144 Fragments.emplace_back(Spelling, Kind, PreciseIdentifier, Declaration); 145 } 146 return *this; 147 } 148 149 /// Append another DeclarationFragments to the end. 150 /// 151 /// Note: \p Other is moved from and cannot be used after a call to this 152 /// method. 153 /// 154 /// \returns a reference to the DeclarationFragments object itself after 155 /// appending to chain up consecutive appends. 156 DeclarationFragments &append(DeclarationFragments &&Other) { 157 Fragments.insert(Fragments.end(), 158 std::make_move_iterator(Other.Fragments.begin()), 159 std::make_move_iterator(Other.Fragments.end())); 160 Other.Fragments.clear(); 161 return *this; 162 } 163 164 /// Append a text Fragment of a space character. 165 /// 166 /// \returns a reference to the DeclarationFragments object itself after 167 /// appending to chain up consecutive appends. 168 DeclarationFragments &appendSpace(); 169 170 /// Get the string description of a FragmentKind \p Kind. 171 static StringRef getFragmentKindString(FragmentKind Kind); 172 173 /// Get the corresponding FragmentKind from string \p S. 174 static FragmentKind parseFragmentKindFromString(StringRef S); 175 176 private: 177 std::vector<Fragment> Fragments; 178 }; 179 180 /// Store function signature information with DeclarationFragments of the 181 /// return type and parameters. 182 class FunctionSignature { 183 public: 184 FunctionSignature() = default; 185 186 /// Parameter holds the name and DeclarationFragments of a single parameter. 187 struct Parameter { 188 std::string Name; 189 DeclarationFragments Fragments; 190 191 Parameter(StringRef Name, DeclarationFragments Fragments) 192 : Name(Name), Fragments(Fragments) {} 193 }; 194 195 const std::vector<Parameter> &getParameters() const { return Parameters; } 196 const DeclarationFragments &getReturnType() const { return ReturnType; } 197 198 FunctionSignature &addParameter(StringRef Name, 199 DeclarationFragments Fragments) { 200 Parameters.emplace_back(Name, Fragments); 201 return *this; 202 } 203 204 void setReturnType(DeclarationFragments RT) { ReturnType = RT; } 205 206 /// Determine if the FunctionSignature is empty. 207 /// 208 /// \returns true if the return type DeclarationFragments is empty and there 209 /// is no parameter, otherwise false. 210 bool empty() const { 211 return Parameters.empty() && ReturnType.getFragments().empty(); 212 } 213 214 private: 215 std::vector<Parameter> Parameters; 216 DeclarationFragments ReturnType; 217 }; 218 219 /// A factory class to build DeclarationFragments for different kinds of Decl. 220 class DeclarationFragmentsBuilder { 221 public: 222 /// Build DeclarationFragments for a variable declaration VarDecl. 223 static DeclarationFragments getFragmentsForVar(const VarDecl *); 224 225 /// Build DeclarationFragments for a function declaration FunctionDecl. 226 static DeclarationFragments getFragmentsForFunction(const FunctionDecl *); 227 228 /// Build DeclarationFragments for an enum constant declaration 229 /// EnumConstantDecl. 230 static DeclarationFragments 231 getFragmentsForEnumConstant(const EnumConstantDecl *); 232 233 /// Build DeclarationFragments for an enum declaration EnumDecl. 234 static DeclarationFragments getFragmentsForEnum(const EnumDecl *); 235 236 /// Build DeclarationFragments for a field declaration FieldDecl. 237 static DeclarationFragments getFragmentsForField(const FieldDecl *); 238 239 /// Build DeclarationFragments for a struct record declaration RecordDecl. 240 static DeclarationFragments getFragmentsForStruct(const RecordDecl *); 241 242 /// Build DeclarationFragments for an Objective-C category declaration 243 /// ObjCCategoryDecl. 244 static DeclarationFragments 245 getFragmentsForObjCCategory(const ObjCCategoryDecl *); 246 247 /// Build DeclarationFragments for an Objective-C interface declaration 248 /// ObjCInterfaceDecl. 249 static DeclarationFragments 250 getFragmentsForObjCInterface(const ObjCInterfaceDecl *); 251 252 /// Build DeclarationFragments for an Objective-C method declaration 253 /// ObjCMethodDecl. 254 static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *); 255 256 /// Build DeclarationFragments for an Objective-C property declaration 257 /// ObjCPropertyDecl. 258 static DeclarationFragments 259 getFragmentsForObjCProperty(const ObjCPropertyDecl *); 260 261 /// Build DeclarationFragments for an Objective-C protocol declaration 262 /// ObjCProtocolDecl. 263 static DeclarationFragments 264 getFragmentsForObjCProtocol(const ObjCProtocolDecl *); 265 266 /// Build DeclarationFragments for a macro. 267 /// 268 /// \param Name name of the macro. 269 /// \param MD the associated MacroDirective. 270 static DeclarationFragments getFragmentsForMacro(StringRef Name, 271 const MacroDirective *MD); 272 273 /// Build DeclarationFragments for a typedef \p TypedefNameDecl. 274 static DeclarationFragments 275 getFragmentsForTypedef(const TypedefNameDecl *Decl); 276 277 /// Build sub-heading fragments for a NamedDecl. 278 static DeclarationFragments getSubHeading(const NamedDecl *); 279 280 /// Build sub-heading fragments for an Objective-C method. 281 static DeclarationFragments getSubHeading(const ObjCMethodDecl *); 282 283 /// Build a sub-heading for macro \p Name. 284 static DeclarationFragments getSubHeadingForMacro(StringRef Name); 285 286 /// Build FunctionSignature for a function-like declaration \c FunctionT like 287 /// FunctionDecl or ObjCMethodDecl. 288 /// 289 /// The logic and implementation of building a signature for a FunctionDecl 290 /// and an ObjCMethodDecl are exactly the same, but they do not share a common 291 /// base. This template helps reuse the code. 292 template <typename FunctionT> 293 static FunctionSignature getFunctionSignature(const FunctionT *); 294 295 private: 296 DeclarationFragmentsBuilder() = delete; 297 298 /// Build DeclarationFragments for a QualType. 299 static DeclarationFragments getFragmentsForType(const QualType, ASTContext &, 300 DeclarationFragments &); 301 302 /// Build DeclarationFragments for a Type. 303 static DeclarationFragments getFragmentsForType(const Type *, ASTContext &, 304 DeclarationFragments &); 305 306 /// Build DeclarationFragments for a NestedNameSpecifier. 307 static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *, 308 ASTContext &, 309 DeclarationFragments &); 310 311 /// Build DeclarationFragments for Qualifiers. 312 static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals); 313 314 /// Build DeclarationFragments for a parameter variable declaration 315 /// ParmVarDecl. 316 static DeclarationFragments getFragmentsForParam(const ParmVarDecl *); 317 }; 318 319 } // namespace extractapi 320 } // namespace clang 321 322 #endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H 323