/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Sema/CodeCompleteConsumer.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- CodeCompleteConsumer.cpp - Code Completion Interface ---------------===// |
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 | | // This file implements the CodeCompleteConsumer class. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "clang/Sema/CodeCompleteConsumer.h" |
14 | | #include "clang-c/Index.h" |
15 | | #include "clang/AST/Decl.h" |
16 | | #include "clang/AST/DeclBase.h" |
17 | | #include "clang/AST/DeclObjC.h" |
18 | | #include "clang/AST/DeclTemplate.h" |
19 | | #include "clang/AST/DeclarationName.h" |
20 | | #include "clang/AST/Type.h" |
21 | | #include "clang/Basic/IdentifierTable.h" |
22 | | #include "clang/Lex/Preprocessor.h" |
23 | | #include "clang/Sema/Sema.h" |
24 | | #include "llvm/ADT/SmallString.h" |
25 | | #include "llvm/ADT/SmallVector.h" |
26 | | #include "llvm/ADT/StringExtras.h" |
27 | | #include "llvm/ADT/StringRef.h" |
28 | | #include "llvm/ADT/Twine.h" |
29 | | #include "llvm/Support/Casting.h" |
30 | | #include "llvm/Support/Compiler.h" |
31 | | #include "llvm/Support/ErrorHandling.h" |
32 | | #include "llvm/Support/FormatVariadic.h" |
33 | | #include "llvm/Support/raw_ostream.h" |
34 | | #include <algorithm> |
35 | | #include <cassert> |
36 | | #include <cstdint> |
37 | | #include <string> |
38 | | |
39 | | using namespace clang; |
40 | | |
41 | | //===----------------------------------------------------------------------===// |
42 | | // Code completion context implementation |
43 | | //===----------------------------------------------------------------------===// |
44 | | |
45 | 5.33k | bool CodeCompletionContext::wantConstructorResults() const { |
46 | 5.33k | switch (CCKind) { |
47 | 109 | case CCC_Recovery: |
48 | 1.16k | case CCC_Statement: |
49 | 4.01k | case CCC_Expression: |
50 | 4.03k | case CCC_ObjCMessageReceiver: |
51 | 4.13k | case CCC_ParenthesizedExpression: |
52 | 4.40k | case CCC_Symbol: |
53 | 4.40k | case CCC_SymbolOrNewName: |
54 | 4.40k | return true; |
55 | | |
56 | 20 | case CCC_TopLevel: |
57 | 20 | case CCC_ObjCInterface: |
58 | 20 | case CCC_ObjCImplementation: |
59 | 20 | case CCC_ObjCIvarList: |
60 | 46 | case CCC_ClassStructUnion: |
61 | 676 | case CCC_DotMemberAccess: |
62 | 885 | case CCC_ArrowMemberAccess: |
63 | 885 | case CCC_ObjCPropertyAccess: |
64 | 885 | case CCC_EnumTag: |
65 | 885 | case CCC_UnionTag: |
66 | 892 | case CCC_ClassOrStructTag: |
67 | 892 | case CCC_ObjCProtocolName: |
68 | 902 | case CCC_Namespace: |
69 | 905 | case CCC_Type: |
70 | 905 | case CCC_NewName: |
71 | 905 | case CCC_MacroName: |
72 | 905 | case CCC_MacroNameUse: |
73 | 905 | case CCC_PreprocessorExpression: |
74 | 905 | case CCC_PreprocessorDirective: |
75 | 905 | case CCC_NaturalLanguage: |
76 | 905 | case CCC_SelectorName: |
77 | 905 | case CCC_TypeQualifiers: |
78 | 920 | case CCC_Other: |
79 | 920 | case CCC_OtherWithMacros: |
80 | 929 | case CCC_ObjCInstanceMessage: |
81 | 931 | case CCC_ObjCClassMessage: |
82 | 931 | case CCC_ObjCInterfaceName: |
83 | 931 | case CCC_ObjCCategoryName: |
84 | 931 | case CCC_IncludedFile: |
85 | 931 | case CCC_Attribute: |
86 | 931 | return false; |
87 | 5.33k | } |
88 | | |
89 | 0 | llvm_unreachable("Invalid CodeCompletionContext::Kind!"); |
90 | 0 | } |
91 | | |
92 | 0 | StringRef clang::getCompletionKindString(CodeCompletionContext::Kind Kind) { |
93 | 0 | using CCKind = CodeCompletionContext::Kind; |
94 | 0 | switch (Kind) { |
95 | 0 | case CCKind::CCC_Other: |
96 | 0 | return "Other"; |
97 | 0 | case CCKind::CCC_OtherWithMacros: |
98 | 0 | return "OtherWithMacros"; |
99 | 0 | case CCKind::CCC_TopLevel: |
100 | 0 | return "TopLevel"; |
101 | 0 | case CCKind::CCC_ObjCInterface: |
102 | 0 | return "ObjCInterface"; |
103 | 0 | case CCKind::CCC_ObjCImplementation: |
104 | 0 | return "ObjCImplementation"; |
105 | 0 | case CCKind::CCC_ObjCIvarList: |
106 | 0 | return "ObjCIvarList"; |
107 | 0 | case CCKind::CCC_ClassStructUnion: |
108 | 0 | return "ClassStructUnion"; |
109 | 0 | case CCKind::CCC_Statement: |
110 | 0 | return "Statement"; |
111 | 0 | case CCKind::CCC_Expression: |
112 | 0 | return "Expression"; |
113 | 0 | case CCKind::CCC_ObjCMessageReceiver: |
114 | 0 | return "ObjCMessageReceiver"; |
115 | 0 | case CCKind::CCC_DotMemberAccess: |
116 | 0 | return "DotMemberAccess"; |
117 | 0 | case CCKind::CCC_ArrowMemberAccess: |
118 | 0 | return "ArrowMemberAccess"; |
119 | 0 | case CCKind::CCC_ObjCPropertyAccess: |
120 | 0 | return "ObjCPropertyAccess"; |
121 | 0 | case CCKind::CCC_EnumTag: |
122 | 0 | return "EnumTag"; |
123 | 0 | case CCKind::CCC_UnionTag: |
124 | 0 | return "UnionTag"; |
125 | 0 | case CCKind::CCC_ClassOrStructTag: |
126 | 0 | return "ClassOrStructTag"; |
127 | 0 | case CCKind::CCC_ObjCProtocolName: |
128 | 0 | return "ObjCProtocolName"; |
129 | 0 | case CCKind::CCC_Namespace: |
130 | 0 | return "Namespace"; |
131 | 0 | case CCKind::CCC_Type: |
132 | 0 | return "Type"; |
133 | 0 | case CCKind::CCC_NewName: |
134 | 0 | return "NewName"; |
135 | 0 | case CCKind::CCC_Symbol: |
136 | 0 | return "Symbol"; |
137 | 0 | case CCKind::CCC_SymbolOrNewName: |
138 | 0 | return "SymbolOrNewName"; |
139 | 0 | case CCKind::CCC_MacroName: |
140 | 0 | return "MacroName"; |
141 | 0 | case CCKind::CCC_MacroNameUse: |
142 | 0 | return "MacroNameUse"; |
143 | 0 | case CCKind::CCC_PreprocessorExpression: |
144 | 0 | return "PreprocessorExpression"; |
145 | 0 | case CCKind::CCC_PreprocessorDirective: |
146 | 0 | return "PreprocessorDirective"; |
147 | 0 | case CCKind::CCC_NaturalLanguage: |
148 | 0 | return "NaturalLanguage"; |
149 | 0 | case CCKind::CCC_SelectorName: |
150 | 0 | return "SelectorName"; |
151 | 0 | case CCKind::CCC_TypeQualifiers: |
152 | 0 | return "TypeQualifiers"; |
153 | 0 | case CCKind::CCC_ParenthesizedExpression: |
154 | 0 | return "ParenthesizedExpression"; |
155 | 0 | case CCKind::CCC_ObjCInstanceMessage: |
156 | 0 | return "ObjCInstanceMessage"; |
157 | 0 | case CCKind::CCC_ObjCClassMessage: |
158 | 0 | return "ObjCClassMessage"; |
159 | 0 | case CCKind::CCC_ObjCInterfaceName: |
160 | 0 | return "ObjCInterfaceName"; |
161 | 0 | case CCKind::CCC_ObjCCategoryName: |
162 | 0 | return "ObjCCategoryName"; |
163 | 0 | case CCKind::CCC_IncludedFile: |
164 | 0 | return "IncludedFile"; |
165 | 0 | case CCKind::CCC_Attribute: |
166 | 0 | return "Attribute"; |
167 | 0 | case CCKind::CCC_Recovery: |
168 | 0 | return "Recovery"; |
169 | 0 | } |
170 | 0 | llvm_unreachable("Invalid CodeCompletionContext::Kind!"); |
171 | 0 | } |
172 | | |
173 | | //===----------------------------------------------------------------------===// |
174 | | // Code completion string implementation |
175 | | //===----------------------------------------------------------------------===// |
176 | | |
177 | | CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) |
178 | 251k | : Kind(Kind), Text("") { |
179 | 251k | switch (Kind) { |
180 | 179k | case CK_TypedText: |
181 | 181k | case CK_Text: |
182 | 201k | case CK_Placeholder: |
183 | 202k | case CK_Informative: |
184 | 212k | case CK_ResultType: |
185 | 212k | case CK_CurrentParameter: |
186 | 212k | this->Text = Text; |
187 | 212k | break; |
188 | | |
189 | 0 | case CK_Optional: |
190 | 0 | llvm_unreachable("Optional strings cannot be created from text"); |
191 | |
|
192 | 11.9k | case CK_LeftParen: |
193 | 11.9k | this->Text = "("; |
194 | 11.9k | break; |
195 | | |
196 | 12.0k | case CK_RightParen: |
197 | 12.0k | this->Text = ")"; |
198 | 12.0k | break; |
199 | | |
200 | 864 | case CK_LeftBracket: |
201 | 864 | this->Text = "["; |
202 | 864 | break; |
203 | | |
204 | 969 | case CK_RightBracket: |
205 | 969 | this->Text = "]"; |
206 | 969 | break; |
207 | | |
208 | 204 | case CK_LeftBrace: |
209 | 204 | this->Text = "{"; |
210 | 204 | break; |
211 | | |
212 | 309 | case CK_RightBrace: |
213 | 309 | this->Text = "}"; |
214 | 309 | break; |
215 | | |
216 | 2.00k | case CK_LeftAngle: |
217 | 2.00k | this->Text = "<"; |
218 | 2.00k | break; |
219 | | |
220 | 2.00k | case CK_RightAngle: |
221 | 2.00k | this->Text = ">"; |
222 | 2.00k | break; |
223 | | |
224 | 2.13k | case CK_Comma: |
225 | 2.13k | this->Text = ", "; |
226 | 2.13k | break; |
227 | | |
228 | 130 | case CK_Colon: |
229 | 130 | this->Text = ":"; |
230 | 130 | break; |
231 | | |
232 | 1.04k | case CK_SemiColon: |
233 | 1.04k | this->Text = ";"; |
234 | 1.04k | break; |
235 | | |
236 | 167 | case CK_Equal: |
237 | 167 | this->Text = " = "; |
238 | 167 | break; |
239 | | |
240 | 5.26k | case CK_HorizontalSpace: |
241 | 5.26k | this->Text = " "; |
242 | 5.26k | break; |
243 | | |
244 | 314 | case CK_VerticalSpace: |
245 | 314 | this->Text = "\n"; |
246 | 314 | break; |
247 | 251k | } |
248 | 251k | } |
249 | | |
250 | | CodeCompletionString::Chunk |
251 | 1.88k | CodeCompletionString::Chunk::CreateText(const char *Text) { |
252 | 1.88k | return Chunk(CK_Text, Text); |
253 | 1.88k | } |
254 | | |
255 | | CodeCompletionString::Chunk |
256 | 113 | CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) { |
257 | 113 | Chunk Result; |
258 | 113 | Result.Kind = CK_Optional; |
259 | 113 | Result.Optional = Optional; |
260 | 113 | return Result; |
261 | 113 | } |
262 | | |
263 | | CodeCompletionString::Chunk |
264 | 20.2k | CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) { |
265 | 20.2k | return Chunk(CK_Placeholder, Placeholder); |
266 | 20.2k | } |
267 | | |
268 | | CodeCompletionString::Chunk |
269 | 233 | CodeCompletionString::Chunk::CreateInformative(const char *Informative) { |
270 | 233 | return Chunk(CK_Informative, Informative); |
271 | 233 | } |
272 | | |
273 | | CodeCompletionString::Chunk |
274 | 9.85k | CodeCompletionString::Chunk::CreateResultType(const char *ResultType) { |
275 | 9.85k | return Chunk(CK_ResultType, ResultType); |
276 | 9.85k | } |
277 | | |
278 | | CodeCompletionString::Chunk CodeCompletionString::Chunk::CreateCurrentParameter( |
279 | 251 | const char *CurrentParameter) { |
280 | 251 | return Chunk(CK_CurrentParameter, CurrentParameter); |
281 | 251 | } |
282 | | |
283 | | CodeCompletionString::CodeCompletionString( |
284 | | const Chunk *Chunks, unsigned NumChunks, unsigned Priority, |
285 | | CXAvailabilityKind Availability, const char **Annotations, |
286 | | unsigned NumAnnotations, StringRef ParentName, const char *BriefComment) |
287 | | : NumChunks(NumChunks), NumAnnotations(NumAnnotations), Priority(Priority), |
288 | | Availability(Availability), ParentName(ParentName), |
289 | 180k | BriefComment(BriefComment) { |
290 | 180k | assert(NumChunks <= 0xffff); |
291 | 0 | assert(NumAnnotations <= 0xffff); |
292 | | |
293 | 0 | Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1); |
294 | 431k | for (unsigned I = 0; I != NumChunks; ++I251k ) |
295 | 251k | StoredChunks[I] = Chunks[I]; |
296 | | |
297 | 180k | const char **StoredAnnotations = |
298 | 180k | reinterpret_cast<const char **>(StoredChunks + NumChunks); |
299 | 180k | for (unsigned I = 0; I != NumAnnotations; ++I6 ) |
300 | 6 | StoredAnnotations[I] = Annotations[I]; |
301 | 180k | } |
302 | | |
303 | 121k | unsigned CodeCompletionString::getAnnotationCount() const { |
304 | 121k | return NumAnnotations; |
305 | 121k | } |
306 | | |
307 | 6 | const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const { |
308 | 6 | if (AnnotationNr < NumAnnotations) |
309 | 6 | return reinterpret_cast<const char *const *>(end())[AnnotationNr]; |
310 | 0 | else |
311 | 0 | return nullptr; |
312 | 6 | } |
313 | | |
314 | 10.5k | std::string CodeCompletionString::getAsString() const { |
315 | 10.5k | std::string Result; |
316 | 10.5k | llvm::raw_string_ostream OS(Result); |
317 | | |
318 | 31.2k | for (const Chunk &C : *this) { |
319 | 31.2k | switch (C.Kind) { |
320 | 26 | case CK_Optional: |
321 | 26 | OS << "{#" << C.Optional->getAsString() << "#}"; |
322 | 26 | break; |
323 | 6.10k | case CK_Placeholder: |
324 | 6.10k | OS << "<#" << C.Text << "#>"; |
325 | 6.10k | break; |
326 | 82 | case CK_Informative: |
327 | 2.20k | case CK_ResultType: |
328 | 2.20k | OS << "[#" << C.Text << "#]"; |
329 | 2.20k | break; |
330 | 0 | case CK_CurrentParameter: |
331 | 0 | OS << "<#" << C.Text << "#>"; |
332 | 0 | break; |
333 | 22.9k | default: |
334 | 22.9k | OS << C.Text; |
335 | 22.9k | break; |
336 | 31.2k | } |
337 | 31.2k | } |
338 | 10.5k | return Result; |
339 | 10.5k | } |
340 | | |
341 | 223k | const char *CodeCompletionString::getTypedText() const { |
342 | 223k | for (const Chunk &C : *this) |
343 | 234k | if (C.Kind == CK_TypedText) |
344 | 223k | return C.Text; |
345 | | |
346 | 73 | return nullptr; |
347 | 223k | } |
348 | | |
349 | 0 | std::string CodeCompletionString::getAllTypedText() const { |
350 | 0 | std::string Res; |
351 | 0 | for (const Chunk &C : *this) |
352 | 0 | if (C.Kind == CK_TypedText) |
353 | 0 | Res += C.Text; |
354 | |
|
355 | 0 | return Res; |
356 | 0 | } |
357 | | |
358 | 166k | const char *CodeCompletionAllocator::CopyString(const Twine &String) { |
359 | 166k | SmallString<128> Data; |
360 | 166k | StringRef Ref = String.toStringRef(Data); |
361 | | // FIXME: It would be more efficient to teach Twine to tell us its size and |
362 | | // then add a routine there to fill in an allocated char* with the contents |
363 | | // of the string. |
364 | 166k | char *Mem = (char *)Allocate(Ref.size() + 1, 1); |
365 | 166k | std::copy(Ref.begin(), Ref.end(), Mem); |
366 | 166k | Mem[Ref.size()] = 0; |
367 | 166k | return Mem; |
368 | 166k | } |
369 | | |
370 | 2.24k | StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { |
371 | 2.24k | if (!isa<NamedDecl>(DC)) |
372 | 0 | return {}; |
373 | | |
374 | | // Check whether we've already cached the parent name. |
375 | 2.24k | StringRef &CachedParentName = ParentNames[DC]; |
376 | 2.24k | if (!CachedParentName.empty()) |
377 | 1.51k | return CachedParentName; |
378 | | |
379 | | // If we already processed this DeclContext and assigned empty to it, the |
380 | | // data pointer will be non-null. |
381 | 730 | if (CachedParentName.data() != nullptr) |
382 | 10 | return {}; |
383 | | |
384 | | // Find the interesting names. |
385 | 720 | SmallVector<const DeclContext *, 2> Contexts; |
386 | 2.18k | while (DC && !DC->isFunctionOrMethod()1.47k ) { |
387 | 1.46k | if (const auto *ND = dyn_cast<NamedDecl>(DC)) { |
388 | 750 | if (ND->getIdentifier()) |
389 | 726 | Contexts.push_back(DC); |
390 | 750 | } |
391 | | |
392 | 1.46k | DC = DC->getParent(); |
393 | 1.46k | } |
394 | | |
395 | 720 | { |
396 | 720 | SmallString<128> S; |
397 | 720 | llvm::raw_svector_ostream OS(S); |
398 | 720 | bool First = true; |
399 | 726 | for (const DeclContext *CurDC : llvm::reverse(Contexts)) { |
400 | 726 | if (First) |
401 | 701 | First = false; |
402 | 25 | else { |
403 | 25 | OS << "::"; |
404 | 25 | } |
405 | | |
406 | 726 | if (const auto *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC)) |
407 | 0 | CurDC = CatImpl->getCategoryDecl(); |
408 | | |
409 | 726 | if (const auto *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) { |
410 | 17 | const ObjCInterfaceDecl *Interface = Cat->getClassInterface(); |
411 | 17 | if (!Interface) { |
412 | | // Assign an empty StringRef but with non-null data to distinguish |
413 | | // between empty because we didn't process the DeclContext yet. |
414 | 0 | CachedParentName = StringRef((const char *)(uintptr_t)~0U, 0); |
415 | 0 | return {}; |
416 | 0 | } |
417 | | |
418 | 17 | OS << Interface->getName() << '(' << Cat->getName() << ')'; |
419 | 709 | } else { |
420 | 709 | OS << cast<NamedDecl>(CurDC)->getName(); |
421 | 709 | } |
422 | 726 | } |
423 | | |
424 | 720 | CachedParentName = AllocatorRef->CopyString(OS.str()); |
425 | 720 | } |
426 | | |
427 | 0 | return CachedParentName; |
428 | 720 | } |
429 | | |
430 | 180k | CodeCompletionString *CodeCompletionBuilder::TakeString() { |
431 | 180k | void *Mem = getAllocator().Allocate( |
432 | 180k | sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() + |
433 | 180k | sizeof(const char *) * Annotations.size(), |
434 | 180k | alignof(CodeCompletionString)); |
435 | 180k | CodeCompletionString *Result = new (Mem) CodeCompletionString( |
436 | 180k | Chunks.data(), Chunks.size(), Priority, Availability, Annotations.data(), |
437 | 180k | Annotations.size(), ParentName, BriefComment); |
438 | 180k | Chunks.clear(); |
439 | 180k | return Result; |
440 | 180k | } |
441 | | |
442 | 179k | void CodeCompletionBuilder::AddTypedTextChunk(const char *Text) { |
443 | 179k | Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text)); |
444 | 179k | } |
445 | | |
446 | 1.88k | void CodeCompletionBuilder::AddTextChunk(const char *Text) { |
447 | 1.88k | Chunks.push_back(Chunk::CreateText(Text)); |
448 | 1.88k | } |
449 | | |
450 | 113 | void CodeCompletionBuilder::AddOptionalChunk(CodeCompletionString *Optional) { |
451 | 113 | Chunks.push_back(Chunk::CreateOptional(Optional)); |
452 | 113 | } |
453 | | |
454 | 20.2k | void CodeCompletionBuilder::AddPlaceholderChunk(const char *Placeholder) { |
455 | 20.2k | Chunks.push_back(Chunk::CreatePlaceholder(Placeholder)); |
456 | 20.2k | } |
457 | | |
458 | 233 | void CodeCompletionBuilder::AddInformativeChunk(const char *Text) { |
459 | 233 | Chunks.push_back(Chunk::CreateInformative(Text)); |
460 | 233 | } |
461 | | |
462 | 9.85k | void CodeCompletionBuilder::AddResultTypeChunk(const char *ResultType) { |
463 | 9.85k | Chunks.push_back(Chunk::CreateResultType(ResultType)); |
464 | 9.85k | } |
465 | | |
466 | | void CodeCompletionBuilder::AddCurrentParameterChunk( |
467 | 251 | const char *CurrentParameter) { |
468 | 251 | Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter)); |
469 | 251 | } |
470 | | |
471 | | void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK, |
472 | 39.4k | const char *Text) { |
473 | 39.4k | Chunks.push_back(Chunk(CK, Text)); |
474 | 39.4k | } |
475 | | |
476 | 5.89k | void CodeCompletionBuilder::addParentContext(const DeclContext *DC) { |
477 | 5.89k | if (DC->isTranslationUnit()) |
478 | 3.19k | return; |
479 | | |
480 | 2.70k | if (DC->isFunctionOrMethod()) |
481 | 458 | return; |
482 | | |
483 | 2.24k | if (!isa<NamedDecl>(DC)) |
484 | 0 | return; |
485 | | |
486 | 2.24k | ParentName = getCodeCompletionTUInfo().getParentName(DC); |
487 | 2.24k | } |
488 | | |
489 | 118 | void CodeCompletionBuilder::addBriefComment(StringRef Comment) { |
490 | 118 | BriefComment = Allocator.CopyString(Comment); |
491 | 118 | } |
492 | | |
493 | | //===----------------------------------------------------------------------===// |
494 | | // Code completion overload candidate implementation |
495 | | //===----------------------------------------------------------------------===// |
496 | 275 | FunctionDecl *CodeCompleteConsumer::OverloadCandidate::getFunction() const { |
497 | 275 | if (getKind() == CK_Function) |
498 | 263 | return Function; |
499 | 12 | else if (getKind() == CK_FunctionTemplate) |
500 | 0 | return FunctionTemplate->getTemplatedDecl(); |
501 | 12 | else |
502 | 12 | return nullptr; |
503 | 275 | } |
504 | | |
505 | | const FunctionType * |
506 | 585 | CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { |
507 | 585 | switch (Kind) { |
508 | 563 | case CK_Function: |
509 | 563 | return Function->getType()->getAs<FunctionType>(); |
510 | | |
511 | 0 | case CK_FunctionTemplate: |
512 | 0 | return FunctionTemplate->getTemplatedDecl() |
513 | 0 | ->getType() |
514 | 0 | ->getAs<FunctionType>(); |
515 | | |
516 | 15 | case CK_FunctionType: |
517 | 15 | return Type; |
518 | | |
519 | 0 | case CK_Template: |
520 | 7 | case CK_Aggregate: |
521 | 7 | return nullptr; |
522 | 585 | } |
523 | | |
524 | 0 | llvm_unreachable("Invalid CandidateKind!"); |
525 | 0 | } |
526 | | |
527 | 10 | unsigned CodeCompleteConsumer::OverloadCandidate::getNumParams() const { |
528 | 10 | if (Kind == CK_Template) |
529 | 0 | return Template->getTemplateParameters()->size(); |
530 | | |
531 | 10 | if (Kind == CK_Aggregate) { |
532 | 10 | unsigned Count = |
533 | 10 | std::distance(AggregateType->field_begin(), AggregateType->field_end()); |
534 | 10 | if (const auto *CRD = dyn_cast<CXXRecordDecl>(AggregateType)) |
535 | 10 | Count += CRD->getNumBases(); |
536 | 10 | return Count; |
537 | 10 | } |
538 | | |
539 | 0 | if (const auto *FT = getFunctionType()) |
540 | 0 | if (const auto *FPT = dyn_cast<FunctionProtoType>(FT)) |
541 | 0 | return FPT->getNumParams(); |
542 | | |
543 | 0 | return 0; |
544 | 0 | } |
545 | | |
546 | | QualType |
547 | 319 | CodeCompleteConsumer::OverloadCandidate::getParamType(unsigned N) const { |
548 | 319 | if (Kind == CK_Aggregate) { |
549 | 7 | if (const auto *CRD = dyn_cast<CXXRecordDecl>(AggregateType)) { |
550 | 7 | if (N < CRD->getNumBases()) |
551 | 0 | return std::next(CRD->bases_begin(), N)->getType(); |
552 | 7 | N -= CRD->getNumBases(); |
553 | 7 | } |
554 | 7 | for (const auto *Field : AggregateType->fields()) |
555 | 15 | if (N-- == 0) |
556 | 7 | return Field->getType(); |
557 | 0 | return QualType(); |
558 | 7 | } |
559 | | |
560 | 312 | if (Kind == CK_Template) { |
561 | 7 | TemplateParameterList *TPL = getTemplate()->getTemplateParameters(); |
562 | 7 | if (N < TPL->size()) |
563 | 6 | if (const auto *D = dyn_cast<NonTypeTemplateParmDecl>(TPL->getParam(N))) |
564 | 3 | return D->getType(); |
565 | 4 | return QualType(); |
566 | 7 | } |
567 | | |
568 | 305 | if (const auto *FT = getFunctionType()) |
569 | 305 | if (const auto *FPT = dyn_cast<FunctionProtoType>(FT)) |
570 | 304 | if (N < FPT->getNumParams()) |
571 | 275 | return FPT->getParamType(N); |
572 | 30 | return QualType(); |
573 | 305 | } |
574 | | |
575 | | const NamedDecl * |
576 | 3 | CodeCompleteConsumer::OverloadCandidate::getParamDecl(unsigned N) const { |
577 | 3 | if (Kind == CK_Aggregate) { |
578 | 3 | if (const auto *CRD = dyn_cast<CXXRecordDecl>(AggregateType)) { |
579 | 3 | if (N < CRD->getNumBases()) |
580 | 0 | return std::next(CRD->bases_begin(), N)->getType()->getAsTagDecl(); |
581 | 3 | N -= CRD->getNumBases(); |
582 | 3 | } |
583 | 3 | for (const auto *Field : AggregateType->fields()) |
584 | 4 | if (N-- == 0) |
585 | 3 | return Field; |
586 | 0 | return nullptr; |
587 | 3 | } |
588 | | |
589 | 0 | if (Kind == CK_Template) { |
590 | 0 | TemplateParameterList *TPL = getTemplate()->getTemplateParameters(); |
591 | 0 | if (N < TPL->size()) |
592 | 0 | return TPL->getParam(N); |
593 | 0 | return nullptr; |
594 | 0 | } |
595 | | |
596 | | // Note that if we only have a FunctionProtoType, we don't have param decls. |
597 | 0 | if (const auto *FD = getFunction()) { |
598 | 0 | if (N < FD->param_size()) |
599 | 0 | return FD->getParamDecl(N); |
600 | 0 | } |
601 | 0 | return nullptr; |
602 | 0 | } |
603 | | |
604 | | //===----------------------------------------------------------------------===// |
605 | | // Code completion consumer implementation |
606 | | //===----------------------------------------------------------------------===// |
607 | | |
608 | 1.99k | CodeCompleteConsumer::~CodeCompleteConsumer() = default; |
609 | | |
610 | | bool PrintingCodeCompleteConsumer::isResultFilteredOut( |
611 | 7.46k | StringRef Filter, CodeCompletionResult Result) { |
612 | 7.46k | switch (Result.Kind) { |
613 | 32 | case CodeCompletionResult::RK_Declaration: |
614 | 32 | return !(Result.Declaration->getIdentifier() && |
615 | 32 | Result.Declaration->getIdentifier()->getName().startswith(Filter)); |
616 | 405 | case CodeCompletionResult::RK_Keyword: |
617 | 405 | return !StringRef(Result.Keyword).startswith(Filter); |
618 | 828 | case CodeCompletionResult::RK_Macro: |
619 | 828 | return !Result.Macro->getName().startswith(Filter); |
620 | 6.19k | case CodeCompletionResult::RK_Pattern: |
621 | 6.19k | return !(Result.Pattern->getTypedText() && |
622 | 6.19k | StringRef(Result.Pattern->getTypedText()).startswith(Filter)); |
623 | 7.46k | } |
624 | 0 | llvm_unreachable("Unknown code completion result Kind."); |
625 | 0 | } |
626 | | |
627 | | void PrintingCodeCompleteConsumer::ProcessCodeCompleteResults( |
628 | | Sema &SemaRef, CodeCompletionContext Context, CodeCompletionResult *Results, |
629 | 316 | unsigned NumResults) { |
630 | 316 | std::stable_sort(Results, Results + NumResults); |
631 | | |
632 | 316 | if (!Context.getPreferredType().isNull()) |
633 | 56 | OS << "PREFERRED-TYPE: " << Context.getPreferredType() << '\n'; |
634 | | |
635 | 316 | StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter(); |
636 | | // Print the completions. |
637 | 21.2k | for (unsigned I = 0; I != NumResults; ++I20.9k ) { |
638 | 20.9k | if (!Filter.empty() && isResultFilteredOut(Filter, Results[I])7.46k ) |
639 | 7.39k | continue; |
640 | 13.5k | OS << "COMPLETION: "; |
641 | 13.5k | switch (Results[I].Kind) { |
642 | 1.45k | case CodeCompletionResult::RK_Declaration: |
643 | 1.45k | OS << *Results[I].Declaration; |
644 | 1.45k | { |
645 | 1.45k | std::vector<std::string> Tags; |
646 | 1.45k | if (Results[I].Hidden) |
647 | 105 | Tags.push_back("Hidden"); |
648 | 1.45k | if (Results[I].InBaseClass) |
649 | 162 | Tags.push_back("InBase"); |
650 | 1.45k | if (Results[I].Availability == |
651 | 1.45k | CXAvailabilityKind::CXAvailability_NotAccessible) |
652 | 33 | Tags.push_back("Inaccessible"); |
653 | 1.45k | if (!Tags.empty()) |
654 | 229 | OS << " (" << llvm::join(Tags, ",") << ")"; |
655 | 1.45k | } |
656 | 1.45k | if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString( |
657 | 1.45k | SemaRef, Context, getAllocator(), CCTUInfo, |
658 | 1.45k | includeBriefComments())) { |
659 | 1.45k | OS << " : " << CCS->getAsString(); |
660 | 1.45k | if (const char *BriefComment = CCS->getBriefComment()) |
661 | 9 | OS << " : " << BriefComment; |
662 | 1.45k | } |
663 | 1.45k | break; |
664 | | |
665 | 3.41k | case CodeCompletionResult::RK_Keyword: |
666 | 3.41k | OS << Results[I].Keyword; |
667 | 3.41k | break; |
668 | | |
669 | 1.56k | case CodeCompletionResult::RK_Macro: |
670 | 1.56k | OS << Results[I].Macro->getName(); |
671 | 1.56k | if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString( |
672 | 1.56k | SemaRef, Context, getAllocator(), CCTUInfo, |
673 | 1.56k | includeBriefComments())) { |
674 | 1.56k | OS << " : " << CCS->getAsString(); |
675 | 1.56k | } |
676 | 1.56k | break; |
677 | | |
678 | 7.09k | case CodeCompletionResult::RK_Pattern: |
679 | 7.09k | OS << "Pattern : " << Results[I].Pattern->getAsString(); |
680 | 7.09k | break; |
681 | 13.5k | } |
682 | 13.5k | for (const FixItHint &FixIt : Results[I].FixIts) { |
683 | 38 | const SourceLocation BLoc = FixIt.RemoveRange.getBegin(); |
684 | 38 | const SourceLocation ELoc = FixIt.RemoveRange.getEnd(); |
685 | | |
686 | 38 | SourceManager &SM = SemaRef.SourceMgr; |
687 | 38 | std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc); |
688 | 38 | std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc); |
689 | | // Adjust for token ranges. |
690 | 38 | if (FixIt.RemoveRange.isTokenRange()) |
691 | 38 | EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, SemaRef.LangOpts); |
692 | | |
693 | 38 | OS << " (requires fix-it:" |
694 | 38 | << " {" << SM.getLineNumber(BInfo.first, BInfo.second) << ':' |
695 | 38 | << SM.getColumnNumber(BInfo.first, BInfo.second) << '-' |
696 | 38 | << SM.getLineNumber(EInfo.first, EInfo.second) << ':' |
697 | 38 | << SM.getColumnNumber(EInfo.first, EInfo.second) << "}" |
698 | 38 | << " to \"" << FixIt.CodeToInsert << "\")"; |
699 | 38 | } |
700 | 13.5k | OS << '\n'; |
701 | 13.5k | } |
702 | 316 | } |
703 | | |
704 | | // This function is used solely to preserve the former presentation of overloads |
705 | | // by "clang -cc1 -code-completion-at", since CodeCompletionString::getAsString |
706 | | // needs to be improved for printing the newer and more detailed overload |
707 | | // chunks. |
708 | 119 | static std::string getOverloadAsString(const CodeCompletionString &CCS) { |
709 | 119 | std::string Result; |
710 | 119 | llvm::raw_string_ostream OS(Result); |
711 | | |
712 | 697 | for (auto &C : CCS) { |
713 | 697 | switch (C.Kind) { |
714 | 3 | case CodeCompletionString::CK_Informative: |
715 | 60 | case CodeCompletionString::CK_ResultType: |
716 | 60 | OS << "[#" << C.Text << "#]"; |
717 | 60 | break; |
718 | | |
719 | 103 | case CodeCompletionString::CK_CurrentParameter: |
720 | 103 | OS << "<#" << C.Text << "#>"; |
721 | 103 | break; |
722 | | |
723 | | // FIXME: We can also print optional parameters of an overload. |
724 | 11 | case CodeCompletionString::CK_Optional: |
725 | 11 | break; |
726 | | |
727 | 523 | default: |
728 | 523 | OS << C.Text; |
729 | 523 | break; |
730 | 697 | } |
731 | 697 | } |
732 | 119 | return Result; |
733 | 119 | } |
734 | | |
735 | | void PrintingCodeCompleteConsumer::ProcessOverloadCandidates( |
736 | | Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates, |
737 | 59 | unsigned NumCandidates, SourceLocation OpenParLoc, bool Braced) { |
738 | 59 | OS << "OPENING_PAREN_LOC: "; |
739 | 59 | OpenParLoc.print(OS, SemaRef.getSourceManager()); |
740 | 59 | OS << "\n"; |
741 | | |
742 | 178 | for (unsigned I = 0; I != NumCandidates; ++I119 ) { |
743 | 119 | if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString( |
744 | 119 | CurrentArg, SemaRef, getAllocator(), CCTUInfo, |
745 | 119 | includeBriefComments(), Braced)) { |
746 | 119 | OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n"; |
747 | 119 | } |
748 | 119 | } |
749 | 59 | } |
750 | | |
751 | | /// Retrieve the effective availability of the given declaration. |
752 | 18.7k | static AvailabilityResult getDeclAvailability(const Decl *D) { |
753 | 18.7k | AvailabilityResult AR = D->getAvailability(); |
754 | 18.7k | if (isa<EnumConstantDecl>(D)) |
755 | 193 | AR = std::max(AR, cast<Decl>(D->getDeclContext())->getAvailability()); |
756 | 18.7k | return AR; |
757 | 18.7k | } |
758 | | |
759 | 18.7k | void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { |
760 | 18.7k | switch (Kind) { |
761 | 245 | case RK_Pattern: |
762 | 245 | if (!Declaration) { |
763 | | // Do nothing: Patterns can come with cursor kinds! |
764 | 0 | break; |
765 | 0 | } |
766 | 245 | LLVM_FALLTHROUGH; |
767 | | |
768 | 18.7k | case RK_Declaration: { |
769 | | // Set the availability based on attributes. |
770 | 18.7k | switch (getDeclAvailability(Declaration)) { |
771 | 18.6k | case AR_Available: |
772 | 18.6k | case AR_NotYetIntroduced: |
773 | 18.6k | Availability = CXAvailability_Available; |
774 | 18.6k | break; |
775 | | |
776 | 19 | case AR_Deprecated: |
777 | 19 | Availability = CXAvailability_Deprecated; |
778 | 19 | break; |
779 | | |
780 | 20 | case AR_Unavailable: |
781 | 20 | Availability = CXAvailability_NotAvailable; |
782 | 20 | break; |
783 | 18.7k | } |
784 | | |
785 | 18.7k | if (const auto *Function = dyn_cast<FunctionDecl>(Declaration)) |
786 | 4.81k | if (Function->isDeleted()) |
787 | 36 | Availability = CXAvailability_NotAvailable; |
788 | | |
789 | 18.7k | CursorKind = getCursorKindForDecl(Declaration); |
790 | 18.7k | if (CursorKind == CXCursor_UnexposedDecl) { |
791 | | // FIXME: Forward declarations of Objective-C classes and protocols |
792 | | // are not directly exposed, but we want code completion to treat them |
793 | | // like a definition. |
794 | 202 | if (isa<ObjCInterfaceDecl>(Declaration)) |
795 | 0 | CursorKind = CXCursor_ObjCInterfaceDecl; |
796 | 202 | else if (isa<ObjCProtocolDecl>(Declaration)) |
797 | 0 | CursorKind = CXCursor_ObjCProtocolDecl; |
798 | 202 | else |
799 | 202 | CursorKind = CXCursor_NotImplemented; |
800 | 202 | } |
801 | 18.7k | break; |
802 | 18.7k | } |
803 | | |
804 | 0 | case RK_Macro: |
805 | 0 | case RK_Keyword: |
806 | 0 | llvm_unreachable("Macro and keyword kinds are handled by the constructors"); |
807 | 18.7k | } |
808 | | |
809 | 18.7k | if (!Accessible) |
810 | 90 | Availability = CXAvailability_NotAccessible; |
811 | 18.7k | } |
812 | | |
813 | | /// Retrieve the name that should be used to order a result. |
814 | | /// |
815 | | /// If the name needs to be constructed as a string, that string will be |
816 | | /// saved into Saved and the returned StringRef will refer to it. |
817 | 274k | StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const { |
818 | 274k | switch (Kind) { |
819 | 36.2k | case RK_Keyword: |
820 | 36.2k | return Keyword; |
821 | 192k | case RK_Pattern: |
822 | 192k | return Pattern->getTypedText(); |
823 | 35.1k | case RK_Macro: |
824 | 35.1k | return Macro->getName(); |
825 | 10.7k | case RK_Declaration: |
826 | | // Handle declarations below. |
827 | 10.7k | break; |
828 | 274k | } |
829 | | |
830 | 10.7k | DeclarationName Name = Declaration->getDeclName(); |
831 | | |
832 | | // If the name is a simple identifier (by far the common case), or a |
833 | | // zero-argument selector, just return a reference to that identifier. |
834 | 10.7k | if (IdentifierInfo *Id = Name.getAsIdentifierInfo()) |
835 | 7.86k | return Id->getName(); |
836 | 2.90k | if (Name.isObjCZeroArgSelector()) |
837 | 42 | if (IdentifierInfo *Id = Name.getObjCSelector().getIdentifierInfoForSlot(0)) |
838 | 42 | return Id->getName(); |
839 | | |
840 | 2.86k | Saved = Name.getAsString(); |
841 | 2.86k | return Saved; |
842 | 2.90k | } |
843 | | |
844 | | bool clang::operator<(const CodeCompletionResult &X, |
845 | 137k | const CodeCompletionResult &Y) { |
846 | 137k | std::string XSaved, YSaved; |
847 | 137k | StringRef XStr = X.getOrderedName(XSaved); |
848 | 137k | StringRef YStr = Y.getOrderedName(YSaved); |
849 | 137k | int cmp = XStr.compare_insensitive(YStr); |
850 | 137k | if (cmp) |
851 | 136k | return cmp < 0; |
852 | | |
853 | | // If case-insensitive comparison fails, try case-sensitive comparison. |
854 | 1.09k | return XStr.compare(YStr) < 0; |
855 | 137k | } |