/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/ExtractAPI/DeclarationFragments.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- ExtractAPI/DeclarationFragments.cpp ----------------------*- 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 implements Declaration Fragments related classes. |
11 | | /// |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "clang/ExtractAPI/DeclarationFragments.h" |
15 | | #include "clang/AST/Decl.h" |
16 | | #include "clang/AST/DeclCXX.h" |
17 | | #include "clang/AST/QualTypeNames.h" |
18 | | #include "clang/Basic/OperatorKinds.h" |
19 | | #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" |
20 | | #include "clang/Index/USRGeneration.h" |
21 | | #include "llvm/ADT/StringSwitch.h" |
22 | | #include <typeinfo> |
23 | | |
24 | | using namespace clang::extractapi; |
25 | | using namespace llvm; |
26 | | |
27 | 517 | DeclarationFragments &DeclarationFragments::appendSpace() { |
28 | 517 | if (!Fragments.empty()) { |
29 | 517 | Fragment &Last = Fragments.back(); |
30 | 517 | if (Last.Kind == FragmentKind::Text) { |
31 | | // Merge the extra space into the last fragment if the last fragment is |
32 | | // also text. |
33 | 90 | if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces. |
34 | 74 | Last.Spelling.push_back(' '); |
35 | 74 | } |
36 | 427 | } else { |
37 | 427 | append(" ", FragmentKind::Text); |
38 | 427 | } |
39 | 517 | } |
40 | | |
41 | 517 | return *this; |
42 | 517 | } |
43 | | |
44 | | StringRef DeclarationFragments::getFragmentKindString( |
45 | 1.71k | DeclarationFragments::FragmentKind Kind) { |
46 | 1.71k | switch (Kind) { |
47 | 0 | case DeclarationFragments::FragmentKind::None: |
48 | 0 | return "none"; |
49 | 189 | case DeclarationFragments::FragmentKind::Keyword: |
50 | 189 | return "keyword"; |
51 | 0 | case DeclarationFragments::FragmentKind::Attribute: |
52 | 0 | return "attribute"; |
53 | 0 | case DeclarationFragments::FragmentKind::NumberLiteral: |
54 | 0 | return "number"; |
55 | 0 | case DeclarationFragments::FragmentKind::StringLiteral: |
56 | 0 | return "string"; |
57 | 600 | case DeclarationFragments::FragmentKind::Identifier: |
58 | 600 | return "identifier"; |
59 | 230 | case DeclarationFragments::FragmentKind::TypeIdentifier: |
60 | 230 | return "typeIdentifier"; |
61 | 18 | case DeclarationFragments::FragmentKind::GenericParameter: |
62 | 18 | return "genericParameter"; |
63 | 0 | case DeclarationFragments::FragmentKind::ExternalParam: |
64 | 0 | return "externalParam"; |
65 | 63 | case DeclarationFragments::FragmentKind::InternalParam: |
66 | 63 | return "internalParam"; |
67 | 612 | case DeclarationFragments::FragmentKind::Text: |
68 | 612 | return "text"; |
69 | 1.71k | } |
70 | | |
71 | 0 | llvm_unreachable("Unhandled FragmentKind"); |
72 | 0 | } |
73 | | |
74 | | DeclarationFragments::FragmentKind |
75 | 0 | DeclarationFragments::parseFragmentKindFromString(StringRef S) { |
76 | 0 | return llvm::StringSwitch<FragmentKind>(S) |
77 | 0 | .Case("keyword", DeclarationFragments::FragmentKind::Keyword) |
78 | 0 | .Case("attribute", DeclarationFragments::FragmentKind::Attribute) |
79 | 0 | .Case("number", DeclarationFragments::FragmentKind::NumberLiteral) |
80 | 0 | .Case("string", DeclarationFragments::FragmentKind::StringLiteral) |
81 | 0 | .Case("identifier", DeclarationFragments::FragmentKind::Identifier) |
82 | 0 | .Case("typeIdentifier", |
83 | 0 | DeclarationFragments::FragmentKind::TypeIdentifier) |
84 | 0 | .Case("genericParameter", |
85 | 0 | DeclarationFragments::FragmentKind::GenericParameter) |
86 | 0 | .Case("internalParam", DeclarationFragments::FragmentKind::InternalParam) |
87 | 0 | .Case("externalParam", DeclarationFragments::FragmentKind::ExternalParam) |
88 | 0 | .Case("text", DeclarationFragments::FragmentKind::Text) |
89 | 0 | .Default(DeclarationFragments::FragmentKind::None); |
90 | 0 | } |
91 | | |
92 | | DeclarationFragments DeclarationFragments::getExceptionSpecificationString( |
93 | 40 | ExceptionSpecificationType ExceptionSpec) { |
94 | 40 | DeclarationFragments Fragments; |
95 | 40 | switch (ExceptionSpec) { |
96 | 36 | case ExceptionSpecificationType::EST_None: |
97 | 36 | return Fragments; |
98 | 0 | case ExceptionSpecificationType::EST_DynamicNone: |
99 | 0 | return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) |
100 | 0 | .append("throw", DeclarationFragments::FragmentKind::Keyword) |
101 | 0 | .append("(", DeclarationFragments::FragmentKind::Text) |
102 | 0 | .append(")", DeclarationFragments::FragmentKind::Text); |
103 | 0 | case ExceptionSpecificationType::EST_Dynamic: |
104 | | // FIXME: throw(int), get types of inner expression |
105 | 0 | return Fragments; |
106 | 2 | case ExceptionSpecificationType::EST_BasicNoexcept: |
107 | 2 | return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) |
108 | 2 | .append("noexcept", DeclarationFragments::FragmentKind::Keyword); |
109 | 0 | case ExceptionSpecificationType::EST_DependentNoexcept: |
110 | | // FIXME: throw(conditional-expression), get expression |
111 | 0 | break; |
112 | 1 | case ExceptionSpecificationType::EST_NoexceptFalse: |
113 | 1 | return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) |
114 | 1 | .append("noexcept", DeclarationFragments::FragmentKind::Keyword) |
115 | 1 | .append("(", DeclarationFragments::FragmentKind::Text) |
116 | 1 | .append("false", DeclarationFragments::FragmentKind::Keyword) |
117 | 1 | .append(")", DeclarationFragments::FragmentKind::Text); |
118 | 1 | case ExceptionSpecificationType::EST_NoexceptTrue: |
119 | 1 | return Fragments.append(" ", DeclarationFragments::FragmentKind::Text) |
120 | 1 | .append("noexcept", DeclarationFragments::FragmentKind::Keyword) |
121 | 1 | .append("(", DeclarationFragments::FragmentKind::Text) |
122 | 1 | .append("true", DeclarationFragments::FragmentKind::Keyword) |
123 | 1 | .append(")", DeclarationFragments::FragmentKind::Text); |
124 | 0 | default: |
125 | 0 | return Fragments; |
126 | 40 | } |
127 | | |
128 | 0 | llvm_unreachable("Unhandled exception specification"); |
129 | 0 | } |
130 | | |
131 | | DeclarationFragments |
132 | 21 | DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) { |
133 | 21 | DeclarationFragments Fragments; |
134 | 21 | if (Record->isStruct()) |
135 | 0 | Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); |
136 | 21 | else if (Record->isUnion()) |
137 | 0 | Fragments.append("union", DeclarationFragments::FragmentKind::Keyword); |
138 | 21 | else |
139 | 21 | Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); |
140 | | |
141 | 21 | return Fragments; |
142 | 21 | } |
143 | | |
144 | | // NNS stores C++ nested name specifiers, which are prefixes to qualified names. |
145 | | // Build declaration fragments for NNS recursively so that we have the USR for |
146 | | // every part in a qualified name, and also leaves the actual underlying type |
147 | | // cleaner for its own fragment. |
148 | | DeclarationFragments |
149 | | DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS, |
150 | | ASTContext &Context, |
151 | 0 | DeclarationFragments &After) { |
152 | 0 | DeclarationFragments Fragments; |
153 | 0 | if (NNS->getPrefix()) |
154 | 0 | Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After)); |
155 | |
|
156 | 0 | switch (NNS->getKind()) { |
157 | 0 | case NestedNameSpecifier::Identifier: |
158 | 0 | Fragments.append(NNS->getAsIdentifier()->getName(), |
159 | 0 | DeclarationFragments::FragmentKind::Identifier); |
160 | 0 | break; |
161 | | |
162 | 0 | case NestedNameSpecifier::Namespace: { |
163 | 0 | const NamespaceDecl *NS = NNS->getAsNamespace(); |
164 | 0 | if (NS->isAnonymousNamespace()) |
165 | 0 | return Fragments; |
166 | 0 | SmallString<128> USR; |
167 | 0 | index::generateUSRForDecl(NS, USR); |
168 | 0 | Fragments.append(NS->getName(), |
169 | 0 | DeclarationFragments::FragmentKind::Identifier, USR, NS); |
170 | 0 | break; |
171 | 0 | } |
172 | | |
173 | 0 | case NestedNameSpecifier::NamespaceAlias: { |
174 | 0 | const NamespaceAliasDecl *Alias = NNS->getAsNamespaceAlias(); |
175 | 0 | SmallString<128> USR; |
176 | 0 | index::generateUSRForDecl(Alias, USR); |
177 | 0 | Fragments.append(Alias->getName(), |
178 | 0 | DeclarationFragments::FragmentKind::Identifier, USR, |
179 | 0 | Alias); |
180 | 0 | break; |
181 | 0 | } |
182 | | |
183 | 0 | case NestedNameSpecifier::Global: |
184 | | // The global specifier `::` at the beginning. No stored value. |
185 | 0 | break; |
186 | | |
187 | 0 | case NestedNameSpecifier::Super: |
188 | | // Microsoft's `__super` specifier. |
189 | 0 | Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword); |
190 | 0 | break; |
191 | | |
192 | 0 | case NestedNameSpecifier::TypeSpecWithTemplate: |
193 | | // A type prefixed by the `template` keyword. |
194 | 0 | Fragments.append("template", DeclarationFragments::FragmentKind::Keyword); |
195 | 0 | Fragments.appendSpace(); |
196 | | // Fallthrough after adding the keyword to handle the actual type. |
197 | 0 | [[fallthrough]]; |
198 | |
|
199 | 0 | case NestedNameSpecifier::TypeSpec: { |
200 | 0 | const Type *T = NNS->getAsType(); |
201 | | // FIXME: Handle C++ template specialization type |
202 | 0 | Fragments.append(getFragmentsForType(T, Context, After)); |
203 | 0 | break; |
204 | 0 | } |
205 | 0 | } |
206 | | |
207 | | // Add the separator text `::` for this segment. |
208 | 0 | return Fragments.append("::", DeclarationFragments::FragmentKind::Text); |
209 | 0 | } |
210 | | |
211 | | // Recursively build the declaration fragments for an underlying `Type` with |
212 | | // qualifiers removed. |
213 | | DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( |
214 | 461 | const Type *T, ASTContext &Context, DeclarationFragments &After) { |
215 | 461 | assert(T && "invalid type"); |
216 | | |
217 | 461 | DeclarationFragments Fragments; |
218 | | |
219 | | // Declaration fragments of a pointer type is the declaration fragments of |
220 | | // the pointee type followed by a `*`, |
221 | 461 | if (T->isPointerType()) |
222 | 7 | return Fragments |
223 | 7 | .append(getFragmentsForType(T->getPointeeType(), Context, After)) |
224 | 7 | .append(" *", DeclarationFragments::FragmentKind::Text); |
225 | | |
226 | | // For Objective-C `id` and `Class` pointers |
227 | | // we do not spell out the `*`. |
228 | 454 | if (T->isObjCObjectPointerType() && |
229 | 454 | !T->getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()36 ) { |
230 | | |
231 | 26 | Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After)); |
232 | | |
233 | | // id<protocol> is an qualified id type |
234 | | // id<protocol>* is not an qualified id type |
235 | 26 | if (!T->getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) { |
236 | 0 | Fragments.append(" *", DeclarationFragments::FragmentKind::Text); |
237 | 0 | } |
238 | | |
239 | 26 | return Fragments; |
240 | 26 | } |
241 | | |
242 | | // Declaration fragments of a lvalue reference type is the declaration |
243 | | // fragments of the underlying type followed by a `&`. |
244 | 428 | if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T)) |
245 | 0 | return Fragments |
246 | 0 | .append( |
247 | 0 | getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After)) |
248 | 0 | .append(" &", DeclarationFragments::FragmentKind::Text); |
249 | | |
250 | | // Declaration fragments of a rvalue reference type is the declaration |
251 | | // fragments of the underlying type followed by a `&&`. |
252 | 428 | if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T)) |
253 | 0 | return Fragments |
254 | 0 | .append( |
255 | 0 | getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After)) |
256 | 0 | .append(" &&", DeclarationFragments::FragmentKind::Text); |
257 | | |
258 | | // Declaration fragments of an array-typed variable have two parts: |
259 | | // 1. the element type of the array that appears before the variable name; |
260 | | // 2. array brackets `[(0-9)?]` that appear after the variable name. |
261 | 428 | if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) { |
262 | | // Build the "after" part first because the inner element type might also |
263 | | // be an array-type. For example `int matrix[3][4]` which has a type of |
264 | | // "(array 3 of (array 4 of ints))." |
265 | | // Push the array size part first to make sure they are in the right order. |
266 | 0 | After.append("[", DeclarationFragments::FragmentKind::Text); |
267 | |
|
268 | 0 | switch (AT->getSizeModifier()) { |
269 | 0 | case ArrayType::Normal: |
270 | 0 | break; |
271 | 0 | case ArrayType::Static: |
272 | 0 | Fragments.append("static", DeclarationFragments::FragmentKind::Keyword); |
273 | 0 | break; |
274 | 0 | case ArrayType::Star: |
275 | 0 | Fragments.append("*", DeclarationFragments::FragmentKind::Text); |
276 | 0 | break; |
277 | 0 | } |
278 | | |
279 | 0 | if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { |
280 | | // FIXME: right now this would evaluate any expressions/macros written in |
281 | | // the original source to concrete values. For example |
282 | | // `int nums[MAX]` -> `int nums[100]` |
283 | | // `char *str[5 + 1]` -> `char *str[6]` |
284 | 0 | SmallString<128> Size; |
285 | 0 | CAT->getSize().toStringUnsigned(Size); |
286 | 0 | After.append(Size, DeclarationFragments::FragmentKind::NumberLiteral); |
287 | 0 | } |
288 | |
|
289 | 0 | After.append("]", DeclarationFragments::FragmentKind::Text); |
290 | |
|
291 | 0 | return Fragments.append( |
292 | 0 | getFragmentsForType(AT->getElementType(), Context, After)); |
293 | 0 | } |
294 | | |
295 | | // An ElaboratedType is a sugar for types that are referred to using an |
296 | | // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a |
297 | | // qualified name, e.g., `N::M::type`, or both. |
298 | 428 | if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) { |
299 | 46 | ElaboratedTypeKeyword Keyword = ET->getKeyword(); |
300 | 46 | if (Keyword != ETK_None) { |
301 | 35 | Fragments |
302 | 35 | .append(ElaboratedType::getKeywordName(Keyword), |
303 | 35 | DeclarationFragments::FragmentKind::Keyword) |
304 | 35 | .appendSpace(); |
305 | 35 | } |
306 | | |
307 | 46 | if (const NestedNameSpecifier *NNS = ET->getQualifier()) |
308 | 0 | Fragments.append(getFragmentsForNNS(NNS, Context, After)); |
309 | | |
310 | | // After handling the elaborated keyword or qualified name, build |
311 | | // declaration fragments for the desugared underlying type. |
312 | 46 | return Fragments.append(getFragmentsForType(ET->desugar(), Context, After)); |
313 | 46 | } |
314 | | |
315 | | // If the type is a typedefed type, get the underlying TypedefNameDecl for a |
316 | | // direct reference to the typedef instead of the wrapped type. |
317 | | |
318 | | // 'id' type is a typedef for an ObjCObjectPointerType |
319 | | // we treat it as a typedef |
320 | 382 | if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) { |
321 | 13 | const TypedefNameDecl *Decl = TypedefTy->getDecl(); |
322 | 13 | TypedefUnderlyingTypeResolver TypedefResolver(Context); |
323 | 13 | std::string USR = TypedefResolver.getUSRForType(QualType(T, 0)); |
324 | | |
325 | 13 | if (T->isObjCIdType()) { |
326 | 6 | return Fragments.append(Decl->getName(), |
327 | 6 | DeclarationFragments::FragmentKind::Keyword); |
328 | 6 | } |
329 | | |
330 | 7 | return Fragments.append( |
331 | 7 | Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier, |
332 | 7 | USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0))); |
333 | 13 | } |
334 | | |
335 | | // Everything we care about has been handled now, reduce to the canonical |
336 | | // unqualified base type. |
337 | 369 | QualType Base = T->getCanonicalTypeUnqualified(); |
338 | | |
339 | | // If the base type is a TagType (struct/interface/union/class/enum), let's |
340 | | // get the underlying Decl for better names and USRs. |
341 | 369 | if (const TagType *TagTy = dyn_cast<TagType>(Base)) { |
342 | 35 | const TagDecl *Decl = TagTy->getDecl(); |
343 | | // Anonymous decl, skip this fragment. |
344 | 35 | if (Decl->getName().empty()) |
345 | 8 | return Fragments; |
346 | 27 | SmallString<128> TagUSR; |
347 | 27 | clang::index::generateUSRForDecl(Decl, TagUSR); |
348 | 27 | return Fragments.append(Decl->getName(), |
349 | 27 | DeclarationFragments::FragmentKind::TypeIdentifier, |
350 | 27 | TagUSR, Decl); |
351 | 35 | } |
352 | | |
353 | | // If the base type is an ObjCInterfaceType, use the underlying |
354 | | // ObjCInterfaceDecl for the true USR. |
355 | 334 | if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) { |
356 | 0 | const auto *Decl = ObjCIT->getDecl(); |
357 | 0 | SmallString<128> USR; |
358 | 0 | index::generateUSRForDecl(Decl, USR); |
359 | 0 | return Fragments.append(Decl->getName(), |
360 | 0 | DeclarationFragments::FragmentKind::TypeIdentifier, |
361 | 0 | USR, Decl); |
362 | 0 | } |
363 | | |
364 | | // Default fragment builder for other kinds of types (BuiltinType etc.) |
365 | 334 | SmallString<128> USR; |
366 | 334 | clang::index::generateUSRForType(Base, Context, USR); |
367 | 334 | Fragments.append(Base.getAsString(), |
368 | 334 | DeclarationFragments::FragmentKind::TypeIdentifier, USR); |
369 | | |
370 | 334 | return Fragments; |
371 | 334 | } |
372 | | |
373 | | DeclarationFragments |
374 | 461 | DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) { |
375 | 461 | DeclarationFragments Fragments; |
376 | 461 | if (Quals.hasConst()) |
377 | 10 | Fragments.append("const", DeclarationFragments::FragmentKind::Keyword); |
378 | 461 | if (Quals.hasVolatile()) |
379 | 0 | Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword); |
380 | 461 | if (Quals.hasRestrict()) |
381 | 0 | Fragments.append("restrict", DeclarationFragments::FragmentKind::Keyword); |
382 | | |
383 | 461 | return Fragments; |
384 | 461 | } |
385 | | |
386 | | DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( |
387 | 461 | const QualType QT, ASTContext &Context, DeclarationFragments &After) { |
388 | 461 | assert(!QT.isNull() && "invalid type"); |
389 | | |
390 | 461 | if (const ParenType *PT = dyn_cast<ParenType>(QT)) { |
391 | 0 | After.append(")", DeclarationFragments::FragmentKind::Text); |
392 | 0 | return getFragmentsForType(PT->getInnerType(), Context, After) |
393 | 0 | .append("(", DeclarationFragments::FragmentKind::Text); |
394 | 0 | } |
395 | | |
396 | 461 | const SplitQualType SQT = QT.split(); |
397 | 461 | DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals), |
398 | 461 | TypeFragments = |
399 | 461 | getFragmentsForType(SQT.Ty, Context, After); |
400 | 461 | if (QT.getAsString() == "_Bool") |
401 | 10 | TypeFragments.replace("bool", 0); |
402 | | |
403 | 461 | if (QualsFragments.getFragments().empty()) |
404 | 451 | return TypeFragments; |
405 | | |
406 | | // Use east qualifier for pointer types |
407 | | // For example: |
408 | | // ``` |
409 | | // int * const |
410 | | // ^---- ^---- |
411 | | // type qualifier |
412 | | // ^----------------- |
413 | | // const pointer to int |
414 | | // ``` |
415 | | // should not be reconstructed as |
416 | | // ``` |
417 | | // const int * |
418 | | // ^---- ^-- |
419 | | // qualifier type |
420 | | // ^---------------- ^ |
421 | | // pointer to const int |
422 | | // ``` |
423 | 10 | if (SQT.Ty->isAnyPointerType()) |
424 | 0 | return TypeFragments.appendSpace().append(std::move(QualsFragments)); |
425 | | |
426 | 10 | return QualsFragments.appendSpace().append(std::move(TypeFragments)); |
427 | 10 | } |
428 | | |
429 | | DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace( |
430 | 3 | const NamespaceDecl *Decl) { |
431 | 3 | DeclarationFragments Fragments; |
432 | 3 | Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword); |
433 | 3 | if (!Decl->isAnonymousNamespace()) |
434 | 3 | Fragments.appendSpace().append( |
435 | 3 | Decl->getName(), DeclarationFragments::FragmentKind::Identifier); |
436 | 3 | return Fragments.append(";", DeclarationFragments::FragmentKind::Text); |
437 | 3 | } |
438 | | |
439 | | DeclarationFragments |
440 | 13 | DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { |
441 | 13 | DeclarationFragments Fragments; |
442 | 13 | if (Var->isConstexpr()) |
443 | 0 | Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) |
444 | 0 | .appendSpace(); |
445 | | |
446 | 13 | StorageClass SC = Var->getStorageClass(); |
447 | 13 | if (SC != SC_None) |
448 | 0 | Fragments |
449 | 0 | .append(VarDecl::getStorageClassSpecifierString(SC), |
450 | 0 | DeclarationFragments::FragmentKind::Keyword) |
451 | 0 | .appendSpace(); |
452 | 13 | QualType T = |
453 | 13 | Var->getTypeSourceInfo() |
454 | 13 | ? Var->getTypeSourceInfo()->getType() |
455 | 13 | : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType())0 ; |
456 | | |
457 | | // Capture potential fragments that needs to be placed after the variable name |
458 | | // ``` |
459 | | // int nums[5]; |
460 | | // char (*ptr_to_array)[6]; |
461 | | // ``` |
462 | 13 | DeclarationFragments After; |
463 | 13 | return Fragments.append(getFragmentsForType(T, Var->getASTContext(), After)) |
464 | 13 | .appendSpace() |
465 | 13 | .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) |
466 | 13 | .append(std::move(After)) |
467 | 13 | .append(";", DeclarationFragments::FragmentKind::Text); |
468 | 13 | } |
469 | | |
470 | | DeclarationFragments |
471 | 6 | DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) { |
472 | 6 | DeclarationFragments Fragments; |
473 | 6 | if (Var->isConstexpr()) |
474 | 0 | Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) |
475 | 0 | .appendSpace(); |
476 | 6 | QualType T = |
477 | 6 | Var->getTypeSourceInfo() |
478 | 6 | ? Var->getTypeSourceInfo()->getType() |
479 | 6 | : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType())0 ; |
480 | | |
481 | | // Might be a member, so might be static. |
482 | 6 | if (Var->isStaticDataMember()) |
483 | 1 | Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) |
484 | 1 | .appendSpace(); |
485 | | |
486 | 6 | DeclarationFragments After; |
487 | 6 | DeclarationFragments ArgumentFragment = |
488 | 6 | getFragmentsForType(T, Var->getASTContext(), After); |
489 | 6 | if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare( |
490 | 6 | "type-parameter") == 0) { |
491 | 3 | std::string ProperArgName = getNameForTemplateArgument( |
492 | 3 | Var->getDescribedVarTemplate()->getTemplateParameters()->asArray(), |
493 | 3 | ArgumentFragment.begin()->Spelling); |
494 | 3 | ArgumentFragment.begin()->Spelling.swap(ProperArgName); |
495 | 3 | } |
496 | 6 | Fragments.append(std::move(ArgumentFragment)) |
497 | 6 | .appendSpace() |
498 | 6 | .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier) |
499 | 6 | .append(";", DeclarationFragments::FragmentKind::Text); |
500 | 6 | return Fragments; |
501 | 6 | } |
502 | | |
503 | | DeclarationFragments |
504 | 108 | DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { |
505 | 108 | DeclarationFragments Fragments, After; |
506 | | |
507 | 108 | QualType T = Param->getTypeSourceInfo() |
508 | 108 | ? Param->getTypeSourceInfo()->getType() |
509 | 108 | : Param->getASTContext().getUnqualifiedObjCPointerType( |
510 | 0 | Param->getType()); |
511 | | |
512 | 108 | DeclarationFragments TypeFragments = |
513 | 108 | getFragmentsForType(T, Param->getASTContext(), After); |
514 | 108 | if (TypeFragments.begin()->Spelling.substr(0, 14).compare("type-parameter") == |
515 | 108 | 0) { |
516 | 10 | std::string ProperArgName = getNameForTemplateArgument( |
517 | 10 | dyn_cast<FunctionDecl>(Param->getDeclContext()) |
518 | 10 | ->getDescribedFunctionTemplate() |
519 | 10 | ->getTemplateParameters() |
520 | 10 | ->asArray(), |
521 | 10 | TypeFragments.begin()->Spelling); |
522 | 10 | TypeFragments.begin()->Spelling.swap(ProperArgName); |
523 | 10 | } |
524 | | |
525 | 108 | if (Param->isObjCMethodParameter()) |
526 | 56 | Fragments.append("(", DeclarationFragments::FragmentKind::Text) |
527 | 56 | .append(std::move(TypeFragments)) |
528 | 56 | .append(") ", DeclarationFragments::FragmentKind::Text); |
529 | 52 | else |
530 | 52 | Fragments.append(std::move(TypeFragments)).appendSpace(); |
531 | | |
532 | 108 | return Fragments |
533 | 108 | .append(Param->getName(), |
534 | 108 | DeclarationFragments::FragmentKind::InternalParam) |
535 | 108 | .append(std::move(After)); |
536 | 108 | } |
537 | | |
538 | | DeclarationFragments |
539 | 33 | DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { |
540 | 33 | DeclarationFragments Fragments; |
541 | | // FIXME: Handle template specialization |
542 | 33 | switch (Func->getStorageClass()) { |
543 | 33 | case SC_None: |
544 | 33 | case SC_PrivateExtern: |
545 | 33 | break; |
546 | 0 | case SC_Extern: |
547 | 0 | Fragments.append("extern", DeclarationFragments::FragmentKind::Keyword) |
548 | 0 | .appendSpace(); |
549 | 0 | break; |
550 | 0 | case SC_Static: |
551 | 0 | Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) |
552 | 0 | .appendSpace(); |
553 | 0 | break; |
554 | 0 | case SC_Auto: |
555 | 0 | case SC_Register: |
556 | 0 | llvm_unreachable("invalid for functions"); |
557 | 33 | } |
558 | 33 | if (Func->isConsteval()) // if consteval, it is also constexpr |
559 | 0 | Fragments.append("consteval", DeclarationFragments::FragmentKind::Keyword) |
560 | 0 | .appendSpace(); |
561 | 33 | else if (Func->isConstexpr()) |
562 | 0 | Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) |
563 | 0 | .appendSpace(); |
564 | | |
565 | | // FIXME: Is `after` actually needed here? |
566 | 33 | DeclarationFragments After; |
567 | 33 | auto ReturnValueFragment = |
568 | 33 | getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After); |
569 | 33 | if (ReturnValueFragment.begin()->Spelling.substr(0, 14).compare( |
570 | 33 | "type-parameter") == 0) { |
571 | 1 | std::string ProperArgName = |
572 | 1 | getNameForTemplateArgument(Func->getDescribedFunctionTemplate() |
573 | 1 | ->getTemplateParameters() |
574 | 1 | ->asArray(), |
575 | 1 | ReturnValueFragment.begin()->Spelling); |
576 | 1 | ReturnValueFragment.begin()->Spelling.swap(ProperArgName); |
577 | 1 | } |
578 | | |
579 | 33 | Fragments.append(std::move(ReturnValueFragment)) |
580 | 33 | .appendSpace() |
581 | 33 | .append(Func->getName(), DeclarationFragments::FragmentKind::Identifier); |
582 | | |
583 | 33 | if (Func->getTemplateSpecializationInfo()) { |
584 | 2 | Fragments.append("<", DeclarationFragments::FragmentKind::Text); |
585 | | |
586 | 4 | for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i2 ) { |
587 | 2 | if (i) |
588 | 0 | Fragments.append(", ", DeclarationFragments::FragmentKind::Text); |
589 | 2 | Fragments.append( |
590 | 2 | getFragmentsForType(Func->getParamDecl(i)->getType(), |
591 | 2 | Func->getParamDecl(i)->getASTContext(), After)); |
592 | 2 | } |
593 | 2 | Fragments.append(">", DeclarationFragments::FragmentKind::Text); |
594 | 2 | } |
595 | 33 | Fragments.append(std::move(After)); |
596 | | |
597 | 33 | Fragments.append("(", DeclarationFragments::FragmentKind::Text); |
598 | 56 | for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i23 ) { |
599 | 23 | if (i) |
600 | 8 | Fragments.append(", ", DeclarationFragments::FragmentKind::Text); |
601 | 23 | Fragments.append(getFragmentsForParam(Func->getParamDecl(i))); |
602 | 23 | } |
603 | 33 | Fragments.append(")", DeclarationFragments::FragmentKind::Text); |
604 | | |
605 | 33 | Fragments.append(DeclarationFragments::getExceptionSpecificationString( |
606 | 33 | Func->getExceptionSpecType())); |
607 | | |
608 | 33 | return Fragments.append(";", DeclarationFragments::FragmentKind::Text); |
609 | 33 | } |
610 | | |
611 | | DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant( |
612 | 15 | const EnumConstantDecl *EnumConstDecl) { |
613 | 15 | DeclarationFragments Fragments; |
614 | 15 | return Fragments.append(EnumConstDecl->getName(), |
615 | 15 | DeclarationFragments::FragmentKind::Identifier); |
616 | 15 | } |
617 | | |
618 | | DeclarationFragments |
619 | 7 | DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) { |
620 | 7 | if (const auto *TypedefNameDecl = EnumDecl->getTypedefNameForAnonDecl()) |
621 | 1 | return getFragmentsForTypedef(TypedefNameDecl); |
622 | | |
623 | 6 | DeclarationFragments Fragments, After; |
624 | 6 | Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword); |
625 | | |
626 | 6 | if (!EnumDecl->getName().empty()) |
627 | 3 | Fragments.appendSpace().append( |
628 | 3 | EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier); |
629 | | |
630 | 6 | QualType IntegerType = EnumDecl->getIntegerType(); |
631 | 6 | if (!IntegerType.isNull()) |
632 | 6 | Fragments.append(": ", DeclarationFragments::FragmentKind::Text) |
633 | 6 | .append( |
634 | 6 | getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After)) |
635 | 6 | .append(std::move(After)); |
636 | | |
637 | 6 | return Fragments.append(";", DeclarationFragments::FragmentKind::Text); |
638 | 7 | } |
639 | | |
640 | | DeclarationFragments |
641 | 27 | DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) { |
642 | 27 | DeclarationFragments After; |
643 | 27 | DeclarationFragments Fragments; |
644 | 27 | if (Field->isMutable()) |
645 | 1 | Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword) |
646 | 1 | .appendSpace(); |
647 | 27 | return Fragments |
648 | 27 | .append( |
649 | 27 | getFragmentsForType(Field->getType(), Field->getASTContext(), After)) |
650 | 27 | .appendSpace() |
651 | 27 | .append(Field->getName(), DeclarationFragments::FragmentKind::Identifier) |
652 | 27 | .append(std::move(After)) |
653 | 27 | .append(";", DeclarationFragments::FragmentKind::Text); |
654 | 27 | } |
655 | | |
656 | | DeclarationFragments |
657 | 21 | DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) { |
658 | 21 | if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) |
659 | 2 | return getFragmentsForTypedef(TypedefNameDecl); |
660 | | |
661 | 19 | DeclarationFragments Fragments; |
662 | 19 | Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword); |
663 | | |
664 | 19 | if (!Record->getName().empty()) |
665 | 19 | Fragments.appendSpace().append( |
666 | 19 | Record->getName(), DeclarationFragments::FragmentKind::Identifier); |
667 | | |
668 | 19 | return Fragments.append(";", DeclarationFragments::FragmentKind::Text); |
669 | 21 | } |
670 | | |
671 | | DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass( |
672 | 21 | const CXXRecordDecl *Record) { |
673 | 21 | if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl()) |
674 | 0 | return getFragmentsForTypedef(TypedefNameDecl); |
675 | | |
676 | 21 | DeclarationFragments Fragments; |
677 | 21 | Fragments.append(DeclarationFragments::getStructureTypeFragment(Record)); |
678 | | |
679 | 21 | if (!Record->getName().empty()) |
680 | 21 | Fragments.appendSpace().append( |
681 | 21 | Record->getName(), DeclarationFragments::FragmentKind::Identifier); |
682 | | |
683 | 21 | return Fragments.append(";", DeclarationFragments::FragmentKind::Text); |
684 | 21 | } |
685 | | |
686 | | DeclarationFragments |
687 | | DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod( |
688 | 2 | const CXXMethodDecl *Method) { |
689 | 2 | DeclarationFragments Fragments; |
690 | 2 | std::string Name; |
691 | 2 | if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) { |
692 | 1 | Name = Method->getNameAsString(); |
693 | 1 | if (Constructor->isExplicit()) |
694 | 0 | Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword) |
695 | 0 | .appendSpace(); |
696 | 1 | } else if (isa<CXXDestructorDecl>(Method)) |
697 | 1 | Name = Method->getNameAsString(); |
698 | | |
699 | 2 | DeclarationFragments After; |
700 | 2 | Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier) |
701 | 2 | .append(std::move(After)); |
702 | 2 | Fragments.append("(", DeclarationFragments::FragmentKind::Text); |
703 | 2 | for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i0 ) { |
704 | 0 | if (i) |
705 | 0 | Fragments.append(", ", DeclarationFragments::FragmentKind::Text); |
706 | 0 | Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); |
707 | 0 | } |
708 | 2 | Fragments.append(")", DeclarationFragments::FragmentKind::Text); |
709 | | |
710 | 2 | Fragments.append(DeclarationFragments::getExceptionSpecificationString( |
711 | 2 | Method->getExceptionSpecType())); |
712 | | |
713 | 2 | return Fragments.append(";", DeclarationFragments::FragmentKind::Text); |
714 | 2 | } |
715 | | |
716 | | DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod( |
717 | 4 | const CXXMethodDecl *Method) { |
718 | 4 | DeclarationFragments Fragments; |
719 | 4 | StringRef Name = Method->getName(); |
720 | 4 | if (Method->isStatic()) |
721 | 1 | Fragments.append("static", DeclarationFragments::FragmentKind::Keyword) |
722 | 1 | .appendSpace(); |
723 | 4 | if (Method->isConstexpr()) |
724 | 1 | Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword) |
725 | 1 | .appendSpace(); |
726 | 4 | if (Method->isVolatile()) |
727 | 0 | Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword) |
728 | 0 | .appendSpace(); |
729 | | |
730 | | // Build return type |
731 | 4 | DeclarationFragments After; |
732 | 4 | Fragments |
733 | 4 | .append(getFragmentsForType(Method->getReturnType(), |
734 | 4 | Method->getASTContext(), After)) |
735 | 4 | .appendSpace() |
736 | 4 | .append(Name, DeclarationFragments::FragmentKind::Identifier) |
737 | 4 | .append(std::move(After)); |
738 | 4 | Fragments.append("(", DeclarationFragments::FragmentKind::Text); |
739 | 5 | for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i1 ) { |
740 | 1 | if (i) |
741 | 0 | Fragments.append(", ", DeclarationFragments::FragmentKind::Text); |
742 | 1 | Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); |
743 | 1 | } |
744 | 4 | Fragments.append(")", DeclarationFragments::FragmentKind::Text); |
745 | | |
746 | 4 | if (Method->isConst()) |
747 | 1 | Fragments.appendSpace().append("const", |
748 | 1 | DeclarationFragments::FragmentKind::Keyword); |
749 | | |
750 | 4 | Fragments.append(DeclarationFragments::getExceptionSpecificationString( |
751 | 4 | Method->getExceptionSpecType())); |
752 | | |
753 | 4 | return Fragments.append(";", DeclarationFragments::FragmentKind::Text); |
754 | 4 | } |
755 | | |
756 | | DeclarationFragments |
757 | | DeclarationFragmentsBuilder::getFragmentsForConversionFunction( |
758 | 2 | const CXXConversionDecl *ConversionFunction) { |
759 | 2 | DeclarationFragments Fragments; |
760 | | |
761 | 2 | if (ConversionFunction->isExplicit()) |
762 | 1 | Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword) |
763 | 1 | .appendSpace(); |
764 | | |
765 | 2 | Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword) |
766 | 2 | .appendSpace(); |
767 | | |
768 | 2 | Fragments |
769 | 2 | .append(ConversionFunction->getConversionType().getAsString(), |
770 | 2 | DeclarationFragments::FragmentKind::TypeIdentifier) |
771 | 2 | .append("(", DeclarationFragments::FragmentKind::Text); |
772 | 2 | for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end; |
773 | 2 | ++i0 ) { |
774 | 0 | if (i) |
775 | 0 | Fragments.append(", ", DeclarationFragments::FragmentKind::Text); |
776 | 0 | Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i))); |
777 | 0 | } |
778 | 2 | Fragments.append(")", DeclarationFragments::FragmentKind::Text); |
779 | | |
780 | 2 | if (ConversionFunction->isConst()) |
781 | 0 | Fragments.appendSpace().append("const", |
782 | 0 | DeclarationFragments::FragmentKind::Keyword); |
783 | | |
784 | 2 | return Fragments.append(";", DeclarationFragments::FragmentKind::Text); |
785 | 2 | } |
786 | | |
787 | | DeclarationFragments |
788 | | DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator( |
789 | 1 | const CXXMethodDecl *Method) { |
790 | 1 | DeclarationFragments Fragments; |
791 | | |
792 | | // Build return type |
793 | 1 | DeclarationFragments After; |
794 | 1 | Fragments |
795 | 1 | .append(getFragmentsForType(Method->getReturnType(), |
796 | 1 | Method->getASTContext(), After)) |
797 | 1 | .appendSpace() |
798 | 1 | .append(Method->getNameAsString(), |
799 | 1 | DeclarationFragments::FragmentKind::Identifier) |
800 | 1 | .append(std::move(After)); |
801 | 1 | Fragments.append("(", DeclarationFragments::FragmentKind::Text); |
802 | 2 | for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i1 ) { |
803 | 1 | if (i) |
804 | 0 | Fragments.append(", ", DeclarationFragments::FragmentKind::Text); |
805 | 1 | Fragments.append(getFragmentsForParam(Method->getParamDecl(i))); |
806 | 1 | } |
807 | 1 | Fragments.append(")", DeclarationFragments::FragmentKind::Text); |
808 | | |
809 | 1 | if (Method->isConst()) |
810 | 0 | Fragments.appendSpace().append("const", |
811 | 0 | DeclarationFragments::FragmentKind::Keyword); |
812 | | |
813 | 1 | Fragments.append(DeclarationFragments::getExceptionSpecificationString( |
814 | 1 | Method->getExceptionSpecType())); |
815 | | |
816 | 1 | return Fragments.append(";", DeclarationFragments::FragmentKind::Text); |
817 | 1 | } |
818 | | |
819 | | // Get fragments for template parameters, e.g. T in tempalte<typename T> ... |
820 | | DeclarationFragments |
821 | | DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( |
822 | 16 | ArrayRef<NamedDecl *> ParameterArray) { |
823 | 16 | DeclarationFragments Fragments; |
824 | 34 | for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i18 ) { |
825 | 18 | if (i) |
826 | 2 | Fragments.append(",", DeclarationFragments::FragmentKind::Text) |
827 | 2 | .appendSpace(); |
828 | | |
829 | 18 | const auto *TemplateParam = |
830 | 18 | dyn_cast<TemplateTypeParmDecl>(ParameterArray[i]); |
831 | 18 | if (!TemplateParam) |
832 | 0 | continue; |
833 | 18 | if (TemplateParam->hasTypeConstraint()) |
834 | 0 | Fragments.append(TemplateParam->getTypeConstraint() |
835 | 0 | ->getNamedConcept() |
836 | 0 | ->getName() |
837 | 0 | .str(), |
838 | 0 | DeclarationFragments::FragmentKind::TypeIdentifier); |
839 | 18 | else if (TemplateParam->wasDeclaredWithTypename()) |
840 | 18 | Fragments.append("typename", DeclarationFragments::FragmentKind::Keyword); |
841 | 0 | else |
842 | 0 | Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); |
843 | | |
844 | 18 | if (TemplateParam->isParameterPack()) |
845 | 0 | Fragments.append("...", DeclarationFragments::FragmentKind::Text); |
846 | | |
847 | 18 | Fragments.appendSpace().append( |
848 | 18 | TemplateParam->getName(), |
849 | 18 | DeclarationFragments::FragmentKind::GenericParameter); |
850 | 18 | } |
851 | 16 | return Fragments; |
852 | 16 | } |
853 | | |
854 | | // Find the name of a template argument from the template's parameters. |
855 | | std::string DeclarationFragmentsBuilder::getNameForTemplateArgument( |
856 | 17 | const ArrayRef<NamedDecl *> TemplateParameters, std::string TypeParameter) { |
857 | | // The arg is a generic parameter from a partial spec, e.g. |
858 | | // T in template<typename T> Foo<T, int>. |
859 | | // |
860 | | // Those names appear as "type-parameter-<index>-<depth>", so we must find its |
861 | | // name from the template's parameter list. |
862 | 17 | for (unsigned i = 0; i < TemplateParameters.size(); ++i0 ) { |
863 | 17 | const auto *Parameter = |
864 | 17 | dyn_cast<TemplateTypeParmDecl>(TemplateParameters[i]); |
865 | 17 | if (TypeParameter.compare("type-parameter-" + |
866 | 17 | std::to_string(Parameter->getDepth()) + "-" + |
867 | 17 | std::to_string(Parameter->getIndex())) == 0) |
868 | 17 | return std::string(TemplateParameters[i]->getName()); |
869 | 17 | } |
870 | 0 | llvm_unreachable("Could not find the name of a template argument."); |
871 | 0 | } |
872 | | |
873 | | // Get fragments for template arguments, e.g. int in template<typename T> |
874 | | // Foo<int>; |
875 | | // |
876 | | // Note: TemplateParameters is only necessary if the Decl is a |
877 | | // PartialSpecialization, where we need the parameters to deduce the name of the |
878 | | // generic arguments. |
879 | | DeclarationFragments |
880 | | DeclarationFragmentsBuilder::getFragmentsForTemplateArguments( |
881 | | const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context, |
882 | 4 | const std::optional<ArrayRef<NamedDecl *>> TemplateParameters) { |
883 | 4 | DeclarationFragments Fragments; |
884 | 10 | for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i6 ) { |
885 | 6 | if (i) |
886 | 2 | Fragments.append(",", DeclarationFragments::FragmentKind::Text) |
887 | 2 | .appendSpace(); |
888 | | |
889 | 6 | std::string Type = TemplateArguments[i].getAsType().getAsString(); |
890 | 6 | DeclarationFragments After; |
891 | 6 | DeclarationFragments ArgumentFragment = |
892 | 6 | getFragmentsForType(TemplateArguments[i].getAsType(), Context, After); |
893 | | |
894 | 6 | if (ArgumentFragment.begin()->Spelling.substr(0, 14).compare( |
895 | 6 | "type-parameter") == 0) { |
896 | 2 | std::string ProperArgName = getNameForTemplateArgument( |
897 | 2 | TemplateParameters.value(), ArgumentFragment.begin()->Spelling); |
898 | 2 | ArgumentFragment.begin()->Spelling.swap(ProperArgName); |
899 | 2 | } |
900 | 6 | Fragments.append(std::move(ArgumentFragment)); |
901 | | |
902 | 6 | if (TemplateArguments[i].isPackExpansion()) |
903 | 0 | Fragments.append("...", DeclarationFragments::FragmentKind::Text); |
904 | 6 | } |
905 | 4 | return Fragments; |
906 | 4 | } |
907 | | |
908 | | DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept( |
909 | 1 | const ConceptDecl *Concept) { |
910 | 1 | DeclarationFragments Fragments; |
911 | 1 | return Fragments |
912 | 1 | .append("template", DeclarationFragments::FragmentKind::Keyword) |
913 | 1 | .append("<", DeclarationFragments::FragmentKind::Text) |
914 | 1 | .append(getFragmentsForTemplateParameters( |
915 | 1 | Concept->getTemplateParameters()->asArray())) |
916 | 1 | .append("> ", DeclarationFragments::FragmentKind::Text) |
917 | 1 | .append("concept", DeclarationFragments::FragmentKind::Keyword) |
918 | 1 | .appendSpace() |
919 | 1 | .append(Concept->getName().str(), |
920 | 1 | DeclarationFragments::FragmentKind::Identifier) |
921 | 1 | .append(";", DeclarationFragments::FragmentKind::Text); |
922 | 1 | } |
923 | | |
924 | | DeclarationFragments |
925 | | DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate( |
926 | 8 | const RedeclarableTemplateDecl *RedeclarableTemplate) { |
927 | 8 | DeclarationFragments Fragments; |
928 | 8 | Fragments.append("template", DeclarationFragments::FragmentKind::Keyword) |
929 | 8 | .append("<", DeclarationFragments::FragmentKind::Text) |
930 | 8 | .append(getFragmentsForTemplateParameters( |
931 | 8 | RedeclarableTemplate->getTemplateParameters()->asArray())) |
932 | 8 | .append(">", DeclarationFragments::FragmentKind::Text) |
933 | 8 | .appendSpace(); |
934 | | |
935 | 8 | if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate)) |
936 | 0 | Fragments.appendSpace() |
937 | 0 | .append("using", DeclarationFragments::FragmentKind::Keyword) |
938 | 0 | .appendSpace() |
939 | 0 | .append(RedeclarableTemplate->getName(), |
940 | 0 | DeclarationFragments::FragmentKind::Identifier); |
941 | | // the templated records will be resposbible for injecting their templates |
942 | 8 | return Fragments.appendSpace(); |
943 | 8 | } |
944 | | |
945 | | DeclarationFragments |
946 | | DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization( |
947 | 1 | const ClassTemplateSpecializationDecl *Decl) { |
948 | 1 | DeclarationFragments Fragments; |
949 | 1 | return Fragments |
950 | 1 | .append("template", DeclarationFragments::FragmentKind::Keyword) |
951 | 1 | .append("<", DeclarationFragments::FragmentKind::Text) |
952 | 1 | .append(">", DeclarationFragments::FragmentKind::Text) |
953 | 1 | .appendSpace() |
954 | 1 | .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass( |
955 | 1 | cast<CXXRecordDecl>(Decl))) |
956 | 1 | .pop_back() // there is an extra semicolon now |
957 | 1 | .append("<", DeclarationFragments::FragmentKind::Text) |
958 | 1 | .append( |
959 | 1 | getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), |
960 | 1 | Decl->getASTContext(), std::nullopt)) |
961 | 1 | .append(">", DeclarationFragments::FragmentKind::Text) |
962 | 1 | .append(";", DeclarationFragments::FragmentKind::Text); |
963 | 1 | } |
964 | | |
965 | | DeclarationFragments |
966 | | DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization( |
967 | 1 | const ClassTemplatePartialSpecializationDecl *Decl) { |
968 | 1 | DeclarationFragments Fragments; |
969 | 1 | return Fragments |
970 | 1 | .append("template", DeclarationFragments::FragmentKind::Keyword) |
971 | 1 | .append("<", DeclarationFragments::FragmentKind::Text) |
972 | 1 | .append(getFragmentsForTemplateParameters( |
973 | 1 | Decl->getTemplateParameters()->asArray())) |
974 | 1 | .append(">", DeclarationFragments::FragmentKind::Text) |
975 | 1 | .appendSpace() |
976 | 1 | .append(DeclarationFragmentsBuilder::getFragmentsForCXXClass( |
977 | 1 | cast<CXXRecordDecl>(Decl))) |
978 | 1 | .pop_back() // there is an extra semicolon now |
979 | 1 | .append("<", DeclarationFragments::FragmentKind::Text) |
980 | 1 | .append(getFragmentsForTemplateArguments( |
981 | 1 | Decl->getTemplateArgs().asArray(), Decl->getASTContext(), |
982 | 1 | Decl->getTemplateParameters()->asArray())) |
983 | 1 | .append(">", DeclarationFragments::FragmentKind::Text) |
984 | 1 | .append(";", DeclarationFragments::FragmentKind::Text); |
985 | 1 | } |
986 | | |
987 | | DeclarationFragments |
988 | | DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization( |
989 | 1 | const VarTemplateSpecializationDecl *Decl) { |
990 | 1 | DeclarationFragments Fragments; |
991 | 1 | return Fragments |
992 | 1 | .append("template", DeclarationFragments::FragmentKind::Keyword) |
993 | 1 | .append("<", DeclarationFragments::FragmentKind::Text) |
994 | 1 | .append(">", DeclarationFragments::FragmentKind::Text) |
995 | 1 | .appendSpace() |
996 | 1 | .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) |
997 | 1 | .pop_back() // there is an extra semicolon now |
998 | 1 | .append("<", DeclarationFragments::FragmentKind::Text) |
999 | 1 | .append( |
1000 | 1 | getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), |
1001 | 1 | Decl->getASTContext(), std::nullopt)) |
1002 | 1 | .append(">", DeclarationFragments::FragmentKind::Text) |
1003 | 1 | .append(";", DeclarationFragments::FragmentKind::Text); |
1004 | 1 | } |
1005 | | |
1006 | | DeclarationFragments |
1007 | | DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization( |
1008 | 1 | const VarTemplatePartialSpecializationDecl *Decl) { |
1009 | 1 | DeclarationFragments Fragments; |
1010 | 1 | return Fragments |
1011 | 1 | .append("template", DeclarationFragments::FragmentKind::Keyword) |
1012 | 1 | .append("<", DeclarationFragments::FragmentKind::Text) |
1013 | | // Partial specs may have new params. |
1014 | 1 | .append(getFragmentsForTemplateParameters( |
1015 | 1 | Decl->getTemplateParameters()->asArray())) |
1016 | 1 | .append(">", DeclarationFragments::FragmentKind::Text) |
1017 | 1 | .appendSpace() |
1018 | 1 | .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) |
1019 | 1 | .pop_back() // there is an extra semicolon now |
1020 | 1 | .append("<", DeclarationFragments::FragmentKind::Text) |
1021 | 1 | .append(getFragmentsForTemplateArguments( |
1022 | 1 | Decl->getTemplateArgs().asArray(), Decl->getASTContext(), |
1023 | 1 | Decl->getTemplateParameters()->asArray())) |
1024 | 1 | .append(">", DeclarationFragments::FragmentKind::Text) |
1025 | 1 | .append(";", DeclarationFragments::FragmentKind::Text); |
1026 | 1 | } |
1027 | | |
1028 | | DeclarationFragments |
1029 | | DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate( |
1030 | 5 | const FunctionTemplateDecl *Decl) { |
1031 | 5 | DeclarationFragments Fragments; |
1032 | 5 | return Fragments |
1033 | 5 | .append("template", DeclarationFragments::FragmentKind::Keyword) |
1034 | 5 | .append("<", DeclarationFragments::FragmentKind::Text) |
1035 | | // Partial specs may have new params. |
1036 | 5 | .append(getFragmentsForTemplateParameters( |
1037 | 5 | Decl->getTemplateParameters()->asArray())) |
1038 | 5 | .append(">", DeclarationFragments::FragmentKind::Text) |
1039 | 5 | .appendSpace() |
1040 | 5 | .append(DeclarationFragmentsBuilder::getFragmentsForFunction( |
1041 | 5 | Decl->getAsFunction())); |
1042 | 5 | } |
1043 | | |
1044 | | DeclarationFragments |
1045 | | DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization( |
1046 | 2 | const FunctionDecl *Decl) { |
1047 | 2 | DeclarationFragments Fragments; |
1048 | 2 | return Fragments |
1049 | 2 | .append("template", DeclarationFragments::FragmentKind::Keyword) |
1050 | 2 | .append("<>", DeclarationFragments::FragmentKind::Text) |
1051 | 2 | .appendSpace() |
1052 | 2 | .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl)); |
1053 | 2 | } |
1054 | | |
1055 | | DeclarationFragments |
1056 | | DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name, |
1057 | 24 | const MacroDirective *MD) { |
1058 | 24 | DeclarationFragments Fragments; |
1059 | 24 | Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword) |
1060 | 24 | .appendSpace(); |
1061 | 24 | Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); |
1062 | | |
1063 | 24 | auto *MI = MD->getMacroInfo(); |
1064 | | |
1065 | 24 | if (MI->isFunctionLike()) { |
1066 | 4 | Fragments.append("(", DeclarationFragments::FragmentKind::Text); |
1067 | 4 | unsigned numParameters = MI->getNumParams(); |
1068 | 4 | if (MI->isC99Varargs()) |
1069 | 1 | --numParameters; |
1070 | 10 | for (unsigned i = 0; i < numParameters; ++i6 ) { |
1071 | 6 | if (i) |
1072 | 2 | Fragments.append(", ", DeclarationFragments::FragmentKind::Text); |
1073 | 6 | Fragments.append(MI->params()[i]->getName(), |
1074 | 6 | DeclarationFragments::FragmentKind::InternalParam); |
1075 | 6 | } |
1076 | 4 | if (MI->isVariadic()) { |
1077 | 2 | if (numParameters && MI->isC99Varargs()) |
1078 | 1 | Fragments.append(", ", DeclarationFragments::FragmentKind::Text); |
1079 | 2 | Fragments.append("...", DeclarationFragments::FragmentKind::Text); |
1080 | 2 | } |
1081 | 4 | Fragments.append(")", DeclarationFragments::FragmentKind::Text); |
1082 | 4 | } |
1083 | 24 | return Fragments; |
1084 | 24 | } |
1085 | | |
1086 | | DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory( |
1087 | 7 | const ObjCCategoryDecl *Category) { |
1088 | 7 | DeclarationFragments Fragments; |
1089 | | |
1090 | 7 | auto *Interface = Category->getClassInterface(); |
1091 | 7 | SmallString<128> InterfaceUSR; |
1092 | 7 | index::generateUSRForDecl(Interface, InterfaceUSR); |
1093 | | |
1094 | 7 | Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) |
1095 | 7 | .appendSpace() |
1096 | 7 | .append(Category->getClassInterface()->getName(), |
1097 | 7 | DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR, |
1098 | 7 | Interface) |
1099 | 7 | .append(" (", DeclarationFragments::FragmentKind::Text) |
1100 | 7 | .append(Category->getName(), |
1101 | 7 | DeclarationFragments::FragmentKind::Identifier) |
1102 | 7 | .append(")", DeclarationFragments::FragmentKind::Text); |
1103 | | |
1104 | 7 | return Fragments; |
1105 | 7 | } |
1106 | | |
1107 | | DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCInterface( |
1108 | 32 | const ObjCInterfaceDecl *Interface) { |
1109 | 32 | DeclarationFragments Fragments; |
1110 | | // Build the base of the Objective-C interface declaration. |
1111 | 32 | Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword) |
1112 | 32 | .appendSpace() |
1113 | 32 | .append(Interface->getName(), |
1114 | 32 | DeclarationFragments::FragmentKind::Identifier); |
1115 | | |
1116 | | // Build the inheritance part of the declaration. |
1117 | 32 | if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) { |
1118 | 13 | SmallString<128> SuperUSR; |
1119 | 13 | index::generateUSRForDecl(SuperClass, SuperUSR); |
1120 | 13 | Fragments.append(" : ", DeclarationFragments::FragmentKind::Text) |
1121 | 13 | .append(SuperClass->getName(), |
1122 | 13 | DeclarationFragments::FragmentKind::TypeIdentifier, SuperUSR, |
1123 | 13 | SuperClass); |
1124 | 13 | } |
1125 | | |
1126 | 32 | return Fragments; |
1127 | 32 | } |
1128 | | |
1129 | | DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod( |
1130 | 37 | const ObjCMethodDecl *Method) { |
1131 | 37 | DeclarationFragments Fragments, After; |
1132 | | // Build the instance/class method indicator. |
1133 | 37 | if (Method->isClassMethod()) |
1134 | 2 | Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); |
1135 | 35 | else if (Method->isInstanceMethod()) |
1136 | 35 | Fragments.append("- ", DeclarationFragments::FragmentKind::Text); |
1137 | | |
1138 | | // Build the return type. |
1139 | 37 | Fragments.append("(", DeclarationFragments::FragmentKind::Text) |
1140 | 37 | .append(getFragmentsForType(Method->getReturnType(), |
1141 | 37 | Method->getASTContext(), After)) |
1142 | 37 | .append(std::move(After)) |
1143 | 37 | .append(")", DeclarationFragments::FragmentKind::Text); |
1144 | | |
1145 | | // Build the selector part. |
1146 | 37 | Selector Selector = Method->getSelector(); |
1147 | 37 | if (Selector.getNumArgs() == 0) |
1148 | | // For Objective-C methods that don't take arguments, the first (and only) |
1149 | | // slot of the selector is the method name. |
1150 | 10 | Fragments.appendSpace().append( |
1151 | 10 | Selector.getNameForSlot(0), |
1152 | 10 | DeclarationFragments::FragmentKind::Identifier); |
1153 | | |
1154 | | // For Objective-C methods that take arguments, build the selector slots. |
1155 | 65 | for (unsigned i = 0, end = Method->param_size(); i != end; ++i28 ) { |
1156 | | // Objective-C method selector parts are considered as identifiers instead |
1157 | | // of "external parameters" as in Swift. This is because Objective-C method |
1158 | | // symbols are referenced with the entire selector, instead of just the |
1159 | | // method name in Swift. |
1160 | 28 | SmallString<32> ParamID(Selector.getNameForSlot(i)); |
1161 | 28 | ParamID.append(":"); |
1162 | 28 | Fragments.appendSpace().append( |
1163 | 28 | ParamID, DeclarationFragments::FragmentKind::Identifier); |
1164 | | |
1165 | | // Build the internal parameter. |
1166 | 28 | const ParmVarDecl *Param = Method->getParamDecl(i); |
1167 | 28 | Fragments.append(getFragmentsForParam(Param)); |
1168 | 28 | } |
1169 | | |
1170 | 37 | return Fragments.append(";", DeclarationFragments::FragmentKind::Text); |
1171 | 37 | } |
1172 | | |
1173 | | DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty( |
1174 | 34 | const ObjCPropertyDecl *Property) { |
1175 | 34 | DeclarationFragments Fragments, After; |
1176 | | |
1177 | | // Build the Objective-C property keyword. |
1178 | 34 | Fragments.append("@property", DeclarationFragments::FragmentKind::Keyword); |
1179 | | |
1180 | 34 | const auto Attributes = Property->getPropertyAttributesAsWritten(); |
1181 | | // Build the attributes if there is any associated with the property. |
1182 | 34 | if (Attributes != ObjCPropertyAttribute::kind_noattr) { |
1183 | | // No leading comma for the first attribute. |
1184 | 6 | bool First = true; |
1185 | 6 | Fragments.append(" (", DeclarationFragments::FragmentKind::Text); |
1186 | | // Helper function to render the attribute. |
1187 | 6 | auto RenderAttribute = |
1188 | 6 | [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling, |
1189 | 6 | StringRef Arg = "", |
1190 | 6 | DeclarationFragments::FragmentKind ArgKind = |
1191 | 84 | DeclarationFragments::FragmentKind::Identifier) { |
1192 | | // Check if the `Kind` attribute is set for this property. |
1193 | 84 | if ((Attributes & Kind) && !Spelling.empty()8 ) { |
1194 | | // Add a leading comma if this is not the first attribute rendered. |
1195 | 8 | if (!First) |
1196 | 2 | Fragments.append(", ", DeclarationFragments::FragmentKind::Text); |
1197 | | // Render the spelling of this attribute `Kind` as a keyword. |
1198 | 8 | Fragments.append(Spelling, |
1199 | 8 | DeclarationFragments::FragmentKind::Keyword); |
1200 | | // If this attribute takes in arguments (e.g. `getter=getterName`), |
1201 | | // render the arguments. |
1202 | 8 | if (!Arg.empty()) |
1203 | 1 | Fragments.append("=", DeclarationFragments::FragmentKind::Text) |
1204 | 1 | .append(Arg, ArgKind); |
1205 | 8 | First = false; |
1206 | 8 | } |
1207 | 84 | }; |
1208 | | |
1209 | | // Go through all possible Objective-C property attributes and render set |
1210 | | // ones. |
1211 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_class, "class"); |
1212 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct"); |
1213 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic"); |
1214 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic"); |
1215 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign"); |
1216 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain"); |
1217 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong"); |
1218 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy"); |
1219 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak"); |
1220 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_unsafe_unretained, |
1221 | 6 | "unsafe_unretained"); |
1222 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite"); |
1223 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly"); |
1224 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter", |
1225 | 6 | Property->getGetterName().getAsString()); |
1226 | 6 | RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter", |
1227 | 6 | Property->getSetterName().getAsString()); |
1228 | | |
1229 | | // Render nullability attributes. |
1230 | 6 | if (Attributes & ObjCPropertyAttribute::kind_nullability) { |
1231 | 0 | QualType Type = Property->getType(); |
1232 | 0 | if (const auto Nullability = |
1233 | 0 | AttributedType::stripOuterNullability(Type)) { |
1234 | 0 | if (!First) |
1235 | 0 | Fragments.append(", ", DeclarationFragments::FragmentKind::Text); |
1236 | 0 | if (*Nullability == NullabilityKind::Unspecified && |
1237 | 0 | (Attributes & ObjCPropertyAttribute::kind_null_resettable)) |
1238 | 0 | Fragments.append("null_resettable", |
1239 | 0 | DeclarationFragments::FragmentKind::Keyword); |
1240 | 0 | else |
1241 | 0 | Fragments.append( |
1242 | 0 | getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true), |
1243 | 0 | DeclarationFragments::FragmentKind::Keyword); |
1244 | 0 | First = false; |
1245 | 0 | } |
1246 | 0 | } |
1247 | | |
1248 | 6 | Fragments.append(")", DeclarationFragments::FragmentKind::Text); |
1249 | 6 | } |
1250 | | |
1251 | | // Build the property type and name, and return the completed fragments. |
1252 | 34 | return Fragments.appendSpace() |
1253 | 34 | .append(getFragmentsForType(Property->getType(), |
1254 | 34 | Property->getASTContext(), After)) |
1255 | 34 | .appendSpace() |
1256 | 34 | .append(Property->getName(), |
1257 | 34 | DeclarationFragments::FragmentKind::Identifier) |
1258 | 34 | .append(std::move(After)); |
1259 | 34 | } |
1260 | | |
1261 | | DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol( |
1262 | 15 | const ObjCProtocolDecl *Protocol) { |
1263 | 15 | DeclarationFragments Fragments; |
1264 | | // Build basic protocol declaration. |
1265 | 15 | Fragments.append("@protocol", DeclarationFragments::FragmentKind::Keyword) |
1266 | 15 | .appendSpace() |
1267 | 15 | .append(Protocol->getName(), |
1268 | 15 | DeclarationFragments::FragmentKind::Identifier); |
1269 | | |
1270 | | // If this protocol conforms to other protocols, build the conformance list. |
1271 | 15 | if (!Protocol->protocols().empty()) { |
1272 | 1 | Fragments.append(" <", DeclarationFragments::FragmentKind::Text); |
1273 | 1 | for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin(); |
1274 | 2 | It != Protocol->protocol_end(); It++1 ) { |
1275 | | // Add a leading comma if this is not the first protocol rendered. |
1276 | 1 | if (It != Protocol->protocol_begin()) |
1277 | 0 | Fragments.append(", ", DeclarationFragments::FragmentKind::Text); |
1278 | | |
1279 | 1 | SmallString<128> USR; |
1280 | 1 | index::generateUSRForDecl(*It, USR); |
1281 | 1 | Fragments.append((*It)->getName(), |
1282 | 1 | DeclarationFragments::FragmentKind::TypeIdentifier, USR, |
1283 | 1 | *It); |
1284 | 1 | } |
1285 | 1 | Fragments.append(">", DeclarationFragments::FragmentKind::Text); |
1286 | 1 | } |
1287 | | |
1288 | 15 | return Fragments; |
1289 | 15 | } |
1290 | | |
1291 | | DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef( |
1292 | 24 | const TypedefNameDecl *Decl) { |
1293 | 24 | DeclarationFragments Fragments, After; |
1294 | 24 | Fragments.append("typedef", DeclarationFragments::FragmentKind::Keyword) |
1295 | 24 | .appendSpace() |
1296 | 24 | .append(getFragmentsForType(Decl->getUnderlyingType(), |
1297 | 24 | Decl->getASTContext(), After)) |
1298 | 24 | .append(std::move(After)) |
1299 | 24 | .appendSpace() |
1300 | 24 | .append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); |
1301 | | |
1302 | 24 | return Fragments.append(";", DeclarationFragments::FragmentKind::Text); |
1303 | 24 | } |
1304 | | |
1305 | | // Instantiate template for FunctionDecl. |
1306 | | template FunctionSignature |
1307 | | DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *); |
1308 | | |
1309 | | // Instantiate template for ObjCMethodDecl. |
1310 | | template FunctionSignature |
1311 | | DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *); |
1312 | | |
1313 | | // Subheading of a symbol defaults to its name. |
1314 | | DeclarationFragments |
1315 | 265 | DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { |
1316 | 265 | DeclarationFragments Fragments; |
1317 | 265 | if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl)264 ) |
1318 | 2 | Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(), |
1319 | 2 | DeclarationFragments::FragmentKind::Identifier); |
1320 | 263 | else if (isa<CXXConversionDecl>(Decl)) { |
1321 | 2 | Fragments.append( |
1322 | 2 | cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(), |
1323 | 2 | DeclarationFragments::FragmentKind::Identifier); |
1324 | 261 | } else if (isa<CXXMethodDecl>(Decl) && |
1325 | 261 | cast<CXXMethodDecl>(Decl)->isOverloadedOperator()8 ) { |
1326 | 1 | Fragments.append(Decl->getNameAsString(), |
1327 | 1 | DeclarationFragments::FragmentKind::Identifier); |
1328 | 260 | } else if (!Decl->getName().empty()) |
1329 | 254 | Fragments.append(Decl->getName(), |
1330 | 254 | DeclarationFragments::FragmentKind::Identifier); |
1331 | 265 | return Fragments; |
1332 | 265 | } |
1333 | | |
1334 | | // Subheading of an Objective-C method is a `+` or `-` sign indicating whether |
1335 | | // it's a class method or an instance method, followed by the selector name. |
1336 | | DeclarationFragments |
1337 | 37 | DeclarationFragmentsBuilder::getSubHeading(const ObjCMethodDecl *Method) { |
1338 | 37 | DeclarationFragments Fragments; |
1339 | 37 | if (Method->isClassMethod()) |
1340 | 2 | Fragments.append("+ ", DeclarationFragments::FragmentKind::Text); |
1341 | 35 | else if (Method->isInstanceMethod()) |
1342 | 35 | Fragments.append("- ", DeclarationFragments::FragmentKind::Text); |
1343 | | |
1344 | 37 | return Fragments.append(Method->getNameAsString(), |
1345 | 37 | DeclarationFragments::FragmentKind::Identifier); |
1346 | 37 | } |
1347 | | |
1348 | | // Subheading of a symbol defaults to its name. |
1349 | | DeclarationFragments |
1350 | 24 | DeclarationFragmentsBuilder::getSubHeadingForMacro(StringRef Name) { |
1351 | 24 | DeclarationFragments Fragments; |
1352 | 24 | Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); |
1353 | 24 | return Fragments; |
1354 | 24 | } |