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 
99     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 
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   // 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 
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.
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 
169   DeclarationFragments &pop_back() {
170     Fragments.pop_back();
171     return *this;
172   }
173 
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:
202   AccessControl(std::string Access) : Access(Access) {}
203 
204   const std::string &getAccess() const { return Access; }
205 
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 
223     Parameter(StringRef Name, DeclarationFragments Fragments)
224         : Name(Name), Fragments(Fragments) {}
225   };
226 
227   const std::vector<Parameter> &getParameters() const { return Parameters; }
228   const DeclarationFragments &getReturnType() const { return ReturnType; }
229 
230   FunctionSignature &addParameter(StringRef Name,
231                                   DeclarationFragments Fragments) {
232     Parameters.emplace_back(Name, Fragments);
233     return *this;
234   }
235 
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.
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 
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 record declaration RecordDecl.
299   static DeclarationFragments getFragmentsForStruct(const RecordDecl *);
300 
301   static DeclarationFragments getFragmentsForCXXClass(const CXXRecordDecl *);
302 
303   static DeclarationFragments
304   getFragmentsForSpecialCXXMethod(const CXXMethodDecl *);
305 
306   static DeclarationFragments getFragmentsForCXXMethod(const CXXMethodDecl *);
307 
308   static DeclarationFragments
309   getFragmentsForConversionFunction(const CXXConversionDecl *);
310 
311   static DeclarationFragments
312   getFragmentsForOverloadedOperator(const CXXMethodDecl *);
313 
314   static DeclarationFragments
315       getFragmentsForTemplateParameters(ArrayRef<NamedDecl *>);
316 
317   static std::string
318   getNameForTemplateArgument(const ArrayRef<NamedDecl *>, std::string);
319 
320   static DeclarationFragments
321   getFragmentsForTemplateArguments(const ArrayRef<TemplateArgument>,
322                                    ASTContext &,
323                                    const std::optional<ArrayRef<NamedDecl *>>);
324 
325   static DeclarationFragments getFragmentsForConcept(const ConceptDecl *);
326 
327   static DeclarationFragments
328   getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl *);
329 
330   static DeclarationFragments getFragmentsForClassTemplateSpecialization(
331       const ClassTemplateSpecializationDecl *);
332 
333   static DeclarationFragments getFragmentsForClassTemplatePartialSpecialization(
334       const ClassTemplatePartialSpecializationDecl *);
335 
336   static DeclarationFragments getFragmentsForVarTemplateSpecialization(
337       const VarTemplateSpecializationDecl *);
338 
339   static DeclarationFragments getFragmentsForVarTemplatePartialSpecialization(
340       const VarTemplatePartialSpecializationDecl *);
341 
342   static DeclarationFragments
343   getFragmentsForFunctionTemplate(const FunctionTemplateDecl *Decl);
344 
345   static DeclarationFragments
346   getFragmentsForFunctionTemplateSpecialization(const FunctionDecl *Decl);
347 
348   /// Build DeclarationFragments for an Objective-C category declaration
349   /// ObjCCategoryDecl.
350   static DeclarationFragments
351   getFragmentsForObjCCategory(const ObjCCategoryDecl *);
352 
353   /// Build DeclarationFragments for an Objective-C interface declaration
354   /// ObjCInterfaceDecl.
355   static DeclarationFragments
356   getFragmentsForObjCInterface(const ObjCInterfaceDecl *);
357 
358   /// Build DeclarationFragments for an Objective-C method declaration
359   /// ObjCMethodDecl.
360   static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *);
361 
362   /// Build DeclarationFragments for an Objective-C property declaration
363   /// ObjCPropertyDecl.
364   static DeclarationFragments
365   getFragmentsForObjCProperty(const ObjCPropertyDecl *);
366 
367   /// Build DeclarationFragments for an Objective-C protocol declaration
368   /// ObjCProtocolDecl.
369   static DeclarationFragments
370   getFragmentsForObjCProtocol(const ObjCProtocolDecl *);
371 
372   /// Build DeclarationFragments for a macro.
373   ///
374   /// \param Name name of the macro.
375   /// \param MD the associated MacroDirective.
376   static DeclarationFragments getFragmentsForMacro(StringRef Name,
377                                                    const MacroDirective *MD);
378 
379   /// Build DeclarationFragments for a typedef \p TypedefNameDecl.
380   static DeclarationFragments
381   getFragmentsForTypedef(const TypedefNameDecl *Decl);
382 
383   /// Build sub-heading fragments for a NamedDecl.
384   static DeclarationFragments getSubHeading(const NamedDecl *);
385 
386   /// Build sub-heading fragments for an Objective-C method.
387   static DeclarationFragments getSubHeading(const ObjCMethodDecl *);
388 
389   /// Build a sub-heading for macro \p Name.
390   static DeclarationFragments getSubHeadingForMacro(StringRef Name);
391 
392 private:
393   DeclarationFragmentsBuilder() = delete;
394 
395   /// Build DeclarationFragments for a QualType.
396   static DeclarationFragments getFragmentsForType(const QualType, ASTContext &,
397                                                   DeclarationFragments &);
398 
399   /// Build DeclarationFragments for a Type.
400   static DeclarationFragments getFragmentsForType(const Type *, ASTContext &,
401                                                   DeclarationFragments &);
402 
403   /// Build DeclarationFragments for a NestedNameSpecifier.
404   static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *,
405                                                  ASTContext &,
406                                                  DeclarationFragments &);
407 
408   /// Build DeclarationFragments for Qualifiers.
409   static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals);
410 
411   /// Build DeclarationFragments for a parameter variable declaration
412   /// ParmVarDecl.
413   static DeclarationFragments getFragmentsForParam(const ParmVarDecl *);
414 
415   static DeclarationFragments
416   getFragmentsForBlock(const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
417                        FunctionProtoTypeLoc &BlockProto,
418                        DeclarationFragments &After);
419 };
420 
421 template <typename FunctionT>
422 FunctionSignature
423 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
424   FunctionSignature Signature;
425 
426   DeclarationFragments ReturnType, After;
427   ReturnType = getFragmentsForType(Function->getReturnType(),
428                                    Function->getASTContext(), After);
429   if (isa<FunctionDecl>(Function) &&
430       dyn_cast<FunctionDecl>(Function)->getDescribedFunctionTemplate() &&
431       ReturnType.begin()->Spelling.substr(0, 14).compare("type-parameter") ==
432           0) {
433     std::string ProperArgName =
434         getNameForTemplateArgument(dyn_cast<FunctionDecl>(Function)
435                                        ->getDescribedFunctionTemplate()
436                                        ->getTemplateParameters()
437                                        ->asArray(),
438                                    ReturnType.begin()->Spelling);
439     ReturnType.begin()->Spelling.swap(ProperArgName);
440   }
441   ReturnType.append(std::move(After));
442   Signature.setReturnType(ReturnType);
443 
444   for (const auto *Param : Function->parameters())
445     Signature.addParameter(Param->getName(), getFragmentsForParam(Param));
446 
447   return Signature;
448 }
449 
450 } // namespace extractapi
451 } // namespace clang
452 
453 #endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H
454