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 <iterator>
31 #include <utility>
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
FragmentFragment99 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
getFragments()108 const std::vector<Fragment> &getFragments() const { return Fragments; }
109
begin()110 FragmentIterator begin() { return Fragments.begin(); }
111
end()112 FragmentIterator end() { return Fragments.end(); }
113
cbegin()114 ConstFragmentIterator cbegin() const { return Fragments.cbegin(); }
115
cend()116 ConstFragmentIterator cend() const { return Fragments.cend(); }
117
118 /// Prepend another DeclarationFragments to the beginning.
119 ///
120 /// \returns a reference to the DeclarationFragments object itself after
121 /// appending to chain up consecutive operations.
prepend(DeclarationFragments Other)122 DeclarationFragments &prepend(DeclarationFragments Other) {
123 return insert(begin(), std::move(Other));
124 }
125
126 /// Append another DeclarationFragments to the end.
127 ///
128 /// \returns a reference to the DeclarationFragments object itself after
129 /// appending to chain up consecutive operations.
append(DeclarationFragments Other)130 DeclarationFragments &append(DeclarationFragments Other) {
131 return insert(end(), std::move(Other));
132 }
133
134 /// Append a new Fragment to the end of the Fragments.
135 ///
136 /// \returns a reference to the DeclarationFragments object itself after
137 /// appending to chain up consecutive operations.
138 DeclarationFragments &append(StringRef Spelling, FragmentKind Kind,
139 StringRef PreciseIdentifier = "",
140 const Decl *Declaration = nullptr) {
141 if (Kind == FragmentKind::Text && !Fragments.empty() &&
142 Fragments.back().Kind == FragmentKind::Text) {
143 // If appending a text fragment, and the last fragment is also text,
144 // merge into the last fragment.
145 Fragments.back().Spelling.append(Spelling.data(), Spelling.size());
146 } else {
147 Fragments.emplace_back(Spelling, Kind, PreciseIdentifier, Declaration);
148 }
149 return *this;
150 }
151
152 /// Inserts another DeclarationFragments at \p It.
153 ///
154 /// \returns a reference to the DeclarationFragments object itself after
155 /// appending to chain up consecutive operations.
insert(FragmentIterator It,DeclarationFragments Other)156 DeclarationFragments &insert(FragmentIterator It,
157 DeclarationFragments Other) {
158 if (Other.Fragments.empty())
159 return *this;
160
161 if (Fragments.empty()) {
162 Fragments = std::move(Other.Fragments);
163 return *this;
164 }
165
166 const auto &OtherFrags = Other.Fragments;
167 auto ToInsertBegin = std::make_move_iterator(Other.begin());
168 auto ToInsertEnd = std::make_move_iterator(Other.end());
169
170 // If we aren't inserting at the end let's make sure that we merge their
171 // last fragment with It if both are text fragments.
172 if (It != end() && It->Kind == FragmentKind::Text &&
173 OtherFrags.back().Kind == FragmentKind::Text) {
174 auto &TheirBackSpelling = OtherFrags.back().Spelling;
175 It->Spelling.reserve(It->Spelling.size() + TheirBackSpelling.size());
176 It->Spelling.insert(It->Spelling.begin(), TheirBackSpelling.begin(),
177 TheirBackSpelling.end());
178 --ToInsertEnd;
179 }
180
181 // If we aren't inserting at the beginning we want to merge their first
182 // fragment with the fragment before It if both are text fragments.
183 if (It != begin() && std::prev(It)->Kind == FragmentKind::Text &&
184 OtherFrags.front().Kind == FragmentKind::Text) {
185 auto PrevIt = std::prev(It);
186 auto &TheirFrontSpelling = OtherFrags.front().Spelling;
187 PrevIt->Spelling.reserve(PrevIt->Spelling.size() +
188 TheirFrontSpelling.size());
189 PrevIt->Spelling.append(TheirFrontSpelling);
190 ++ToInsertBegin;
191 }
192
193 Fragments.insert(It, ToInsertBegin, ToInsertEnd);
194 return *this;
195 }
196
pop_back()197 DeclarationFragments &pop_back() {
198 Fragments.pop_back();
199 return *this;
200 }
201
replace(std::string NewSpelling,unsigned Position)202 DeclarationFragments &replace(std::string NewSpelling, unsigned Position) {
203 Fragments.at(Position).Spelling = NewSpelling;
204 return *this;
205 }
206
207 /// Append a text Fragment of a space character.
208 ///
209 /// \returns a reference to the DeclarationFragments object itself after
210 /// appending to chain up consecutive operations.
211 DeclarationFragments &appendSpace();
212
213 /// Append a text Fragment of a semicolon character.
214 ///
215 /// \returns a reference to the DeclarationFragments object itself after
216 /// appending to chain up consecutive operations.
217 DeclarationFragments &appendSemicolon();
218
219 /// Removes a trailing semicolon character if present.
220 ///
221 /// \returns a reference to the DeclarationFragments object itself after
222 /// removing to chain up consecutive operations.
223 DeclarationFragments &removeTrailingSemicolon();
224
225 /// Get the string description of a FragmentKind \p Kind.
226 static StringRef getFragmentKindString(FragmentKind Kind);
227
228 /// Get the corresponding FragmentKind from string \p S.
229 static FragmentKind parseFragmentKindFromString(StringRef S);
230
231 static DeclarationFragments
232 getExceptionSpecificationString(ExceptionSpecificationType ExceptionSpec);
233
234 static DeclarationFragments getStructureTypeFragment(const RecordDecl *Decl);
235
236 private:
237 DeclarationFragments &appendUnduplicatedTextCharacter(char Character);
238 std::vector<Fragment> Fragments;
239 };
240
241 class AccessControl {
242 public:
AccessControl(std::string Access)243 AccessControl(std::string Access) : Access(Access) {}
AccessControl()244 AccessControl() : Access("public") {}
245
getAccess()246 const std::string &getAccess() const { return Access; }
247
empty()248 bool empty() const { return Access.empty(); }
249
250 private:
251 std::string Access;
252 };
253
254 /// Store function signature information with DeclarationFragments of the
255 /// return type and parameters.
256 class FunctionSignature {
257 public:
258 FunctionSignature() = default;
259
260 /// Parameter holds the name and DeclarationFragments of a single parameter.
261 struct Parameter {
262 std::string Name;
263 DeclarationFragments Fragments;
264
ParameterParameter265 Parameter(StringRef Name, DeclarationFragments Fragments)
266 : Name(Name), Fragments(Fragments) {}
267 };
268
getParameters()269 const std::vector<Parameter> &getParameters() const { return Parameters; }
getReturnType()270 const DeclarationFragments &getReturnType() const { return ReturnType; }
271
addParameter(StringRef Name,DeclarationFragments Fragments)272 FunctionSignature &addParameter(StringRef Name,
273 DeclarationFragments Fragments) {
274 Parameters.emplace_back(Name, Fragments);
275 return *this;
276 }
277
setReturnType(DeclarationFragments RT)278 void setReturnType(DeclarationFragments RT) { ReturnType = RT; }
279
280 /// Determine if the FunctionSignature is empty.
281 ///
282 /// \returns true if the return type DeclarationFragments is empty and there
283 /// is no parameter, otherwise false.
empty()284 bool empty() const {
285 return Parameters.empty() && ReturnType.getFragments().empty();
286 }
287
288 private:
289 std::vector<Parameter> Parameters;
290 DeclarationFragments ReturnType;
291 };
292
293 /// A factory class to build DeclarationFragments for different kinds of Decl.
294 class DeclarationFragmentsBuilder {
295 public:
296 /// Build FunctionSignature for a function-like declaration \c FunctionT like
297 /// FunctionDecl, ObjCMethodDecl, or CXXMethodDecl.
298 ///
299 /// The logic and implementation of building a signature for a FunctionDecl,
300 /// CXXMethodDecl, and ObjCMethodDecl are exactly the same, but they do not
301 /// share a common base. This template helps reuse the code.
302 template <typename FunctionT>
303 static FunctionSignature getFunctionSignature(const FunctionT *Function);
304
getAccessControl(const Decl * Decl)305 static AccessControl getAccessControl(const Decl *Decl) {
306 switch (Decl->getAccess()) {
307 case AS_public:
308 case AS_none:
309 return AccessControl("public");
310 case AS_private:
311 return AccessControl("private");
312 case AS_protected:
313 return AccessControl("protected");
314 }
315 llvm_unreachable("Unhandled access control");
316 }
317
318 static DeclarationFragments
319 getFragmentsForNamespace(const NamespaceDecl *Decl);
320
321 /// Build DeclarationFragments for a variable declaration VarDecl.
322 static DeclarationFragments getFragmentsForVar(const VarDecl *);
323
324 static DeclarationFragments getFragmentsForVarTemplate(const VarDecl *);
325
326 /// Build DeclarationFragments for a function declaration FunctionDecl.
327 static DeclarationFragments getFragmentsForFunction(const FunctionDecl *);
328
329 /// Build DeclarationFragments for an enum constant declaration
330 /// EnumConstantDecl.
331 static DeclarationFragments
332 getFragmentsForEnumConstant(const EnumConstantDecl *);
333
334 /// Build DeclarationFragments for an enum declaration EnumDecl.
335 static DeclarationFragments getFragmentsForEnum(const EnumDecl *);
336
337 /// Build DeclarationFragments for a field declaration FieldDecl.
338 static DeclarationFragments getFragmentsForField(const FieldDecl *);
339
340 /// Build DeclarationFragments for a struct/union record declaration
341 /// RecordDecl.
342 static DeclarationFragments getFragmentsForRecordDecl(const RecordDecl *);
343
344 static DeclarationFragments getFragmentsForCXXClass(const CXXRecordDecl *);
345
346 static DeclarationFragments
347 getFragmentsForSpecialCXXMethod(const CXXMethodDecl *);
348
349 static DeclarationFragments getFragmentsForCXXMethod(const CXXMethodDecl *);
350
351 static DeclarationFragments
352 getFragmentsForConversionFunction(const CXXConversionDecl *);
353
354 static DeclarationFragments
355 getFragmentsForOverloadedOperator(const CXXMethodDecl *);
356
357 static DeclarationFragments
358 getFragmentsForTemplateParameters(ArrayRef<NamedDecl *>);
359
360 static DeclarationFragments getFragmentsForTemplateArguments(
361 const ArrayRef<TemplateArgument>, ASTContext &,
362 const std::optional<ArrayRef<TemplateArgumentLoc>>);
363
364 static DeclarationFragments getFragmentsForConcept(const ConceptDecl *);
365
366 static DeclarationFragments
367 getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl *);
368
369 static DeclarationFragments getFragmentsForClassTemplateSpecialization(
370 const ClassTemplateSpecializationDecl *);
371
372 static DeclarationFragments getFragmentsForClassTemplatePartialSpecialization(
373 const ClassTemplatePartialSpecializationDecl *);
374
375 static DeclarationFragments getFragmentsForVarTemplateSpecialization(
376 const VarTemplateSpecializationDecl *);
377
378 static DeclarationFragments getFragmentsForVarTemplatePartialSpecialization(
379 const VarTemplatePartialSpecializationDecl *);
380
381 static DeclarationFragments
382 getFragmentsForFunctionTemplate(const FunctionTemplateDecl *Decl);
383
384 static DeclarationFragments
385 getFragmentsForFunctionTemplateSpecialization(const FunctionDecl *Decl);
386
387 /// Build DeclarationFragments for an Objective-C category declaration
388 /// ObjCCategoryDecl.
389 static DeclarationFragments
390 getFragmentsForObjCCategory(const ObjCCategoryDecl *);
391
392 /// Build DeclarationFragments for an Objective-C interface declaration
393 /// ObjCInterfaceDecl.
394 static DeclarationFragments
395 getFragmentsForObjCInterface(const ObjCInterfaceDecl *);
396
397 /// Build DeclarationFragments for an Objective-C method declaration
398 /// ObjCMethodDecl.
399 static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *);
400
401 /// Build DeclarationFragments for an Objective-C property declaration
402 /// ObjCPropertyDecl.
403 static DeclarationFragments
404 getFragmentsForObjCProperty(const ObjCPropertyDecl *);
405
406 /// Build DeclarationFragments for an Objective-C protocol declaration
407 /// ObjCProtocolDecl.
408 static DeclarationFragments
409 getFragmentsForObjCProtocol(const ObjCProtocolDecl *);
410
411 /// Build DeclarationFragments for a macro.
412 ///
413 /// \param Name name of the macro.
414 /// \param MD the associated MacroDirective.
415 static DeclarationFragments getFragmentsForMacro(StringRef Name,
416 const MacroDirective *MD);
417
418 /// Build DeclarationFragments for a typedef \p TypedefNameDecl.
419 static DeclarationFragments
420 getFragmentsForTypedef(const TypedefNameDecl *Decl);
421
422 /// Build sub-heading fragments for a NamedDecl.
423 static DeclarationFragments getSubHeading(const NamedDecl *);
424
425 /// Build sub-heading fragments for an Objective-C method.
426 static DeclarationFragments getSubHeading(const ObjCMethodDecl *);
427
428 /// Build a sub-heading for macro \p Name.
429 static DeclarationFragments getSubHeadingForMacro(StringRef Name);
430
431 private:
432 DeclarationFragmentsBuilder() = delete;
433
434 /// Build DeclarationFragments for a QualType.
435 static DeclarationFragments getFragmentsForType(const QualType, ASTContext &,
436 DeclarationFragments &);
437
438 /// Build DeclarationFragments for a Type.
439 static DeclarationFragments getFragmentsForType(const Type *, ASTContext &,
440 DeclarationFragments &);
441
442 /// Build DeclarationFragments for a NestedNameSpecifier.
443 static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *,
444 ASTContext &,
445 DeclarationFragments &);
446
447 /// Build DeclarationFragments for Qualifiers.
448 static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals);
449
450 /// Build DeclarationFragments for a parameter variable declaration
451 /// ParmVarDecl.
452 static DeclarationFragments getFragmentsForParam(const ParmVarDecl *);
453
454 static DeclarationFragments
455 getFragmentsForBlock(const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
456 FunctionProtoTypeLoc &BlockProto,
457 DeclarationFragments &After);
458 };
459
460 template <typename FunctionT>
461 FunctionSignature
getFunctionSignature(const FunctionT * Function)462 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
463 FunctionSignature Signature;
464
465 DeclarationFragments ReturnType, After;
466 ReturnType = getFragmentsForType(Function->getReturnType(),
467 Function->getASTContext(), After);
468 if (isa<FunctionDecl>(Function) &&
469 dyn_cast<FunctionDecl>(Function)->getDescribedFunctionTemplate() &&
470 StringRef(ReturnType.begin()->Spelling).starts_with("type-parameter")) {
471 std::string ProperArgName = Function->getReturnType().getAsString();
472 ReturnType.begin()->Spelling.swap(ProperArgName);
473 }
474 ReturnType.append(std::move(After));
475 Signature.setReturnType(ReturnType);
476
477 for (const auto *Param : Function->parameters())
478 Signature.addParameter(Param->getName(), getFragmentsForParam(Param));
479
480 return Signature;
481 }
482
483 } // namespace extractapi
484 } // namespace clang
485
486 #endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H
487