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 const std::vector<Fragment> &getFragments() const { return Fragments; } 101 102 /// Append a new Fragment to the end of the Fragments. 103 /// 104 /// \returns a reference to the DeclarationFragments object itself after 105 /// appending to chain up consecutive appends. 106 DeclarationFragments &append(StringRef Spelling, FragmentKind Kind, 107 StringRef PreciseIdentifier = "", 108 const Decl *Declaration = nullptr) { 109 if (Kind == FragmentKind::Text && !Fragments.empty() && 110 Fragments.back().Kind == FragmentKind::Text) { 111 // If appending a text fragment, and the last fragment is also text, 112 // merge into the last fragment. 113 Fragments.back().Spelling.append(Spelling.data(), Spelling.size()); 114 } else { 115 Fragments.emplace_back(Spelling, Kind, PreciseIdentifier, Declaration); 116 } 117 return *this; 118 } 119 120 /// Append another DeclarationFragments to the end. 121 /// 122 /// Note: \p Other is moved from and cannot be used after a call to this 123 /// method. 124 /// 125 /// \returns a reference to the DeclarationFragments object itself after 126 /// appending to chain up consecutive appends. 127 DeclarationFragments &append(DeclarationFragments &&Other) { 128 Fragments.insert(Fragments.end(), 129 std::make_move_iterator(Other.Fragments.begin()), 130 std::make_move_iterator(Other.Fragments.end())); 131 Other.Fragments.clear(); 132 return *this; 133 } 134 135 /// Append a text Fragment of a space character. 136 /// 137 /// \returns a reference to the DeclarationFragments object itself after 138 /// appending to chain up consecutive appends. 139 DeclarationFragments &appendSpace(); 140 141 /// Get the string description of a FragmentKind \p Kind. 142 static StringRef getFragmentKindString(FragmentKind Kind); 143 144 /// Get the corresponding FragmentKind from string \p S. 145 static FragmentKind parseFragmentKindFromString(StringRef S); 146 147 private: 148 std::vector<Fragment> Fragments; 149 }; 150 151 /// Store function signature information with DeclarationFragments of the 152 /// return type and parameters. 153 class FunctionSignature { 154 public: 155 FunctionSignature() = default; 156 157 /// Parameter holds the name and DeclarationFragments of a single parameter. 158 struct Parameter { 159 std::string Name; 160 DeclarationFragments Fragments; 161 162 Parameter(StringRef Name, DeclarationFragments Fragments) 163 : Name(Name), Fragments(Fragments) {} 164 }; 165 166 const std::vector<Parameter> &getParameters() const { return Parameters; } 167 const DeclarationFragments &getReturnType() const { return ReturnType; } 168 169 FunctionSignature &addParameter(StringRef Name, 170 DeclarationFragments Fragments) { 171 Parameters.emplace_back(Name, Fragments); 172 return *this; 173 } 174 175 void setReturnType(DeclarationFragments RT) { ReturnType = RT; } 176 177 /// Determine if the FunctionSignature is empty. 178 /// 179 /// \returns true if the return type DeclarationFragments is empty and there 180 /// is no parameter, otherwise false. 181 bool empty() const { 182 return Parameters.empty() && ReturnType.getFragments().empty(); 183 } 184 185 private: 186 std::vector<Parameter> Parameters; 187 DeclarationFragments ReturnType; 188 }; 189 190 /// A factory class to build DeclarationFragments for different kinds of Decl. 191 class DeclarationFragmentsBuilder { 192 public: 193 /// Build DeclarationFragments for a variable declaration VarDecl. 194 static DeclarationFragments getFragmentsForVar(const VarDecl *); 195 196 /// Build DeclarationFragments for a function declaration FunctionDecl. 197 static DeclarationFragments getFragmentsForFunction(const FunctionDecl *); 198 199 /// Build DeclarationFragments for an enum constant declaration 200 /// EnumConstantDecl. 201 static DeclarationFragments 202 getFragmentsForEnumConstant(const EnumConstantDecl *); 203 204 /// Build DeclarationFragments for an enum declaration EnumDecl. 205 static DeclarationFragments getFragmentsForEnum(const EnumDecl *); 206 207 /// Build DeclarationFragments for a field declaration FieldDecl. 208 static DeclarationFragments getFragmentsForField(const FieldDecl *); 209 210 /// Build DeclarationFragments for a struct record declaration RecordDecl. 211 static DeclarationFragments getFragmentsForStruct(const RecordDecl *); 212 213 /// Build DeclarationFragments for an Objective-C category declaration 214 /// ObjCCategoryDecl. 215 static DeclarationFragments 216 getFragmentsForObjCCategory(const ObjCCategoryDecl *); 217 218 /// Build DeclarationFragments for an Objective-C interface declaration 219 /// ObjCInterfaceDecl. 220 static DeclarationFragments 221 getFragmentsForObjCInterface(const ObjCInterfaceDecl *); 222 223 /// Build DeclarationFragments for an Objective-C method declaration 224 /// ObjCMethodDecl. 225 static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *); 226 227 /// Build DeclarationFragments for an Objective-C property declaration 228 /// ObjCPropertyDecl. 229 static DeclarationFragments 230 getFragmentsForObjCProperty(const ObjCPropertyDecl *); 231 232 /// Build DeclarationFragments for an Objective-C protocol declaration 233 /// ObjCProtocolDecl. 234 static DeclarationFragments 235 getFragmentsForObjCProtocol(const ObjCProtocolDecl *); 236 237 /// Build DeclarationFragments for a macro. 238 /// 239 /// \param Name name of the macro. 240 /// \param MD the associated MacroDirective. 241 static DeclarationFragments getFragmentsForMacro(StringRef Name, 242 const MacroDirective *MD); 243 244 /// Build DeclarationFragments for a typedef \p TypedefNameDecl. 245 static DeclarationFragments 246 getFragmentsForTypedef(const TypedefNameDecl *Decl); 247 248 /// Build sub-heading fragments for a NamedDecl. 249 static DeclarationFragments getSubHeading(const NamedDecl *); 250 251 /// Build sub-heading fragments for an Objective-C method. 252 static DeclarationFragments getSubHeading(const ObjCMethodDecl *); 253 254 /// Build a sub-heading for macro \p Name. 255 static DeclarationFragments getSubHeadingForMacro(StringRef Name); 256 257 /// Build FunctionSignature for a function-like declaration \c FunctionT like 258 /// FunctionDecl or ObjCMethodDecl. 259 /// 260 /// The logic and implementation of building a signature for a FunctionDecl 261 /// and an ObjCMethodDecl are exactly the same, but they do not share a common 262 /// base. This template helps reuse the code. 263 template <typename FunctionT> 264 static FunctionSignature getFunctionSignature(const FunctionT *); 265 266 private: 267 DeclarationFragmentsBuilder() = delete; 268 269 /// Build DeclarationFragments for a QualType. 270 static DeclarationFragments getFragmentsForType(const QualType, ASTContext &, 271 DeclarationFragments &); 272 273 /// Build DeclarationFragments for a Type. 274 static DeclarationFragments getFragmentsForType(const Type *, ASTContext &, 275 DeclarationFragments &); 276 277 /// Build DeclarationFragments for a NestedNameSpecifier. 278 static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *, 279 ASTContext &, 280 DeclarationFragments &); 281 282 /// Build DeclarationFragments for Qualifiers. 283 static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals); 284 285 /// Build DeclarationFragments for a parameter variable declaration 286 /// ParmVarDecl. 287 static DeclarationFragments getFragmentsForParam(const ParmVarDecl *); 288 }; 289 290 } // namespace extractapi 291 } // namespace clang 292 293 #endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H 294