clang 24.0.0git
DeclarationFragments.h
Go to the documentation of this file.
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
22#include "clang/AST/Decl.h"
23#include "clang/AST/DeclCXX.h"
24#include "clang/AST/DeclObjC.h"
26#include "clang/AST/ExprCXX.h"
27#include "clang/AST/TypeLoc.h"
29#include "clang/Lex/MacroInfo.h"
30#include <iterator>
31#include <utility>
32#include <vector>
33
34namespace clang {
35namespace 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
49public:
51
52 /// The kind of a fragment.
53 enum class FragmentKind {
54 /// Unknown fragment kind.
56
62
63 /// Identifier that refers to a type in the context.
65
66 /// Parameter that's used as generics in the context. For example template
67 /// parameters.
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
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
83
85 };
86
87 /// Fragment holds information of a single fragment.
88 struct Fragment {
89 std::string Spelling;
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.
98
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 /// Prepend another DeclarationFragments to the beginning.
119 ///
120 /// \returns a reference to the DeclarationFragments object itself after
121 /// appending to chain up consecutive operations.
125
126 /// Append another DeclarationFragments to the end.
127 ///
128 /// \returns a reference to the DeclarationFragments object itself after
129 /// appending to chain up consecutive operations.
133
134 /// Append a new Fragment to the end of the Fragments.
135 ///
136 /// \returns a reference to the DeclarationFragments object itself after
137 /// appending to chain up consecutive operations.
138 DeclarationFragments &append(StringRef Spelling, FragmentKind Kind,
139 StringRef PreciseIdentifier = "",
140 const Decl *Declaration = nullptr) {
141 if (Kind == FragmentKind::Text && !Fragments.empty() &&
142 Fragments.back().Kind == FragmentKind::Text) {
143 // If appending a text fragment, and the last fragment is also text,
144 // merge into the last fragment.
145 Fragments.back().Spelling.append(Spelling.data(), Spelling.size());
146 } else {
147 Fragments.emplace_back(Spelling, Kind, PreciseIdentifier, Declaration);
148 }
149 return *this;
150 }
151
152 /// Inserts another DeclarationFragments at \p It.
153 ///
154 /// \returns a reference to the DeclarationFragments object itself after
155 /// appending to chain up consecutive operations.
158 if (Other.Fragments.empty())
159 return *this;
160
161 if (Fragments.empty()) {
162 Fragments = std::move(Other.Fragments);
163 return *this;
164 }
165
166 const auto &OtherFrags = Other.Fragments;
167 auto ToInsertBegin = std::make_move_iterator(Other.begin());
168 auto ToInsertEnd = std::make_move_iterator(Other.end());
169
170 // If we aren't inserting at the end let's make sure that we merge their
171 // last fragment with It if both are text fragments.
172 if (It != end() && It->Kind == FragmentKind::Text &&
173 OtherFrags.back().Kind == FragmentKind::Text) {
174 auto &TheirBackSpelling = OtherFrags.back().Spelling;
175 It->Spelling.reserve(It->Spelling.size() + TheirBackSpelling.size());
176 It->Spelling.insert(It->Spelling.begin(), TheirBackSpelling.begin(),
177 TheirBackSpelling.end());
178 --ToInsertEnd;
179 }
180
181 // If we aren't inserting at the beginning we want to merge their first
182 // fragment with the fragment before It if both are text fragments.
183 if (It != begin() && std::prev(It)->Kind == FragmentKind::Text &&
184 OtherFrags.front().Kind == FragmentKind::Text) {
185 auto PrevIt = std::prev(It);
186 auto &TheirFrontSpelling = OtherFrags.front().Spelling;
187 PrevIt->Spelling.reserve(PrevIt->Spelling.size() +
188 TheirFrontSpelling.size());
189 PrevIt->Spelling.append(TheirFrontSpelling);
190 ++ToInsertBegin;
191 }
192
193 Fragments.insert(It, ToInsertBegin, ToInsertEnd);
194 return *this;
195 }
196
198 Fragments.pop_back();
199 return *this;
200 }
201
202 DeclarationFragments &replace(std::string NewSpelling, unsigned Position) {
203 Fragments.at(Position).Spelling = NewSpelling;
204 return *this;
205 }
206
207 bool endsWithKeyword() const {
208 return !Fragments.empty() && Fragments.back().Kind == FragmentKind::Keyword;
209 }
210
211 /// Append a text Fragment of a space character.
212 ///
213 /// \returns a reference to the DeclarationFragments object itself after
214 /// appending to chain up consecutive operations.
216
217 /// Append a text Fragment of a semicolon character.
218 ///
219 /// \returns a reference to the DeclarationFragments object itself after
220 /// appending to chain up consecutive operations.
222
223 /// Removes a trailing semicolon character if present.
224 ///
225 /// \returns a reference to the DeclarationFragments object itself after
226 /// removing to chain up consecutive operations.
228
229 /// Get the string description of a FragmentKind \p Kind.
230 static StringRef getFragmentKindString(FragmentKind Kind);
231
232 /// Get the corresponding FragmentKind from string \p S.
233 static FragmentKind parseFragmentKindFromString(StringRef S);
234
237
239
240private:
241 DeclarationFragments &appendUnduplicatedTextCharacter(char Character);
242 std::vector<Fragment> Fragments;
243};
244
246public:
247 AccessControl(std::string Access) : Access(Access) {}
248 AccessControl() : Access("public") {}
249
250 const std::string &getAccess() const { return Access; }
251
252 bool empty() const { return Access.empty(); }
253
254private:
255 std::string Access;
256};
257
258/// Store function signature information with DeclarationFragments of the
259/// return type and parameters.
261public:
262 FunctionSignature() = default;
263
264 /// Parameter holds the name and DeclarationFragments of a single parameter.
272
273 const std::vector<Parameter> &getParameters() const { return Parameters; }
274 const DeclarationFragments &getReturnType() const { return ReturnType; }
275
277 DeclarationFragments Fragments) {
278 Parameters.emplace_back(Name, Fragments);
279 return *this;
280 }
281
282 void setReturnType(DeclarationFragments RT) { ReturnType = RT; }
283
284 /// Determine if the FunctionSignature is empty.
285 ///
286 /// \returns true if the return type DeclarationFragments is empty and there
287 /// is no parameter, otherwise false.
288 bool empty() const {
289 return Parameters.empty() && ReturnType.getFragments().empty();
290 }
291
292private:
293 std::vector<Parameter> Parameters;
294 DeclarationFragments ReturnType;
295};
296
297/// A factory class to build DeclarationFragments for different kinds of Decl.
298class DeclarationFragmentsBuilder {
299public:
300 /// Build FunctionSignature for a function-like declaration \c FunctionT like
301 /// FunctionDecl, ObjCMethodDecl, or CXXMethodDecl.
302 ///
303 /// The logic and implementation of building a signature for a FunctionDecl,
304 /// CXXMethodDecl, and ObjCMethodDecl are exactly the same, but they do not
305 /// share a common base. This template helps reuse the code.
306 template <typename FunctionT>
307 static FunctionSignature getFunctionSignature(const FunctionT *Function);
308
310 switch (Decl->getAccess()) {
311 case AS_public:
312 case AS_none:
313 return AccessControl("public");
314 case AS_private:
315 return AccessControl("private");
316 case AS_protected:
317 return AccessControl("protected");
318 }
319 llvm_unreachable("Unhandled access control");
320 }
321
324
325 /// Build DeclarationFragments for a variable declaration VarDecl.
327
329
330 /// Build DeclarationFragments for a function declaration FunctionDecl.
332
333 /// Build DeclarationFragments for an enum constant declaration
334 /// EnumConstantDecl.
337
338 /// Build DeclarationFragments for an enum declaration EnumDecl.
340
341 /// Build DeclarationFragments for a field declaration FieldDecl.
343
344 /// Build DeclarationFragments for a struct/union record declaration
345 /// RecordDecl.
347
349
352
354
357
360
363
366 const std::optional<ArrayRef<TemplateArgumentLoc>>);
367
369
372
375
378
381
384
387
390
391 /// Build DeclarationFragments for an Objective-C category declaration
392 /// ObjCCategoryDecl.
395
396 /// Build DeclarationFragments for an Objective-C interface declaration
397 /// ObjCInterfaceDecl.
400
401 /// Build DeclarationFragments for an Objective-C method declaration
402 /// ObjCMethodDecl.
404
405 /// Build DeclarationFragments for an Objective-C property declaration
406 /// ObjCPropertyDecl.
409
410 /// Build DeclarationFragments for an Objective-C protocol declaration
411 /// ObjCProtocolDecl.
414
415 /// Build DeclarationFragments for a macro.
416 ///
417 /// \param Name name of the macro.
418 /// \param MI the associated MacroInfo.
419 static DeclarationFragments getFragmentsForMacro(StringRef Name,
420 const MacroInfo *MI);
421
422 /// Build DeclarationFragments for a typedef \p TypedefNameDecl.
425
426 /// Build sub-heading fragments for a NamedDecl.
428
429 /// Build sub-heading fragments for an Objective-C method.
431
432 /// Build a sub-heading for macro \p Name.
433 static DeclarationFragments getSubHeadingForMacro(StringRef Name);
434
435private:
437
438 /// Build DeclarationFragments for a QualType.
439 static DeclarationFragments getFragmentsForType(const QualType, ASTContext &,
441
442 /// Build DeclarationFragments for a Type.
443 static DeclarationFragments getFragmentsForType(const Type *, ASTContext &,
445
446 /// Build DeclarationFragments for a NestedNameSpecifier.
448 getFragmentsForNNS(NestedNameSpecifier, ASTContext &, DeclarationFragments &);
449
450 /// Build DeclarationFragments for Qualifiers.
451 static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals);
452
453 /// Build DeclarationFragments for a parameter variable declaration
454 /// ParmVarDecl.
455 static DeclarationFragments getFragmentsForParam(const ParmVarDecl *);
456
458 getFragmentsForBlock(const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
459 FunctionProtoTypeLoc &BlockProto,
460 DeclarationFragments &After);
461};
462
463template <typename FunctionT>
464FunctionSignature
466 FunctionSignature Signature;
467
468 DeclarationFragments ReturnType, After;
469 ReturnType = getFragmentsForType(Function->getReturnType(),
470 Function->getASTContext(), After);
472 dyn_cast<FunctionDecl>(Function)->getDescribedFunctionTemplate() &&
473 StringRef(ReturnType.begin()->Spelling).starts_with("type-parameter")) {
474 std::string ProperArgName = Function->getReturnType().getAsString();
475 ReturnType.begin()->Spelling.swap(ProperArgName);
476 }
477 ReturnType.append(std::move(After));
478 Signature.setReturnType(ReturnType);
479
480 for (const auto *Param : Function->parameters())
481 Signature.addParameter(Param->getName(), getFragmentsForParam(Param));
482
483 return Signature;
484}
485
486} // namespace extractapi
487} // namespace clang
488
489#endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
Defines the clang::Expr interface and subclasses for C++ expressions.
Defines the clang::MacroInfo and clang::MacroDirective classes.
Defines various enumerations that describe declaration and type specifiers.
Defines the clang::TypeLoc interface and its subclasses.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition Decl.h:4716
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2968
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2145
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
Represents a class template specialization, which refers to a class template with a given set of temp...
Declaration of a C++20 concept.
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
AccessSpecifier getAccess() const
Definition DeclBase.h:515
An instance of this object exists for each enum constant that is defined.
Definition Decl.h:3467
Represents an enum.
Definition Decl.h:4055
Represents a member of a struct/union/class.
Definition Decl.h:3204
Represents a function declaration or definition.
Definition Decl.h:2029
Declaration of a template function.
Wrapper for source info for functions.
Definition TypeLoc.h:1644
Encapsulates the data about a macro definition (e.g.
Definition MacroInfo.h:40
This represents a decl that may have a name.
Definition Decl.h:274
Represent a C++ namespace.
Definition Decl.h:592
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
ObjCCategoryDecl - Represents a category declaration.
Definition DeclObjC.h:2329
Represents an ObjC class declaration.
Definition DeclObjC.h:1154
ObjCMethodDecl - Represents an instance or class method declaration.
Definition DeclObjC.h:140
Represents one property declaration in an Objective-C interface.
Definition DeclObjC.h:731
Represents an Objective-C protocol declaration.
Definition DeclObjC.h:2084
Represents a parameter to a function.
Definition Decl.h:1819
A (possibly-)qualified type.
Definition TypeBase.h:937
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
Represents a struct/union/class.
Definition Decl.h:4369
Declaration of a redeclarable template.
The base class of the type hierarchy.
Definition TypeBase.h:1875
Base class for declarations which introduce a typedef-name.
Definition Decl.h:3606
Represents a variable declaration or definition.
Definition Decl.h:932
Represents a variable template specialization, which refers to a variable template with a given set o...
const std::string & getAccess() const
A factory class to build DeclarationFragments for different kinds of Decl.
static DeclarationFragments getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl *)
static DeclarationFragments getFragmentsForCXXClass(const CXXRecordDecl *)
static DeclarationFragments getFragmentsForEnumConstant(const EnumConstantDecl *)
Build DeclarationFragments for an enum constant declaration EnumConstantDecl.
static DeclarationFragments getFragmentsForObjCCategory(const ObjCCategoryDecl *)
Build DeclarationFragments for an Objective-C category declaration ObjCCategoryDecl.
static DeclarationFragments getFragmentsForMacro(StringRef Name, const MacroInfo *MI)
Build DeclarationFragments for a macro.
static DeclarationFragments getFragmentsForTypedef(const TypedefNameDecl *Decl)
Build DeclarationFragments for a typedef TypedefNameDecl.
static DeclarationFragments getFragmentsForEnum(const EnumDecl *)
Build DeclarationFragments for an enum declaration EnumDecl.
static DeclarationFragments getFragmentsForConversionFunction(const CXXConversionDecl *)
static DeclarationFragments getFragmentsForClassTemplateSpecialization(const ClassTemplateSpecializationDecl *)
static DeclarationFragments getFragmentsForTemplateParameters(ArrayRef< NamedDecl * >)
static DeclarationFragments getFragmentsForObjCProtocol(const ObjCProtocolDecl *)
Build DeclarationFragments for an Objective-C protocol declaration ObjCProtocolDecl.
static DeclarationFragments getFragmentsForConcept(const ConceptDecl *)
static DeclarationFragments getFragmentsForField(const FieldDecl *)
Build DeclarationFragments for a field declaration FieldDecl.
static DeclarationFragments getFragmentsForVar(const VarDecl *)
Build DeclarationFragments for a variable declaration VarDecl.
static DeclarationFragments getFragmentsForTemplateArguments(const ArrayRef< TemplateArgument >, ASTContext &, const std::optional< ArrayRef< TemplateArgumentLoc > >)
static DeclarationFragments getFragmentsForClassTemplatePartialSpecialization(const ClassTemplatePartialSpecializationDecl *)
static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *)
Build DeclarationFragments for an Objective-C method declaration ObjCMethodDecl.
static DeclarationFragments getSubHeadingForMacro(StringRef Name)
Build a sub-heading for macro Name.
static DeclarationFragments getFragmentsForFunction(const FunctionDecl *)
Build DeclarationFragments for a function declaration FunctionDecl.
static AccessControl getAccessControl(const Decl *Decl)
static DeclarationFragments getFragmentsForObjCProperty(const ObjCPropertyDecl *)
Build DeclarationFragments for an Objective-C property declaration ObjCPropertyDecl.
static DeclarationFragments getFragmentsForSpecialCXXMethod(const CXXMethodDecl *)
static DeclarationFragments getFragmentsForCXXMethod(const CXXMethodDecl *)
static DeclarationFragments getFragmentsForNamespace(const NamespaceDecl *Decl)
static DeclarationFragments getFragmentsForVarTemplatePartialSpecialization(const VarTemplatePartialSpecializationDecl *)
static DeclarationFragments getFragmentsForFunctionTemplate(const FunctionTemplateDecl *Decl)
static DeclarationFragments getFragmentsForVarTemplateSpecialization(const VarTemplateSpecializationDecl *)
static FunctionSignature getFunctionSignature(const FunctionT *Function)
Build FunctionSignature for a function-like declaration FunctionT like FunctionDecl,...
static DeclarationFragments getSubHeading(const NamedDecl *)
Build sub-heading fragments for a NamedDecl.
static DeclarationFragments getFragmentsForVarTemplate(const VarDecl *)
static DeclarationFragments getFragmentsForOverloadedOperator(const CXXMethodDecl *)
static DeclarationFragments getFragmentsForFunctionTemplateSpecialization(const FunctionDecl *Decl)
static DeclarationFragments getFragmentsForRecordDecl(const RecordDecl *)
Build DeclarationFragments for a struct/union record declaration RecordDecl.
static DeclarationFragments getFragmentsForObjCInterface(const ObjCInterfaceDecl *)
Build DeclarationFragments for an Objective-C interface declaration ObjCInterfaceDecl.
DeclarationFragments is a vector of tagged important parts of a symbol's declaration.
DeclarationFragments & replace(std::string NewSpelling, unsigned Position)
std::vector< Fragment >::iterator FragmentIterator
DeclarationFragments & append(DeclarationFragments Other)
Append another DeclarationFragments to the end.
const std::vector< Fragment > & getFragments() const
DeclarationFragments & appendSpace()
Append a text Fragment of a space character.
DeclarationFragments & prepend(DeclarationFragments Other)
Prepend another DeclarationFragments to the beginning.
static DeclarationFragments getExceptionSpecificationString(ExceptionSpecificationType ExceptionSpec)
DeclarationFragments & insert(FragmentIterator It, DeclarationFragments Other)
Inserts another DeclarationFragments at It.
@ GenericParameter
Parameter that's used as generics in the context.
@ ExternalParam
External parameters in Objective-C methods.
@ TypeIdentifier
Identifier that refers to a type in the context.
@ InternalParam
Internal/local parameters in Objective-C methods.
DeclarationFragments & removeTrailingSemicolon()
Removes a trailing semicolon character if present.
static StringRef getFragmentKindString(FragmentKind Kind)
Get the string description of a FragmentKind Kind.
static DeclarationFragments getStructureTypeFragment(const RecordDecl *Decl)
std::vector< Fragment >::const_iterator ConstFragmentIterator
DeclarationFragments & appendSemicolon()
Append a text Fragment of a semicolon character.
static FragmentKind parseFragmentKindFromString(StringRef S)
Get the corresponding FragmentKind from string S.
DeclarationFragments & append(StringRef Spelling, FragmentKind Kind, StringRef PreciseIdentifier="", const Decl *Declaration=nullptr)
Append a new Fragment to the end of the Fragments.
Store function signature information with DeclarationFragments of the return type and parameters.
FunctionSignature & addParameter(StringRef Name, DeclarationFragments Fragments)
void setReturnType(DeclarationFragments RT)
const std::vector< Parameter > & getParameters() const
const DeclarationFragments & getReturnType() const
bool empty() const
Determine if the FunctionSignature is empty.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ AS_public
Definition Specifiers.h:125
@ AS_protected
Definition Specifiers.h:126
@ AS_none
Definition Specifiers.h:128
@ AS_private
Definition Specifiers.h:127
@ Other
Other implicit parameter.
Definition Decl.h:1774
ExceptionSpecificationType
The various types of exception specifications that exist in C++11.
std::string PreciseIdentifier
The USR of the fragment symbol, if applicable.
const Decl * Declaration
The associated declaration, if applicable.
Fragment(StringRef Spelling, FragmentKind Kind, StringRef PreciseIdentifier, const Decl *Declaration)
Parameter(StringRef Name, DeclarationFragments Fragments)