xref: /freebsd/contrib/llvm-project/clang/include/clang/ExtractAPI/DeclarationFragments.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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
48 class DeclarationFragments {
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,
59     NumberLiteral,
60     StringLiteral,
61     Identifier,
62 
63     /// Identifier that refers to a type in the context.
64     TypeIdentifier,
65 
66     /// Parameter that's used as generics in the context. For example template
67     /// parameters.
68     GenericParameter,
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
75     ExternalParam,
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
82     InternalParam,
83 
84     Text,
85   };
86 
87   /// Fragment holds information of a single fragment.
88   struct Fragment {
89     std::string Spelling;
90     FragmentKind Kind;
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 
FragmentFragment99     Fragment(StringRef Spelling, FragmentKind Kind, StringRef PreciseIdentifier,
100              const Decl *Declaration)
101         : Spelling(Spelling), Kind(Kind), PreciseIdentifier(PreciseIdentifier),
102           Declaration(Declaration) {}
103   };
104 
105   using FragmentIterator = std::vector<Fragment>::iterator;
106   using ConstFragmentIterator = std::vector<Fragment>::const_iterator;
107 
getFragments()108   const std::vector<Fragment> &getFragments() const { return Fragments; }
109 
begin()110   FragmentIterator begin() { return Fragments.begin(); }
111 
end()112   FragmentIterator end() { return Fragments.end(); }
113 
cbegin()114   ConstFragmentIterator cbegin() const { return Fragments.cbegin(); }
115 
cend()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.
prepend(DeclarationFragments Other)122   DeclarationFragments &prepend(DeclarationFragments Other) {
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.
append(DeclarationFragments Other)130   DeclarationFragments &append(DeclarationFragments Other) {
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.
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.
insert(FragmentIterator It,DeclarationFragments Other)156   DeclarationFragments &insert(FragmentIterator It,
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 
pop_back()197   DeclarationFragments &pop_back() {
198     Fragments.pop_back();
199     return *this;
200   }
201 
replace(std::string NewSpelling,unsigned Position)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.
211   DeclarationFragments &appendSpace();
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.
217   DeclarationFragments &appendSemicolon();
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.
223   DeclarationFragments &removeTrailingSemicolon();
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
232   getExceptionSpecificationString(ExceptionSpecificationType ExceptionSpec);
233 
234   static DeclarationFragments getStructureTypeFragment(const RecordDecl *Decl);
235 
236 private:
237   DeclarationFragments &appendUnduplicatedTextCharacter(char Character);
238   std::vector<Fragment> Fragments;
239 };
240 
241 class AccessControl {
242 public:
AccessControl(std::string Access)243   AccessControl(std::string Access) : Access(Access) {}
AccessControl()244   AccessControl() : Access("public") {}
245 
getAccess()246   const std::string &getAccess() const { return Access; }
247 
empty()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.
256 class FunctionSignature {
257 public:
258   FunctionSignature() = default;
259 
260   /// Parameter holds the name and DeclarationFragments of a single parameter.
261   struct Parameter {
262     std::string Name;
263     DeclarationFragments Fragments;
264 
ParameterParameter265     Parameter(StringRef Name, DeclarationFragments Fragments)
266         : Name(Name), Fragments(Fragments) {}
267   };
268 
getParameters()269   const std::vector<Parameter> &getParameters() const { return Parameters; }
getReturnType()270   const DeclarationFragments &getReturnType() const { return ReturnType; }
271 
addParameter(StringRef Name,DeclarationFragments Fragments)272   FunctionSignature &addParameter(StringRef Name,
273                                   DeclarationFragments Fragments) {
274     Parameters.emplace_back(Name, Fragments);
275     return *this;
276   }
277 
setReturnType(DeclarationFragments RT)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.
empty()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.
294 class DeclarationFragmentsBuilder {
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 
getAccessControl(const Decl * Decl)305   static AccessControl getAccessControl(const Decl *Decl) {
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
319   getFragmentsForNamespace(const NamespaceDecl *Decl);
320 
321   /// Build DeclarationFragments for a variable declaration VarDecl.
322   static DeclarationFragments getFragmentsForVar(const VarDecl *);
323 
324   static DeclarationFragments getFragmentsForVarTemplate(const VarDecl *);
325 
326   /// Build DeclarationFragments for a function declaration FunctionDecl.
327   static DeclarationFragments getFragmentsForFunction(const FunctionDecl *);
328 
329   /// Build DeclarationFragments for an enum constant declaration
330   /// EnumConstantDecl.
331   static DeclarationFragments
332   getFragmentsForEnumConstant(const EnumConstantDecl *);
333 
334   /// Build DeclarationFragments for an enum declaration EnumDecl.
335   static DeclarationFragments getFragmentsForEnum(const EnumDecl *);
336 
337   /// Build DeclarationFragments for a field declaration FieldDecl.
338   static DeclarationFragments getFragmentsForField(const FieldDecl *);
339 
340   /// Build DeclarationFragments for a struct/union record declaration
341   /// RecordDecl.
342   static DeclarationFragments getFragmentsForRecordDecl(const RecordDecl *);
343 
344   static DeclarationFragments getFragmentsForCXXClass(const CXXRecordDecl *);
345 
346   static DeclarationFragments
347   getFragmentsForSpecialCXXMethod(const CXXMethodDecl *);
348 
349   static DeclarationFragments getFragmentsForCXXMethod(const CXXMethodDecl *);
350 
351   static DeclarationFragments
352   getFragmentsForConversionFunction(const CXXConversionDecl *);
353 
354   static DeclarationFragments
355   getFragmentsForOverloadedOperator(const CXXMethodDecl *);
356 
357   static DeclarationFragments
358       getFragmentsForTemplateParameters(ArrayRef<NamedDecl *>);
359 
360   static DeclarationFragments getFragmentsForTemplateArguments(
361       const ArrayRef<TemplateArgument>, ASTContext &,
362       const std::optional<ArrayRef<TemplateArgumentLoc>>);
363 
364   static DeclarationFragments getFragmentsForConcept(const ConceptDecl *);
365 
366   static DeclarationFragments
367   getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl *);
368 
369   static DeclarationFragments getFragmentsForClassTemplateSpecialization(
370       const ClassTemplateSpecializationDecl *);
371 
372   static DeclarationFragments getFragmentsForClassTemplatePartialSpecialization(
373       const ClassTemplatePartialSpecializationDecl *);
374 
375   static DeclarationFragments getFragmentsForVarTemplateSpecialization(
376       const VarTemplateSpecializationDecl *);
377 
378   static DeclarationFragments getFragmentsForVarTemplatePartialSpecialization(
379       const VarTemplatePartialSpecializationDecl *);
380 
381   static DeclarationFragments
382   getFragmentsForFunctionTemplate(const FunctionTemplateDecl *Decl);
383 
384   static DeclarationFragments
385   getFragmentsForFunctionTemplateSpecialization(const FunctionDecl *Decl);
386 
387   /// Build DeclarationFragments for an Objective-C category declaration
388   /// ObjCCategoryDecl.
389   static DeclarationFragments
390   getFragmentsForObjCCategory(const ObjCCategoryDecl *);
391 
392   /// Build DeclarationFragments for an Objective-C interface declaration
393   /// ObjCInterfaceDecl.
394   static DeclarationFragments
395   getFragmentsForObjCInterface(const ObjCInterfaceDecl *);
396 
397   /// Build DeclarationFragments for an Objective-C method declaration
398   /// ObjCMethodDecl.
399   static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *);
400 
401   /// Build DeclarationFragments for an Objective-C property declaration
402   /// ObjCPropertyDecl.
403   static DeclarationFragments
404   getFragmentsForObjCProperty(const ObjCPropertyDecl *);
405 
406   /// Build DeclarationFragments for an Objective-C protocol declaration
407   /// ObjCProtocolDecl.
408   static DeclarationFragments
409   getFragmentsForObjCProtocol(const ObjCProtocolDecl *);
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
420   getFragmentsForTypedef(const TypedefNameDecl *Decl);
421 
422   /// Build sub-heading fragments for a NamedDecl.
423   static DeclarationFragments getSubHeading(const NamedDecl *);
424 
425   /// Build sub-heading fragments for an Objective-C method.
426   static DeclarationFragments getSubHeading(const ObjCMethodDecl *);
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 &,
436                                                   DeclarationFragments &);
437 
438   /// Build DeclarationFragments for a Type.
439   static DeclarationFragments getFragmentsForType(const Type *, ASTContext &,
440                                                   DeclarationFragments &);
441 
442   /// Build DeclarationFragments for a NestedNameSpecifier.
443   static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *,
444                                                  ASTContext &,
445                                                  DeclarationFragments &);
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,
457                        DeclarationFragments &After);
458 };
459 
460 template <typename FunctionT>
461 FunctionSignature
getFunctionSignature(const FunctionT * Function)462 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
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
487