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