clang  19.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 
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 <iterator>
31 #include <utility>
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
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,
61  Identifier,
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 
84  Text,
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.
97  const Decl *Declaration;
98 
100  const Decl *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  /// Prepend another DeclarationFragments to the beginning.
119  ///
120  /// \returns a reference to the DeclarationFragments object itself after
121  /// appending to chain up consecutive operations.
123  return insert(begin(), std::move(Other));
124  }
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.
131  return insert(end(), std::move(Other));
132  }
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.
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.
157  DeclarationFragments Other) {
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  /// Append a text Fragment of a space character.
208  ///
209  /// \returns a reference to the DeclarationFragments object itself after
210  /// appending to chain up consecutive operations.
212 
213  /// Append a text Fragment of a semicolon character.
214  ///
215  /// \returns a reference to the DeclarationFragments object itself after
216  /// appending to chain up consecutive operations.
218 
219  /// Removes a trailing semicolon character if present.
220  ///
221  /// \returns a reference to the DeclarationFragments object itself after
222  /// removing to chain up consecutive operations.
224 
225  /// Get the string description of a FragmentKind \p Kind.
226  static StringRef getFragmentKindString(FragmentKind Kind);
227 
228  /// Get the corresponding FragmentKind from string \p S.
229  static FragmentKind parseFragmentKindFromString(StringRef S);
230 
231  static DeclarationFragments
233 
235 
236 private:
237  DeclarationFragments &appendUnduplicatedTextCharacter(char Character);
238  std::vector<Fragment> Fragments;
239 };
240 
242 public:
243  AccessControl(std::string Access) : Access(Access) {}
244  AccessControl() : Access("public") {}
245 
246  const std::string &getAccess() const { return Access; }
247 
248  bool empty() const { return Access.empty(); }
249 
250 private:
251  std::string Access;
252 };
253 
254 /// Store function signature information with DeclarationFragments of the
255 /// return type and parameters.
257 public:
258  FunctionSignature() = default;
259 
260  /// Parameter holds the name and DeclarationFragments of a single parameter.
261  struct Parameter {
262  std::string Name;
264 
266  : Name(Name), Fragments(Fragments) {}
267  };
268 
269  const std::vector<Parameter> &getParameters() const { return Parameters; }
270  const DeclarationFragments &getReturnType() const { return ReturnType; }
271 
273  DeclarationFragments Fragments) {
274  Parameters.emplace_back(Name, Fragments);
275  return *this;
276  }
277 
278  void setReturnType(DeclarationFragments RT) { ReturnType = RT; }
279 
280  /// Determine if the FunctionSignature is empty.
281  ///
282  /// \returns true if the return type DeclarationFragments is empty and there
283  /// is no parameter, otherwise false.
284  bool empty() const {
285  return Parameters.empty() && ReturnType.getFragments().empty();
286  }
287 
288 private:
289  std::vector<Parameter> Parameters;
290  DeclarationFragments ReturnType;
291 };
292 
293 /// A factory class to build DeclarationFragments for different kinds of Decl.
295 public:
296  /// Build FunctionSignature for a function-like declaration \c FunctionT like
297  /// FunctionDecl, ObjCMethodDecl, or CXXMethodDecl.
298  ///
299  /// The logic and implementation of building a signature for a FunctionDecl,
300  /// CXXMethodDecl, and ObjCMethodDecl are exactly the same, but they do not
301  /// share a common base. This template helps reuse the code.
302  template <typename FunctionT>
303  static FunctionSignature getFunctionSignature(const FunctionT *Function);
304 
306  switch (Decl->getAccess()) {
307  case AS_public:
308  case AS_none:
309  return AccessControl("public");
310  case AS_private:
311  return AccessControl("private");
312  case AS_protected:
313  return AccessControl("protected");
314  }
315  llvm_unreachable("Unhandled access control");
316  }
317 
318  static DeclarationFragments
320 
321  /// Build DeclarationFragments for a variable declaration VarDecl.
323 
325 
326  /// Build DeclarationFragments for a function declaration FunctionDecl.
328 
329  /// Build DeclarationFragments for an enum constant declaration
330  /// EnumConstantDecl.
331  static DeclarationFragments
333 
334  /// Build DeclarationFragments for an enum declaration EnumDecl.
336 
337  /// Build DeclarationFragments for a field declaration FieldDecl.
339 
340  /// Build DeclarationFragments for a struct/union record declaration
341  /// RecordDecl.
343 
345 
346  static DeclarationFragments
348 
350 
351  static DeclarationFragments
353 
354  static DeclarationFragments
356 
357  static DeclarationFragments
359 
362  const std::optional<ArrayRef<TemplateArgumentLoc>>);
363 
365 
366  static DeclarationFragments
368 
371 
374 
377 
380 
381  static DeclarationFragments
383 
384  static DeclarationFragments
386 
387  /// Build DeclarationFragments for an Objective-C category declaration
388  /// ObjCCategoryDecl.
389  static DeclarationFragments
391 
392  /// Build DeclarationFragments for an Objective-C interface declaration
393  /// ObjCInterfaceDecl.
394  static DeclarationFragments
396 
397  /// Build DeclarationFragments for an Objective-C method declaration
398  /// ObjCMethodDecl.
400 
401  /// Build DeclarationFragments for an Objective-C property declaration
402  /// ObjCPropertyDecl.
403  static DeclarationFragments
405 
406  /// Build DeclarationFragments for an Objective-C protocol declaration
407  /// ObjCProtocolDecl.
408  static DeclarationFragments
410 
411  /// Build DeclarationFragments for a macro.
412  ///
413  /// \param Name name of the macro.
414  /// \param MD the associated MacroDirective.
415  static DeclarationFragments getFragmentsForMacro(StringRef Name,
416  const MacroDirective *MD);
417 
418  /// Build DeclarationFragments for a typedef \p TypedefNameDecl.
419  static DeclarationFragments
421 
422  /// Build sub-heading fragments for a NamedDecl.
424 
425  /// Build sub-heading fragments for an Objective-C method.
427 
428  /// Build a sub-heading for macro \p Name.
429  static DeclarationFragments getSubHeadingForMacro(StringRef Name);
430 
431 private:
432  DeclarationFragmentsBuilder() = delete;
433 
434  /// Build DeclarationFragments for a QualType.
435  static DeclarationFragments getFragmentsForType(const QualType, ASTContext &,
437 
438  /// Build DeclarationFragments for a Type.
439  static DeclarationFragments getFragmentsForType(const Type *, ASTContext &,
441 
442  /// Build DeclarationFragments for a NestedNameSpecifier.
443  static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *,
444  ASTContext &,
446 
447  /// Build DeclarationFragments for Qualifiers.
448  static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals);
449 
450  /// Build DeclarationFragments for a parameter variable declaration
451  /// ParmVarDecl.
452  static DeclarationFragments getFragmentsForParam(const ParmVarDecl *);
453 
454  static DeclarationFragments
455  getFragmentsForBlock(const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
456  FunctionProtoTypeLoc &BlockProto,
458 };
459 
460 template <typename FunctionT>
461 FunctionSignature
463  FunctionSignature Signature;
464 
465  DeclarationFragments ReturnType, After;
466  ReturnType = getFragmentsForType(Function->getReturnType(),
467  Function->getASTContext(), After);
468  if (isa<FunctionDecl>(Function) &&
469  dyn_cast<FunctionDecl>(Function)->getDescribedFunctionTemplate() &&
470  StringRef(ReturnType.begin()->Spelling).starts_with("type-parameter")) {
471  std::string ProperArgName = Function->getReturnType().getAsString();
472  ReturnType.begin()->Spelling.swap(ProperArgName);
473  }
474  ReturnType.append(std::move(After));
475  Signature.setReturnType(ReturnType);
476 
477  for (const auto *Param : Function->parameters())
478  Signature.addParameter(Param->getName(), getFragmentsForParam(Param));
479 
480  return Signature;
481 }
482 
483 } // namespace extractapi
484 } // namespace clang
485 
486 #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:185
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition: Decl.h:4497
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2862
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2060
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:513
An instance of this object exists for each enum constant that is defined.
Definition: Decl.h:3300
Represents an enum.
Definition: Decl.h:3870
Represents a member of a struct/union/class.
Definition: Decl.h:3060
Represents a function declaration or definition.
Definition: Decl.h:1972
Declaration of a template function.
Definition: DeclTemplate.h:957
Wrapper for source info for functions.
Definition: TypeLoc.h:1428
Encapsulates changes to the "macros namespace" (the location where the macro name became active,...
Definition: MacroInfo.h:313
This represents a decl that may have a name.
Definition: Decl.h:249
Represent a C++ namespace.
Definition: Decl.h:548
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
ObjCCategoryDecl - Represents a category declaration.
Definition: DeclObjC.h:2326
Represents an ObjC class declaration.
Definition: DeclObjC.h:1153
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:140
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:730
Represents an Objective-C protocol declaration.
Definition: DeclObjC.h:2082
Represents a parameter to a function.
Definition: Decl.h:1762
A (possibly-)qualified type.
Definition: Type.h:940
The collection of all-type qualifiers we support.
Definition: Type.h:318
Represents a struct/union/class.
Definition: Decl.h:4171
Declaration of a redeclarable template.
Definition: DeclTemplate.h:716
The base class of the type hierarchy.
Definition: Type.h:1813
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:3435
Represents a variable declaration or definition.
Definition: Decl.h:919
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 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 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 getFragmentsForMacro(StringRef Name, const MacroDirective *MD)
Build DeclarationFragments for a macro.
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.
static DeclarationFragments getFragmentsForTemplateArguments(const ArrayRef< TemplateArgument >, ASTContext &, const std::optional< ArrayRef< TemplateArgumentLoc >>)
DeclarationFragments is a vector of tagged important parts of a symbol's declaration.
const std::vector< Fragment > & getFragments() const
std::vector< Fragment >::iterator FragmentIterator
DeclarationFragments & prepend(DeclarationFragments Other)
Prepend another DeclarationFragments to the beginning.
DeclarationFragments & appendSpace()
Append a text Fragment of a space character.
DeclarationFragments & insert(FragmentIterator It, DeclarationFragments Other)
Inserts another DeclarationFragments at It.
static DeclarationFragments getExceptionSpecificationString(ExceptionSpecificationType ExceptionSpec)
DeclarationFragments & append(DeclarationFragments Other)
Append another DeclarationFragments to the end.
@ 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.
DeclarationFragments & append(StringRef Spelling, FragmentKind Kind, StringRef PreciseIdentifier="", const Decl *Declaration=nullptr)
Append a new Fragment to the end of the Fragments.
static FragmentKind parseFragmentKindFromString(StringRef S)
Get the corresponding FragmentKind from string S.
DeclarationFragments & replace(std::string NewSpelling, unsigned Position)
Store function signature information with DeclarationFragments of the return type and parameters.
void setReturnType(DeclarationFragments RT)
const std::vector< Parameter > & getParameters() const
FunctionSignature & addParameter(StringRef Name, DeclarationFragments Fragments)
const DeclarationFragments & getReturnType() const
bool empty() const
Determine if the FunctionSignature is empty.
@ After
Like System, but searched after the system directories.
The JSON file list parser is used to communicate input to InstallAPI.
@ Other
Other implicit parameter.
ExceptionSpecificationType
The various types of exception specifications that exist in C++11.
@ AS_public
Definition: Specifiers.h:121
@ AS_protected
Definition: Specifiers.h:122
@ AS_none
Definition: Specifiers.h:124
@ AS_private
Definition: Specifiers.h:123
Fragment holds information of a single fragment.
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 holds the name and DeclarationFragments of a single parameter.
Parameter(StringRef Name, DeclarationFragments Fragments)