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
34namespace clang {
35namespace 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
48class DeclarationFragments {
49public:
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(position: It,
124 x: Fragment(Spelling, Kind, PreciseIdentifier, Declaration));
125 return *this;
126 }
127
128 DeclarationFragments &insert(FragmentIterator It,
129 DeclarationFragments &&Other) {
130 Fragments.insert(position: It, first: std::make_move_iterator(i: Other.Fragments.begin()),
131 last: std::make_move_iterator(i: 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(s: Spelling.data(), n: Spelling.size());
148 } else {
149 Fragments.emplace_back(args&: Spelling, args&: Kind, args&: PreciseIdentifier, args&: 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(position: Fragments.end(),
163 first: std::make_move_iterator(i: Other.Fragments.begin()),
164 last: std::make_move_iterator(i: 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(n: 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
196private:
197 std::vector<Fragment> Fragments;
198};
199
200class AccessControl {
201public:
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
208private:
209 std::string Access;
210};
211
212/// Store function signature information with DeclarationFragments of the
213/// return type and parameters.
214class FunctionSignature {
215public:
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(args&: Name, args&: 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
246private:
247 std::vector<Parameter> Parameters;
248 DeclarationFragments ReturnType;
249};
250
251/// A factory class to build DeclarationFragments for different kinds of Decl.
252class DeclarationFragmentsBuilder {
253public:
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/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
393private:
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
422template <typename FunctionT>
423FunctionSignature
424DeclarationFragmentsBuilder::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 StringRef(ReturnType.begin()->Spelling).starts_with(Prefix: "type-parameter")) {
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(s&: ProperArgName);
440 }
441 ReturnType.append(Other: std::move(After));
442 Signature.setReturnType(ReturnType);
443
444 for (const auto *Param : Function->parameters())
445 Signature.addParameter(Name: Param->getName(), Fragments: getFragmentsForParam(Param));
446
447 return Signature;
448}
449
450} // namespace extractapi
451} // namespace clang
452
453#endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H
454

source code of clang/include/clang/ExtractAPI/DeclarationFragments.h