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