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     Fragment(StringRef Spelling, FragmentKind Kind, StringRef PreciseIdentifier)
91         : Spelling(Spelling), Kind(Kind), PreciseIdentifier(PreciseIdentifier) {
92     }
93   };
94 
95   const std::vector<Fragment> &getFragments() const { return Fragments; }
96 
97   /// Append a new Fragment to the end of the Fragments.
98   ///
99   /// \returns a reference to the DeclarationFragments object itself after
100   /// appending to chain up consecutive appends.
101   DeclarationFragments &append(StringRef Spelling, FragmentKind Kind,
102                                StringRef PreciseIdentifier = "") {
103     if (Kind == FragmentKind::Text && !Fragments.empty() &&
104         Fragments.back().Kind == FragmentKind::Text) {
105       // If appending a text fragment, and the last fragment is also text,
106       // merge into the last fragment.
107       Fragments.back().Spelling.append(Spelling.data(), Spelling.size());
108     } else {
109       Fragments.emplace_back(Spelling, Kind, PreciseIdentifier);
110     }
111     return *this;
112   }
113 
114   /// Append another DeclarationFragments to the end.
115   ///
116   /// Note: \p Other is moved from and cannot be used after a call to this
117   /// method.
118   ///
119   /// \returns a reference to the DeclarationFragments object itself after
120   /// appending to chain up consecutive appends.
121   DeclarationFragments &append(DeclarationFragments &&Other) {
122     Fragments.insert(Fragments.end(),
123                      std::make_move_iterator(Other.Fragments.begin()),
124                      std::make_move_iterator(Other.Fragments.end()));
125     Other.Fragments.clear();
126     return *this;
127   }
128 
129   /// Append a text Fragment of a space character.
130   ///
131   /// \returns a reference to the DeclarationFragments object itself after
132   /// appending to chain up consecutive appends.
133   DeclarationFragments &appendSpace();
134 
135   /// Get the string description of a FragmentKind \p Kind.
136   static StringRef getFragmentKindString(FragmentKind Kind);
137 
138   /// Get the corresponding FragmentKind from string \p S.
139   static FragmentKind parseFragmentKindFromString(StringRef S);
140 
141 private:
142   std::vector<Fragment> Fragments;
143 };
144 
145 /// Store function signature information with DeclarationFragments of the
146 /// return type and parameters.
147 class FunctionSignature {
148 public:
149   FunctionSignature() = default;
150 
151   /// Parameter holds the name and DeclarationFragments of a single parameter.
152   struct Parameter {
153     std::string Name;
154     DeclarationFragments Fragments;
155 
156     Parameter(StringRef Name, DeclarationFragments Fragments)
157         : Name(Name), Fragments(Fragments) {}
158   };
159 
160   const std::vector<Parameter> &getParameters() const { return Parameters; }
161   const DeclarationFragments &getReturnType() const { return ReturnType; }
162 
163   FunctionSignature &addParameter(StringRef Name,
164                                   DeclarationFragments Fragments) {
165     Parameters.emplace_back(Name, Fragments);
166     return *this;
167   }
168 
169   void setReturnType(DeclarationFragments RT) { ReturnType = RT; }
170 
171   /// Determine if the FunctionSignature is empty.
172   ///
173   /// \returns true if the return type DeclarationFragments is empty and there
174   /// is no parameter, otherwise false.
175   bool empty() const {
176     return Parameters.empty() && ReturnType.getFragments().empty();
177   }
178 
179 private:
180   std::vector<Parameter> Parameters;
181   DeclarationFragments ReturnType;
182 };
183 
184 /// A factory class to build DeclarationFragments for different kinds of Decl.
185 class DeclarationFragmentsBuilder {
186 public:
187   /// Build DeclarationFragments for a variable declaration VarDecl.
188   static DeclarationFragments getFragmentsForVar(const VarDecl *);
189 
190   /// Build DeclarationFragments for a function declaration FunctionDecl.
191   static DeclarationFragments getFragmentsForFunction(const FunctionDecl *);
192 
193   /// Build DeclarationFragments for an enum constant declaration
194   /// EnumConstantDecl.
195   static DeclarationFragments
196   getFragmentsForEnumConstant(const EnumConstantDecl *);
197 
198   /// Build DeclarationFragments for an enum declaration EnumDecl.
199   static DeclarationFragments getFragmentsForEnum(const EnumDecl *);
200 
201   /// Build DeclarationFragments for a field declaration FieldDecl.
202   static DeclarationFragments getFragmentsForField(const FieldDecl *);
203 
204   /// Build DeclarationFragments for a struct record declaration RecordDecl.
205   static DeclarationFragments getFragmentsForStruct(const RecordDecl *);
206 
207   /// Build DeclarationFragments for an Objective-C category declaration
208   /// ObjCCategoryDecl.
209   static DeclarationFragments
210   getFragmentsForObjCCategory(const ObjCCategoryDecl *);
211 
212   /// Build DeclarationFragments for an Objective-C interface declaration
213   /// ObjCInterfaceDecl.
214   static DeclarationFragments
215   getFragmentsForObjCInterface(const ObjCInterfaceDecl *);
216 
217   /// Build DeclarationFragments for an Objective-C method declaration
218   /// ObjCMethodDecl.
219   static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *);
220 
221   /// Build DeclarationFragments for an Objective-C property declaration
222   /// ObjCPropertyDecl.
223   static DeclarationFragments
224   getFragmentsForObjCProperty(const ObjCPropertyDecl *);
225 
226   /// Build DeclarationFragments for an Objective-C protocol declaration
227   /// ObjCProtocolDecl.
228   static DeclarationFragments
229   getFragmentsForObjCProtocol(const ObjCProtocolDecl *);
230 
231   /// Build DeclarationFragments for a macro.
232   ///
233   /// \param Name name of the macro.
234   /// \param MD the associated MacroDirective.
235   static DeclarationFragments getFragmentsForMacro(StringRef Name,
236                                                    const MacroDirective *MD);
237 
238   /// Build DeclarationFragments for a typedef \p TypedefNameDecl.
239   static DeclarationFragments
240   getFragmentsForTypedef(const TypedefNameDecl *Decl);
241 
242   /// Build sub-heading fragments for a NamedDecl.
243   static DeclarationFragments getSubHeading(const NamedDecl *);
244 
245   /// Build sub-heading fragments for an Objective-C method.
246   static DeclarationFragments getSubHeading(const ObjCMethodDecl *);
247 
248   /// Build a sub-heading for macro \p Name.
249   static DeclarationFragments getSubHeadingForMacro(StringRef Name);
250 
251   /// Build FunctionSignature for a function-like declaration \c FunctionT like
252   /// FunctionDecl or ObjCMethodDecl.
253   ///
254   /// The logic and implementation of building a signature for a FunctionDecl
255   /// and an ObjCMethodDecl are exactly the same, but they do not share a common
256   /// base. This template helps reuse the code.
257   template <typename FunctionT>
258   static FunctionSignature getFunctionSignature(const FunctionT *);
259 
260 private:
261   DeclarationFragmentsBuilder() = delete;
262 
263   /// Build DeclarationFragments for a QualType.
264   static DeclarationFragments getFragmentsForType(const QualType, ASTContext &,
265                                                   DeclarationFragments &);
266 
267   /// Build DeclarationFragments for a Type.
268   static DeclarationFragments getFragmentsForType(const Type *, ASTContext &,
269                                                   DeclarationFragments &);
270 
271   /// Build DeclarationFragments for a NestedNameSpecifier.
272   static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *,
273                                                  ASTContext &,
274                                                  DeclarationFragments &);
275 
276   /// Build DeclarationFragments for Qualifiers.
277   static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals);
278 
279   /// Build DeclarationFragments for a parameter variable declaration
280   /// ParmVarDecl.
281   static DeclarationFragments getFragmentsForParam(const ParmVarDecl *);
282 };
283 
284 } // namespace extractapi
285 } // namespace clang
286 
287 #endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H
288