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/Lex/MacroInfo.h"
26 #include "llvm/ADT/StringRef.h"
27 #include <vector>
28 
29 namespace clang {
30 namespace extractapi {
31 
32 /// DeclarationFragments is a vector of tagged important parts of a symbol's
33 /// declaration.
34 ///
35 /// The fragments sequence can be joined to form spans of declaration text, with
36 /// attached information useful for purposes like syntax-highlighting etc.
37 /// For example:
38 /// \code
39 ///   const -> keyword    "const"
40 ///   int   -> type       "int"
41 ///   pi;   -> identifier "pi"
42 /// \endcode
43 class DeclarationFragments {
44 public:
45   DeclarationFragments() = default;
46 
47   /// The kind of a fragment.
48   enum class FragmentKind {
49     /// Unknown fragment kind.
50     None,
51 
52     Keyword,
53     Attribute,
54     NumberLiteral,
55     StringLiteral,
56     Identifier,
57 
58     /// Identifier that refers to a type in the context.
59     TypeIdentifier,
60 
61     /// Parameter that's used as generics in the context. For example template
62     /// parameters.
63     GenericParameter,
64 
65     /// External parameters in Objective-C methods.
66     /// For example, \c forKey in
67     /// \code{.m}
68     ///   - (void) setValue:(Value)value forKey(Key)key
69     /// \endcode
70     ExternalParam,
71 
72     /// Internal/local parameters in Objective-C methods.
73     /// For example, \c key in
74     /// \code{.m}
75     ///   - (void) setValue:(Value)value forKey(Key)key
76     /// \endcode
77     InternalParam,
78 
79     Text,
80   };
81 
82   /// Fragment holds information of a single fragment.
83   struct Fragment {
84     std::string Spelling;
85     FragmentKind Kind;
86 
87     /// The USR of the fragment symbol, if applicable.
88     std::string PreciseIdentifier;
89 
90     /// The associated declaration, if applicable. This is not intended to be
91     /// used outside of libclang.
92     const Decl *Declaration;
93 
94     Fragment(StringRef Spelling, FragmentKind Kind, StringRef PreciseIdentifier,
95              const Decl *Declaration)
96         : Spelling(Spelling), Kind(Kind), PreciseIdentifier(PreciseIdentifier),
97           Declaration(Declaration) {}
98   };
99 
100   using FragmentIterator = std::vector<Fragment>::iterator;
101   using ConstFragmentIterator = std::vector<Fragment>::const_iterator;
102 
103   const std::vector<Fragment> &getFragments() const { return Fragments; }
104 
105   FragmentIterator begin() { return Fragments.begin(); }
106 
107   FragmentIterator end() { return Fragments.end(); }
108 
109   ConstFragmentIterator cbegin() const { return Fragments.cbegin(); }
110 
111   ConstFragmentIterator cend() const { return Fragments.cend(); }
112 
113   // Add a new Fragment at an arbitrary offset.
114   DeclarationFragments &insert(FragmentIterator It, StringRef Spelling,
115                                FragmentKind Kind,
116                                StringRef PreciseIdentifier = "",
117                                const Decl *Declaration = nullptr) {
118     Fragments.insert(It,
119                      Fragment(Spelling, Kind, PreciseIdentifier, Declaration));
120     return *this;
121   }
122 
123   DeclarationFragments &insert(FragmentIterator It,
124                                DeclarationFragments &&Other) {
125     Fragments.insert(It, std::make_move_iterator(Other.Fragments.begin()),
126                      std::make_move_iterator(Other.Fragments.end()));
127     Other.Fragments.clear();
128     return *this;
129   }
130 
131   /// Append a new Fragment to the end of the Fragments.
132   ///
133   /// \returns a reference to the DeclarationFragments object itself after
134   /// appending to chain up consecutive appends.
135   DeclarationFragments &append(StringRef Spelling, FragmentKind Kind,
136                                StringRef PreciseIdentifier = "",
137                                const Decl *Declaration = nullptr) {
138     if (Kind == FragmentKind::Text && !Fragments.empty() &&
139         Fragments.back().Kind == FragmentKind::Text) {
140       // If appending a text fragment, and the last fragment is also text,
141       // merge into the last fragment.
142       Fragments.back().Spelling.append(Spelling.data(), Spelling.size());
143     } else {
144       Fragments.emplace_back(Spelling, Kind, PreciseIdentifier, Declaration);
145     }
146     return *this;
147   }
148 
149   /// Append another DeclarationFragments to the end.
150   ///
151   /// Note: \p Other is moved from and cannot be used after a call to this
152   /// method.
153   ///
154   /// \returns a reference to the DeclarationFragments object itself after
155   /// appending to chain up consecutive appends.
156   DeclarationFragments &append(DeclarationFragments &&Other) {
157     Fragments.insert(Fragments.end(),
158                      std::make_move_iterator(Other.Fragments.begin()),
159                      std::make_move_iterator(Other.Fragments.end()));
160     Other.Fragments.clear();
161     return *this;
162   }
163 
164   /// Append a text Fragment of a space character.
165   ///
166   /// \returns a reference to the DeclarationFragments object itself after
167   /// appending to chain up consecutive appends.
168   DeclarationFragments &appendSpace();
169 
170   /// Get the string description of a FragmentKind \p Kind.
171   static StringRef getFragmentKindString(FragmentKind Kind);
172 
173   /// Get the corresponding FragmentKind from string \p S.
174   static FragmentKind parseFragmentKindFromString(StringRef S);
175 
176 private:
177   std::vector<Fragment> Fragments;
178 };
179 
180 /// Store function signature information with DeclarationFragments of the
181 /// return type and parameters.
182 class FunctionSignature {
183 public:
184   FunctionSignature() = default;
185 
186   /// Parameter holds the name and DeclarationFragments of a single parameter.
187   struct Parameter {
188     std::string Name;
189     DeclarationFragments Fragments;
190 
191     Parameter(StringRef Name, DeclarationFragments Fragments)
192         : Name(Name), Fragments(Fragments) {}
193   };
194 
195   const std::vector<Parameter> &getParameters() const { return Parameters; }
196   const DeclarationFragments &getReturnType() const { return ReturnType; }
197 
198   FunctionSignature &addParameter(StringRef Name,
199                                   DeclarationFragments Fragments) {
200     Parameters.emplace_back(Name, Fragments);
201     return *this;
202   }
203 
204   void setReturnType(DeclarationFragments RT) { ReturnType = RT; }
205 
206   /// Determine if the FunctionSignature is empty.
207   ///
208   /// \returns true if the return type DeclarationFragments is empty and there
209   /// is no parameter, otherwise false.
210   bool empty() const {
211     return Parameters.empty() && ReturnType.getFragments().empty();
212   }
213 
214 private:
215   std::vector<Parameter> Parameters;
216   DeclarationFragments ReturnType;
217 };
218 
219 /// A factory class to build DeclarationFragments for different kinds of Decl.
220 class DeclarationFragmentsBuilder {
221 public:
222   /// Build DeclarationFragments for a variable declaration VarDecl.
223   static DeclarationFragments getFragmentsForVar(const VarDecl *);
224 
225   /// Build DeclarationFragments for a function declaration FunctionDecl.
226   static DeclarationFragments getFragmentsForFunction(const FunctionDecl *);
227 
228   /// Build DeclarationFragments for an enum constant declaration
229   /// EnumConstantDecl.
230   static DeclarationFragments
231   getFragmentsForEnumConstant(const EnumConstantDecl *);
232 
233   /// Build DeclarationFragments for an enum declaration EnumDecl.
234   static DeclarationFragments getFragmentsForEnum(const EnumDecl *);
235 
236   /// Build DeclarationFragments for a field declaration FieldDecl.
237   static DeclarationFragments getFragmentsForField(const FieldDecl *);
238 
239   /// Build DeclarationFragments for a struct record declaration RecordDecl.
240   static DeclarationFragments getFragmentsForStruct(const RecordDecl *);
241 
242   /// Build DeclarationFragments for an Objective-C category declaration
243   /// ObjCCategoryDecl.
244   static DeclarationFragments
245   getFragmentsForObjCCategory(const ObjCCategoryDecl *);
246 
247   /// Build DeclarationFragments for an Objective-C interface declaration
248   /// ObjCInterfaceDecl.
249   static DeclarationFragments
250   getFragmentsForObjCInterface(const ObjCInterfaceDecl *);
251 
252   /// Build DeclarationFragments for an Objective-C method declaration
253   /// ObjCMethodDecl.
254   static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *);
255 
256   /// Build DeclarationFragments for an Objective-C property declaration
257   /// ObjCPropertyDecl.
258   static DeclarationFragments
259   getFragmentsForObjCProperty(const ObjCPropertyDecl *);
260 
261   /// Build DeclarationFragments for an Objective-C protocol declaration
262   /// ObjCProtocolDecl.
263   static DeclarationFragments
264   getFragmentsForObjCProtocol(const ObjCProtocolDecl *);
265 
266   /// Build DeclarationFragments for a macro.
267   ///
268   /// \param Name name of the macro.
269   /// \param MD the associated MacroDirective.
270   static DeclarationFragments getFragmentsForMacro(StringRef Name,
271                                                    const MacroDirective *MD);
272 
273   /// Build DeclarationFragments for a typedef \p TypedefNameDecl.
274   static DeclarationFragments
275   getFragmentsForTypedef(const TypedefNameDecl *Decl);
276 
277   /// Build sub-heading fragments for a NamedDecl.
278   static DeclarationFragments getSubHeading(const NamedDecl *);
279 
280   /// Build sub-heading fragments for an Objective-C method.
281   static DeclarationFragments getSubHeading(const ObjCMethodDecl *);
282 
283   /// Build a sub-heading for macro \p Name.
284   static DeclarationFragments getSubHeadingForMacro(StringRef Name);
285 
286   /// Build FunctionSignature for a function-like declaration \c FunctionT like
287   /// FunctionDecl or ObjCMethodDecl.
288   ///
289   /// The logic and implementation of building a signature for a FunctionDecl
290   /// and an ObjCMethodDecl are exactly the same, but they do not share a common
291   /// base. This template helps reuse the code.
292   template <typename FunctionT>
293   static FunctionSignature getFunctionSignature(const FunctionT *);
294 
295 private:
296   DeclarationFragmentsBuilder() = delete;
297 
298   /// Build DeclarationFragments for a QualType.
299   static DeclarationFragments getFragmentsForType(const QualType, ASTContext &,
300                                                   DeclarationFragments &);
301 
302   /// Build DeclarationFragments for a Type.
303   static DeclarationFragments getFragmentsForType(const Type *, ASTContext &,
304                                                   DeclarationFragments &);
305 
306   /// Build DeclarationFragments for a NestedNameSpecifier.
307   static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *,
308                                                  ASTContext &,
309                                                  DeclarationFragments &);
310 
311   /// Build DeclarationFragments for Qualifiers.
312   static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals);
313 
314   /// Build DeclarationFragments for a parameter variable declaration
315   /// ParmVarDecl.
316   static DeclarationFragments getFragmentsForParam(const ParmVarDecl *);
317 };
318 
319 } // namespace extractapi
320 } // namespace clang
321 
322 #endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H
323