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 "llvm/ADT/SmallVector.h"
31 #include "llvm/ADT/StringRef.h"
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   // Add a new Fragment at an arbitrary offset.
119   DeclarationFragments &insert(FragmentIterator It, StringRef Spelling,
120                                FragmentKind Kind,
121                                StringRef PreciseIdentifier = "",
122                                const Decl *Declaration = nullptr) {
123     Fragments.insert(It,
124                      Fragment(Spelling, Kind, PreciseIdentifier, Declaration));
125     return *this;
126   }
127 
insert(FragmentIterator It,DeclarationFragments && Other)128   DeclarationFragments &insert(FragmentIterator It,
129                                DeclarationFragments &&Other) {
130     Fragments.insert(It, std::make_move_iterator(Other.Fragments.begin()),
131                      std::make_move_iterator(Other.Fragments.end()));
132     Other.Fragments.clear();
133     return *this;
134   }
135 
136   /// Append a new Fragment to the end of the Fragments.
137   ///
138   /// \returns a reference to the DeclarationFragments object itself after
139   /// appending to chain up consecutive appends.
140   DeclarationFragments &append(StringRef Spelling, FragmentKind Kind,
141                                StringRef PreciseIdentifier = "",
142                                const Decl *Declaration = nullptr) {
143     if (Kind == FragmentKind::Text && !Fragments.empty() &&
144         Fragments.back().Kind == FragmentKind::Text) {
145       // If appending a text fragment, and the last fragment is also text,
146       // merge into the last fragment.
147       Fragments.back().Spelling.append(Spelling.data(), Spelling.size());
148     } else {
149       Fragments.emplace_back(Spelling, Kind, PreciseIdentifier, Declaration);
150     }
151     return *this;
152   }
153 
154   /// Append another DeclarationFragments to the end.
155   ///
156   /// Note: \p Other is moved from and cannot be used after a call to this
157   /// method.
158   ///
159   /// \returns a reference to the DeclarationFragments object itself after
160   /// appending to chain up consecutive appends.
append(DeclarationFragments && Other)161   DeclarationFragments &append(DeclarationFragments &&Other) {
162     Fragments.insert(Fragments.end(),
163                      std::make_move_iterator(Other.Fragments.begin()),
164                      std::make_move_iterator(Other.Fragments.end()));
165     Other.Fragments.clear();
166     return *this;
167   }
168 
pop_back()169   DeclarationFragments &pop_back() {
170     Fragments.pop_back();
171     return *this;
172   }
173 
replace(std::string NewSpelling,unsigned Position)174   DeclarationFragments &replace(std::string NewSpelling, unsigned Position) {
175     Fragments.at(Position).Spelling = NewSpelling;
176     return *this;
177   }
178 
179   /// Append a text Fragment of a space character.
180   ///
181   /// \returns a reference to the DeclarationFragments object itself after
182   /// appending to chain up consecutive appends.
183   DeclarationFragments &appendSpace();
184 
185   /// Get the string description of a FragmentKind \p Kind.
186   static StringRef getFragmentKindString(FragmentKind Kind);
187 
188   /// Get the corresponding FragmentKind from string \p S.
189   static FragmentKind parseFragmentKindFromString(StringRef S);
190 
191   static DeclarationFragments
192   getExceptionSpecificationString(ExceptionSpecificationType ExceptionSpec);
193 
194   static DeclarationFragments getStructureTypeFragment(const RecordDecl *Decl);
195 
196 private:
197   std::vector<Fragment> Fragments;
198 };
199 
200 class AccessControl {
201 public:
AccessControl(std::string Access)202   AccessControl(std::string Access) : Access(Access) {}
203 
getAccess()204   const std::string &getAccess() const { return Access; }
205 
empty()206   bool empty() const { return Access.empty(); }
207 
208 private:
209   std::string Access;
210 };
211 
212 /// Store function signature information with DeclarationFragments of the
213 /// return type and parameters.
214 class FunctionSignature {
215 public:
216   FunctionSignature() = default;
217 
218   /// Parameter holds the name and DeclarationFragments of a single parameter.
219   struct Parameter {
220     std::string Name;
221     DeclarationFragments Fragments;
222 
ParameterParameter223     Parameter(StringRef Name, DeclarationFragments Fragments)
224         : Name(Name), Fragments(Fragments) {}
225   };
226 
getParameters()227   const std::vector<Parameter> &getParameters() const { return Parameters; }
getReturnType()228   const DeclarationFragments &getReturnType() const { return ReturnType; }
229 
addParameter(StringRef Name,DeclarationFragments Fragments)230   FunctionSignature &addParameter(StringRef Name,
231                                   DeclarationFragments Fragments) {
232     Parameters.emplace_back(Name, Fragments);
233     return *this;
234   }
235 
setReturnType(DeclarationFragments RT)236   void setReturnType(DeclarationFragments RT) { ReturnType = RT; }
237 
238   /// Determine if the FunctionSignature is empty.
239   ///
240   /// \returns true if the return type DeclarationFragments is empty and there
241   /// is no parameter, otherwise false.
empty()242   bool empty() const {
243     return Parameters.empty() && ReturnType.getFragments().empty();
244   }
245 
246 private:
247   std::vector<Parameter> Parameters;
248   DeclarationFragments ReturnType;
249 };
250 
251 /// A factory class to build DeclarationFragments for different kinds of Decl.
252 class DeclarationFragmentsBuilder {
253 public:
254   /// Build FunctionSignature for a function-like declaration \c FunctionT like
255   /// FunctionDecl, ObjCMethodDecl, or CXXMethodDecl.
256   ///
257   /// The logic and implementation of building a signature for a FunctionDecl,
258   /// CXXMethodDecl, and ObjCMethodDecl are exactly the same, but they do not
259   /// share a common base. This template helps reuse the code.
260   template <typename FunctionT>
261   static FunctionSignature getFunctionSignature(const FunctionT *Function);
262 
getAccessControl(const Decl * Decl)263   static AccessControl getAccessControl(const Decl *Decl) {
264     switch (Decl->getAccess()) {
265     case AS_public:
266     case AS_none:
267       return AccessControl("public");
268     case AS_private:
269       return AccessControl("private");
270     case AS_protected:
271       return AccessControl("protected");
272     }
273     llvm_unreachable("Unhandled access control");
274   }
275 
276   static DeclarationFragments
277   getFragmentsForNamespace(const NamespaceDecl *Decl);
278 
279   /// Build DeclarationFragments for a variable declaration VarDecl.
280   static DeclarationFragments getFragmentsForVar(const VarDecl *);
281 
282   static DeclarationFragments getFragmentsForVarTemplate(const VarDecl *);
283 
284   /// Build DeclarationFragments for a function declaration FunctionDecl.
285   static DeclarationFragments getFragmentsForFunction(const FunctionDecl *);
286 
287   /// Build DeclarationFragments for an enum constant declaration
288   /// EnumConstantDecl.
289   static DeclarationFragments
290   getFragmentsForEnumConstant(const EnumConstantDecl *);
291 
292   /// Build DeclarationFragments for an enum declaration EnumDecl.
293   static DeclarationFragments getFragmentsForEnum(const EnumDecl *);
294 
295   /// Build DeclarationFragments for a field declaration FieldDecl.
296   static DeclarationFragments getFragmentsForField(const FieldDecl *);
297 
298   /// Build DeclarationFragments for a struct/union record declaration
299   /// RecordDecl.
300   static DeclarationFragments getFragmentsForRecordDecl(const RecordDecl *);
301 
302   static DeclarationFragments getFragmentsForCXXClass(const CXXRecordDecl *);
303 
304   static DeclarationFragments
305   getFragmentsForSpecialCXXMethod(const CXXMethodDecl *);
306 
307   static DeclarationFragments getFragmentsForCXXMethod(const CXXMethodDecl *);
308 
309   static DeclarationFragments
310   getFragmentsForConversionFunction(const CXXConversionDecl *);
311 
312   static DeclarationFragments
313   getFragmentsForOverloadedOperator(const CXXMethodDecl *);
314 
315   static DeclarationFragments
316       getFragmentsForTemplateParameters(ArrayRef<NamedDecl *>);
317 
318   static std::string
319   getNameForTemplateArgument(const ArrayRef<NamedDecl *>, std::string);
320 
321   static DeclarationFragments
322   getFragmentsForTemplateArguments(const ArrayRef<TemplateArgument>,
323                                    ASTContext &,
324                                    const std::optional<ArrayRef<NamedDecl *>>);
325 
326   static DeclarationFragments getFragmentsForConcept(const ConceptDecl *);
327 
328   static DeclarationFragments
329   getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl *);
330 
331   static DeclarationFragments getFragmentsForClassTemplateSpecialization(
332       const ClassTemplateSpecializationDecl *);
333 
334   static DeclarationFragments getFragmentsForClassTemplatePartialSpecialization(
335       const ClassTemplatePartialSpecializationDecl *);
336 
337   static DeclarationFragments getFragmentsForVarTemplateSpecialization(
338       const VarTemplateSpecializationDecl *);
339 
340   static DeclarationFragments getFragmentsForVarTemplatePartialSpecialization(
341       const VarTemplatePartialSpecializationDecl *);
342 
343   static DeclarationFragments
344   getFragmentsForFunctionTemplate(const FunctionTemplateDecl *Decl);
345 
346   static DeclarationFragments
347   getFragmentsForFunctionTemplateSpecialization(const FunctionDecl *Decl);
348 
349   /// Build DeclarationFragments for an Objective-C category declaration
350   /// ObjCCategoryDecl.
351   static DeclarationFragments
352   getFragmentsForObjCCategory(const ObjCCategoryDecl *);
353 
354   /// Build DeclarationFragments for an Objective-C interface declaration
355   /// ObjCInterfaceDecl.
356   static DeclarationFragments
357   getFragmentsForObjCInterface(const ObjCInterfaceDecl *);
358 
359   /// Build DeclarationFragments for an Objective-C method declaration
360   /// ObjCMethodDecl.
361   static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *);
362 
363   /// Build DeclarationFragments for an Objective-C property declaration
364   /// ObjCPropertyDecl.
365   static DeclarationFragments
366   getFragmentsForObjCProperty(const ObjCPropertyDecl *);
367 
368   /// Build DeclarationFragments for an Objective-C protocol declaration
369   /// ObjCProtocolDecl.
370   static DeclarationFragments
371   getFragmentsForObjCProtocol(const ObjCProtocolDecl *);
372 
373   /// Build DeclarationFragments for a macro.
374   ///
375   /// \param Name name of the macro.
376   /// \param MD the associated MacroDirective.
377   static DeclarationFragments getFragmentsForMacro(StringRef Name,
378                                                    const MacroDirective *MD);
379 
380   /// Build DeclarationFragments for a typedef \p TypedefNameDecl.
381   static DeclarationFragments
382   getFragmentsForTypedef(const TypedefNameDecl *Decl);
383 
384   /// Build sub-heading fragments for a NamedDecl.
385   static DeclarationFragments getSubHeading(const NamedDecl *);
386 
387   /// Build sub-heading fragments for an Objective-C method.
388   static DeclarationFragments getSubHeading(const ObjCMethodDecl *);
389 
390   /// Build a sub-heading for macro \p Name.
391   static DeclarationFragments getSubHeadingForMacro(StringRef Name);
392 
393 private:
394   DeclarationFragmentsBuilder() = delete;
395 
396   /// Build DeclarationFragments for a QualType.
397   static DeclarationFragments getFragmentsForType(const QualType, ASTContext &,
398                                                   DeclarationFragments &);
399 
400   /// Build DeclarationFragments for a Type.
401   static DeclarationFragments getFragmentsForType(const Type *, ASTContext &,
402                                                   DeclarationFragments &);
403 
404   /// Build DeclarationFragments for a NestedNameSpecifier.
405   static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *,
406                                                  ASTContext &,
407                                                  DeclarationFragments &);
408 
409   /// Build DeclarationFragments for Qualifiers.
410   static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals);
411 
412   /// Build DeclarationFragments for a parameter variable declaration
413   /// ParmVarDecl.
414   static DeclarationFragments getFragmentsForParam(const ParmVarDecl *);
415 
416   static DeclarationFragments
417   getFragmentsForBlock(const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
418                        FunctionProtoTypeLoc &BlockProto,
419                        DeclarationFragments &After);
420 };
421 
422 template <typename FunctionT>
423 FunctionSignature
getFunctionSignature(const FunctionT * Function)424 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
425   FunctionSignature Signature;
426 
427   DeclarationFragments ReturnType, After;
428   ReturnType = getFragmentsForType(Function->getReturnType(),
429                                    Function->getASTContext(), After);
430   if (isa<FunctionDecl>(Function) &&
431       dyn_cast<FunctionDecl>(Function)->getDescribedFunctionTemplate() &&
432       ReturnType.begin()->Spelling.substr(0, 14).compare("type-parameter") ==
433           0) {
434     std::string ProperArgName =
435         getNameForTemplateArgument(dyn_cast<FunctionDecl>(Function)
436                                        ->getDescribedFunctionTemplate()
437                                        ->getTemplateParameters()
438                                        ->asArray(),
439                                    ReturnType.begin()->Spelling);
440     ReturnType.begin()->Spelling.swap(ProperArgName);
441   }
442   ReturnType.append(std::move(After));
443   Signature.setReturnType(ReturnType);
444 
445   for (const auto *Param : Function->parameters())
446     Signature.addParameter(Param->getName(), getFragmentsForParam(Param));
447 
448   return Signature;
449 }
450 
451 } // namespace extractapi
452 } // namespace clang
453 
454 #endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H
455