1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
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/StringRef.h" |
27 | #include "llvm/ADT/Twine.h" |
28 | #include "llvm/Support/Casting.h" |
29 | #include "llvm/Support/Compiler.h" |
30 | #include "llvm/Support/ErrorHandling.h" |
31 | #include "llvm/Support/FormatVariadic.h" |
32 | #include "llvm/Support/raw_ostream.h" |
33 | #include <algorithm> |
34 | #include <cassert> |
35 | #include <cstdint> |
36 | #include <string> |
37 | |
38 | using namespace clang; |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | bool CodeCompletionContext::wantConstructorResults() const { |
45 | switch (CCKind) { |
46 | case CCC_Recovery: |
47 | case CCC_Statement: |
48 | case CCC_Expression: |
49 | case CCC_ObjCMessageReceiver: |
50 | case CCC_ParenthesizedExpression: |
51 | case CCC_Symbol: |
52 | case CCC_SymbolOrNewName: |
53 | return true; |
54 | |
55 | case CCC_TopLevel: |
56 | case CCC_ObjCInterface: |
57 | case CCC_ObjCImplementation: |
58 | case CCC_ObjCIvarList: |
59 | case CCC_ClassStructUnion: |
60 | case CCC_DotMemberAccess: |
61 | case CCC_ArrowMemberAccess: |
62 | case CCC_ObjCPropertyAccess: |
63 | case CCC_EnumTag: |
64 | case CCC_UnionTag: |
65 | case CCC_ClassOrStructTag: |
66 | case CCC_ObjCProtocolName: |
67 | case CCC_Namespace: |
68 | case CCC_Type: |
69 | case CCC_NewName: |
70 | case CCC_MacroName: |
71 | case CCC_MacroNameUse: |
72 | case CCC_PreprocessorExpression: |
73 | case CCC_PreprocessorDirective: |
74 | case CCC_NaturalLanguage: |
75 | case CCC_SelectorName: |
76 | case CCC_TypeQualifiers: |
77 | case CCC_Other: |
78 | case CCC_OtherWithMacros: |
79 | case CCC_ObjCInstanceMessage: |
80 | case CCC_ObjCClassMessage: |
81 | case CCC_ObjCInterfaceName: |
82 | case CCC_ObjCCategoryName: |
83 | case CCC_IncludedFile: |
84 | return false; |
85 | } |
86 | |
87 | llvm_unreachable("Invalid CodeCompletionContext::Kind!"); |
88 | } |
89 | |
90 | StringRef clang::getCompletionKindString(CodeCompletionContext::Kind Kind) { |
91 | using CCKind = CodeCompletionContext::Kind; |
92 | switch (Kind) { |
93 | case CCKind::CCC_Other: |
94 | return "Other"; |
95 | case CCKind::CCC_OtherWithMacros: |
96 | return "OtherWithMacros"; |
97 | case CCKind::CCC_TopLevel: |
98 | return "TopLevel"; |
99 | case CCKind::CCC_ObjCInterface: |
100 | return "ObjCInterface"; |
101 | case CCKind::CCC_ObjCImplementation: |
102 | return "ObjCImplementation"; |
103 | case CCKind::CCC_ObjCIvarList: |
104 | return "ObjCIvarList"; |
105 | case CCKind::CCC_ClassStructUnion: |
106 | return "ClassStructUnion"; |
107 | case CCKind::CCC_Statement: |
108 | return "Statement"; |
109 | case CCKind::CCC_Expression: |
110 | return "Expression"; |
111 | case CCKind::CCC_ObjCMessageReceiver: |
112 | return "ObjCMessageReceiver"; |
113 | case CCKind::CCC_DotMemberAccess: |
114 | return "DotMemberAccess"; |
115 | case CCKind::CCC_ArrowMemberAccess: |
116 | return "ArrowMemberAccess"; |
117 | case CCKind::CCC_ObjCPropertyAccess: |
118 | return "ObjCPropertyAccess"; |
119 | case CCKind::CCC_EnumTag: |
120 | return "EnumTag"; |
121 | case CCKind::CCC_UnionTag: |
122 | return "UnionTag"; |
123 | case CCKind::CCC_ClassOrStructTag: |
124 | return "ClassOrStructTag"; |
125 | case CCKind::CCC_ObjCProtocolName: |
126 | return "ObjCProtocolName"; |
127 | case CCKind::CCC_Namespace: |
128 | return "Namespace"; |
129 | case CCKind::CCC_Type: |
130 | return "Type"; |
131 | case CCKind::CCC_NewName: |
132 | return "NewName"; |
133 | case CCKind::CCC_Symbol: |
134 | return "Symbol"; |
135 | case CCKind::CCC_SymbolOrNewName: |
136 | return "SymbolOrNewName"; |
137 | case CCKind::CCC_MacroName: |
138 | return "MacroName"; |
139 | case CCKind::CCC_MacroNameUse: |
140 | return "MacroNameUse"; |
141 | case CCKind::CCC_PreprocessorExpression: |
142 | return "PreprocessorExpression"; |
143 | case CCKind::CCC_PreprocessorDirective: |
144 | return "PreprocessorDirective"; |
145 | case CCKind::CCC_NaturalLanguage: |
146 | return "NaturalLanguage"; |
147 | case CCKind::CCC_SelectorName: |
148 | return "SelectorName"; |
149 | case CCKind::CCC_TypeQualifiers: |
150 | return "TypeQualifiers"; |
151 | case CCKind::CCC_ParenthesizedExpression: |
152 | return "ParenthesizedExpression"; |
153 | case CCKind::CCC_ObjCInstanceMessage: |
154 | return "ObjCInstanceMessage"; |
155 | case CCKind::CCC_ObjCClassMessage: |
156 | return "ObjCClassMessage"; |
157 | case CCKind::CCC_ObjCInterfaceName: |
158 | return "ObjCInterfaceName"; |
159 | case CCKind::CCC_ObjCCategoryName: |
160 | return "ObjCCategoryName"; |
161 | case CCKind::CCC_IncludedFile: |
162 | return "IncludedFile"; |
163 | case CCKind::CCC_Recovery: |
164 | return "Recovery"; |
165 | } |
166 | llvm_unreachable("Invalid CodeCompletionContext::Kind!"); |
167 | } |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) |
174 | : Kind(Kind), Text("") { |
175 | switch (Kind) { |
176 | case CK_TypedText: |
177 | case CK_Text: |
178 | case CK_Placeholder: |
179 | case CK_Informative: |
180 | case CK_ResultType: |
181 | case CK_CurrentParameter: |
182 | this->Text = Text; |
183 | break; |
184 | |
185 | case CK_Optional: |
186 | llvm_unreachable("Optional strings cannot be created from text"); |
187 | |
188 | case CK_LeftParen: |
189 | this->Text = "("; |
190 | break; |
191 | |
192 | case CK_RightParen: |
193 | this->Text = ")"; |
194 | break; |
195 | |
196 | case CK_LeftBracket: |
197 | this->Text = "["; |
198 | break; |
199 | |
200 | case CK_RightBracket: |
201 | this->Text = "]"; |
202 | break; |
203 | |
204 | case CK_LeftBrace: |
205 | this->Text = "{"; |
206 | break; |
207 | |
208 | case CK_RightBrace: |
209 | this->Text = "}"; |
210 | break; |
211 | |
212 | case CK_LeftAngle: |
213 | this->Text = "<"; |
214 | break; |
215 | |
216 | case CK_RightAngle: |
217 | this->Text = ">"; |
218 | break; |
219 | |
220 | case CK_Comma: |
221 | this->Text = ", "; |
222 | break; |
223 | |
224 | case CK_Colon: |
225 | this->Text = ":"; |
226 | break; |
227 | |
228 | case CK_SemiColon: |
229 | this->Text = ";"; |
230 | break; |
231 | |
232 | case CK_Equal: |
233 | this->Text = " = "; |
234 | break; |
235 | |
236 | case CK_HorizontalSpace: |
237 | this->Text = " "; |
238 | break; |
239 | |
240 | case CK_VerticalSpace: |
241 | this->Text = "\n"; |
242 | break; |
243 | } |
244 | } |
245 | |
246 | CodeCompletionString::Chunk |
247 | CodeCompletionString::Chunk::CreateText(const char *Text) { |
248 | return Chunk(CK_Text, Text); |
249 | } |
250 | |
251 | CodeCompletionString::Chunk |
252 | CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) { |
253 | Chunk Result; |
254 | Result.Kind = CK_Optional; |
255 | Result.Optional = Optional; |
256 | return Result; |
257 | } |
258 | |
259 | CodeCompletionString::Chunk |
260 | CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) { |
261 | return Chunk(CK_Placeholder, Placeholder); |
262 | } |
263 | |
264 | CodeCompletionString::Chunk |
265 | CodeCompletionString::Chunk::CreateInformative(const char *Informative) { |
266 | return Chunk(CK_Informative, Informative); |
267 | } |
268 | |
269 | CodeCompletionString::Chunk |
270 | CodeCompletionString::Chunk::CreateResultType(const char *ResultType) { |
271 | return Chunk(CK_ResultType, ResultType); |
272 | } |
273 | |
274 | CodeCompletionString::Chunk CodeCompletionString::Chunk::CreateCurrentParameter( |
275 | const char *CurrentParameter) { |
276 | return Chunk(CK_CurrentParameter, CurrentParameter); |
277 | } |
278 | |
279 | CodeCompletionString::CodeCompletionString( |
280 | const Chunk *Chunks, unsigned NumChunks, unsigned Priority, |
281 | CXAvailabilityKind Availability, const char **Annotations, |
282 | unsigned NumAnnotations, StringRef ParentName, const char *) |
283 | : NumChunks(NumChunks), NumAnnotations(NumAnnotations), Priority(Priority), |
284 | Availability(Availability), ParentName(ParentName), |
285 | BriefComment(BriefComment) { |
286 | assert(NumChunks <= 0xffff); |
287 | assert(NumAnnotations <= 0xffff); |
288 | |
289 | Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1); |
290 | for (unsigned I = 0; I != NumChunks; ++I) |
291 | StoredChunks[I] = Chunks[I]; |
292 | |
293 | const char **StoredAnnotations = |
294 | reinterpret_cast<const char **>(StoredChunks + NumChunks); |
295 | for (unsigned I = 0; I != NumAnnotations; ++I) |
296 | StoredAnnotations[I] = Annotations[I]; |
297 | } |
298 | |
299 | unsigned CodeCompletionString::getAnnotationCount() const { |
300 | return NumAnnotations; |
301 | } |
302 | |
303 | const char *CodeCompletionString::getAnnotation(unsigned AnnotationNr) const { |
304 | if (AnnotationNr < NumAnnotations) |
305 | return reinterpret_cast<const char *const *>(end())[AnnotationNr]; |
306 | else |
307 | return nullptr; |
308 | } |
309 | |
310 | std::string CodeCompletionString::getAsString() const { |
311 | std::string Result; |
312 | llvm::raw_string_ostream OS(Result); |
313 | |
314 | for (const Chunk &C : *this) { |
315 | switch (C.Kind) { |
316 | case CK_Optional: |
317 | OS << "{#" << C.Optional->getAsString() << "#}"; |
318 | break; |
319 | case CK_Placeholder: |
320 | OS << "<#" << C.Text << "#>"; |
321 | break; |
322 | case CK_Informative: |
323 | case CK_ResultType: |
324 | OS << "[#" << C.Text << "#]"; |
325 | break; |
326 | case CK_CurrentParameter: |
327 | OS << "<#" << C.Text << "#>"; |
328 | break; |
329 | default: |
330 | OS << C.Text; |
331 | break; |
332 | } |
333 | } |
334 | return OS.str(); |
335 | } |
336 | |
337 | const char *CodeCompletionString::getTypedText() const { |
338 | for (const Chunk &C : *this) |
339 | if (C.Kind == CK_TypedText) |
340 | return C.Text; |
341 | |
342 | return nullptr; |
343 | } |
344 | |
345 | const char *CodeCompletionAllocator::CopyString(const Twine &String) { |
346 | SmallString<128> Data; |
347 | StringRef Ref = String.toStringRef(Data); |
348 | |
349 | |
350 | |
351 | char *Mem = (char *)Allocate(Ref.size() + 1, 1); |
352 | std::copy(Ref.begin(), Ref.end(), Mem); |
353 | Mem[Ref.size()] = 0; |
354 | return Mem; |
355 | } |
356 | |
357 | StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { |
358 | const NamedDecl *ND = dyn_cast<NamedDecl>(DC); |
359 | if (!ND) |
360 | return {}; |
361 | |
362 | |
363 | StringRef &CachedParentName = ParentNames[DC]; |
364 | if (!CachedParentName.empty()) |
365 | return CachedParentName; |
366 | |
367 | |
368 | |
369 | if (CachedParentName.data() != nullptr) |
370 | return {}; |
371 | |
372 | |
373 | SmallVector<const DeclContext *, 2> Contexts; |
374 | while (DC && !DC->isFunctionOrMethod()) { |
375 | if (const auto *ND = dyn_cast<NamedDecl>(DC)) { |
376 | if (ND->getIdentifier()) |
377 | Contexts.push_back(DC); |
378 | } |
379 | |
380 | DC = DC->getParent(); |
381 | } |
382 | |
383 | { |
384 | SmallString<128> S; |
385 | llvm::raw_svector_ostream OS(S); |
386 | bool First = true; |
387 | for (unsigned I = Contexts.size(); I != 0; --I) { |
388 | if (First) |
389 | First = false; |
390 | else { |
391 | OS << "::"; |
392 | } |
393 | |
394 | const DeclContext *CurDC = Contexts[I - 1]; |
395 | if (const auto *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC)) |
396 | CurDC = CatImpl->getCategoryDecl(); |
397 | |
398 | if (const auto *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) { |
399 | const ObjCInterfaceDecl *Interface = Cat->getClassInterface(); |
400 | if (!Interface) { |
401 | |
402 | |
403 | CachedParentName = StringRef((const char *)(uintptr_t)~0U, 0); |
404 | return {}; |
405 | } |
406 | |
407 | OS << Interface->getName() << '(' << Cat->getName() << ')'; |
408 | } else { |
409 | OS << cast<NamedDecl>(CurDC)->getName(); |
410 | } |
411 | } |
412 | |
413 | CachedParentName = AllocatorRef->CopyString(OS.str()); |
414 | } |
415 | |
416 | return CachedParentName; |
417 | } |
418 | |
419 | CodeCompletionString *CodeCompletionBuilder::TakeString() { |
420 | void *Mem = getAllocator().Allocate( |
421 | sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() + |
422 | sizeof(const char *) * Annotations.size(), |
423 | alignof(CodeCompletionString)); |
424 | CodeCompletionString *Result = new (Mem) CodeCompletionString( |
425 | Chunks.data(), Chunks.size(), Priority, Availability, Annotations.data(), |
426 | Annotations.size(), ParentName, BriefComment); |
427 | Chunks.clear(); |
428 | return Result; |
429 | } |
430 | |
431 | void CodeCompletionBuilder::AddTypedTextChunk(const char *Text) { |
432 | Chunks.push_back(Chunk(CodeCompletionString::CK_TypedText, Text)); |
433 | } |
434 | |
435 | void CodeCompletionBuilder::AddTextChunk(const char *Text) { |
436 | Chunks.push_back(Chunk::CreateText(Text)); |
437 | } |
438 | |
439 | void CodeCompletionBuilder::AddOptionalChunk(CodeCompletionString *Optional) { |
440 | Chunks.push_back(Chunk::CreateOptional(Optional)); |
441 | } |
442 | |
443 | void CodeCompletionBuilder::AddPlaceholderChunk(const char *Placeholder) { |
444 | Chunks.push_back(Chunk::CreatePlaceholder(Placeholder)); |
445 | } |
446 | |
447 | void CodeCompletionBuilder::AddInformativeChunk(const char *Text) { |
448 | Chunks.push_back(Chunk::CreateInformative(Text)); |
449 | } |
450 | |
451 | void CodeCompletionBuilder::AddResultTypeChunk(const char *ResultType) { |
452 | Chunks.push_back(Chunk::CreateResultType(ResultType)); |
453 | } |
454 | |
455 | void CodeCompletionBuilder::AddCurrentParameterChunk( |
456 | const char *CurrentParameter) { |
457 | Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter)); |
458 | } |
459 | |
460 | void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK, |
461 | const char *Text) { |
462 | Chunks.push_back(Chunk(CK, Text)); |
463 | } |
464 | |
465 | void CodeCompletionBuilder::addParentContext(const DeclContext *DC) { |
466 | if (DC->isTranslationUnit()) |
467 | return; |
468 | |
469 | if (DC->isFunctionOrMethod()) |
470 | return; |
471 | |
472 | const NamedDecl *ND = dyn_cast<NamedDecl>(DC); |
473 | if (!ND) |
474 | return; |
475 | |
476 | ParentName = getCodeCompletionTUInfo().getParentName(DC); |
477 | } |
478 | |
479 | void CodeCompletionBuilder::(StringRef ) { |
480 | BriefComment = Allocator.CopyString(Comment); |
481 | } |
482 | |
483 | |
484 | |
485 | |
486 | FunctionDecl *CodeCompleteConsumer::OverloadCandidate::getFunction() const { |
487 | if (getKind() == CK_Function) |
488 | return Function; |
489 | else if (getKind() == CK_FunctionTemplate) |
490 | return FunctionTemplate->getTemplatedDecl(); |
491 | else |
492 | return nullptr; |
493 | } |
494 | |
495 | const FunctionType * |
496 | CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { |
497 | switch (Kind) { |
498 | case CK_Function: |
499 | return Function->getType()->getAs<FunctionType>(); |
500 | |
501 | case CK_FunctionTemplate: |
502 | return FunctionTemplate->getTemplatedDecl() |
503 | ->getType() |
504 | ->getAs<FunctionType>(); |
505 | |
506 | case CK_FunctionType: |
507 | return Type; |
508 | } |
509 | |
510 | llvm_unreachable("Invalid CandidateKind!"); |
511 | } |
512 | |
513 | |
514 | |
515 | |
516 | |
517 | CodeCompleteConsumer::~CodeCompleteConsumer() = default; |
518 | |
519 | bool PrintingCodeCompleteConsumer::isResultFilteredOut( |
520 | StringRef Filter, CodeCompletionResult Result) { |
521 | switch (Result.Kind) { |
522 | case CodeCompletionResult::RK_Declaration: |
523 | return !(Result.Declaration->getIdentifier() && |
524 | Result.Declaration->getIdentifier()->getName().startswith(Filter)); |
525 | case CodeCompletionResult::RK_Keyword: |
526 | return !StringRef(Result.Keyword).startswith(Filter); |
527 | case CodeCompletionResult::RK_Macro: |
528 | return !Result.Macro->getName().startswith(Filter); |
529 | case CodeCompletionResult::RK_Pattern: |
530 | return !(Result.Pattern->getTypedText() && |
531 | StringRef(Result.Pattern->getTypedText()).startswith(Filter)); |
532 | } |
533 | llvm_unreachable("Unknown code completion result Kind."); |
534 | } |
535 | |
536 | void PrintingCodeCompleteConsumer::ProcessCodeCompleteResults( |
537 | Sema &SemaRef, CodeCompletionContext Context, CodeCompletionResult *Results, |
538 | unsigned NumResults) { |
539 | std::stable_sort(Results, Results + NumResults); |
540 | |
541 | if (!Context.getPreferredType().isNull()) |
542 | OS << "PREFERRED-TYPE: " << Context.getPreferredType().getAsString() |
543 | << "\n"; |
544 | |
545 | StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter(); |
546 | |
547 | for (unsigned I = 0; I != NumResults; ++I) { |
548 | if (!Filter.empty() && isResultFilteredOut(Filter, Results[I])) |
549 | continue; |
550 | OS << "COMPLETION: "; |
551 | switch (Results[I].Kind) { |
552 | case CodeCompletionResult::RK_Declaration: |
553 | OS << *Results[I].Declaration; |
554 | { |
555 | std::vector<std::string> Tags; |
556 | if (Results[I].Hidden) |
557 | Tags.push_back("Hidden"); |
558 | if (Results[I].InBaseClass) |
559 | Tags.push_back("InBase"); |
560 | if (Results[I].Availability == |
561 | CXAvailabilityKind::CXAvailability_NotAccessible) |
562 | Tags.push_back("Inaccessible"); |
563 | if (!Tags.empty()) |
564 | OS << " (" << llvm::join(Tags, ",") << ")"; |
565 | } |
566 | if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString( |
567 | SemaRef, Context, getAllocator(), CCTUInfo, |
568 | includeBriefComments())) { |
569 | OS << " : " << CCS->getAsString(); |
570 | if (const char * = CCS->getBriefComment()) |
571 | OS << " : " << BriefComment; |
572 | } |
573 | for (const FixItHint &FixIt : Results[I].FixIts) { |
574 | const SourceLocation BLoc = FixIt.RemoveRange.getBegin(); |
575 | const SourceLocation ELoc = FixIt.RemoveRange.getEnd(); |
576 | |
577 | SourceManager &SM = SemaRef.SourceMgr; |
578 | std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc); |
579 | std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc); |
580 | |
581 | if (FixIt.RemoveRange.isTokenRange()) |
582 | EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, SemaRef.LangOpts); |
583 | |
584 | OS << " (requires fix-it:" |
585 | << " {" << SM.getLineNumber(BInfo.first, BInfo.second) << ':' |
586 | << SM.getColumnNumber(BInfo.first, BInfo.second) << '-' |
587 | << SM.getLineNumber(EInfo.first, EInfo.second) << ':' |
588 | << SM.getColumnNumber(EInfo.first, EInfo.second) << "}" |
589 | << " to \"" << FixIt.CodeToInsert << "\")"; |
590 | } |
591 | OS << '\n'; |
592 | break; |
593 | |
594 | case CodeCompletionResult::RK_Keyword: |
595 | OS << Results[I].Keyword << '\n'; |
596 | break; |
597 | |
598 | case CodeCompletionResult::RK_Macro: |
599 | OS << Results[I].Macro->getName(); |
600 | if (CodeCompletionString *CCS = Results[I].CreateCodeCompletionString( |
601 | SemaRef, Context, getAllocator(), CCTUInfo, |
602 | includeBriefComments())) { |
603 | OS << " : " << CCS->getAsString(); |
604 | } |
605 | OS << '\n'; |
606 | break; |
607 | |
608 | case CodeCompletionResult::RK_Pattern: |
609 | OS << "Pattern : " << Results[I].Pattern->getAsString() << '\n'; |
610 | break; |
611 | } |
612 | } |
613 | } |
614 | |
615 | |
616 | |
617 | |
618 | |
619 | static std::string getOverloadAsString(const CodeCompletionString &CCS) { |
620 | std::string Result; |
621 | llvm::raw_string_ostream OS(Result); |
622 | |
623 | for (auto &C : CCS) { |
624 | switch (C.Kind) { |
625 | case CodeCompletionString::CK_Informative: |
626 | case CodeCompletionString::CK_ResultType: |
627 | OS << "[#" << C.Text << "#]"; |
628 | break; |
629 | |
630 | case CodeCompletionString::CK_CurrentParameter: |
631 | OS << "<#" << C.Text << "#>"; |
632 | break; |
633 | |
634 | |
635 | case CodeCompletionString::CK_Optional: |
636 | break; |
637 | |
638 | default: |
639 | OS << C.Text; |
640 | break; |
641 | } |
642 | } |
643 | return OS.str(); |
644 | } |
645 | |
646 | void PrintingCodeCompleteConsumer::ProcessOverloadCandidates( |
647 | Sema &SemaRef, unsigned CurrentArg, OverloadCandidate *Candidates, |
648 | unsigned NumCandidates, SourceLocation OpenParLoc) { |
649 | OS << "OPENING_PAREN_LOC: "; |
650 | OpenParLoc.print(OS, SemaRef.getSourceManager()); |
651 | OS << "\n"; |
652 | |
653 | for (unsigned I = 0; I != NumCandidates; ++I) { |
654 | if (CodeCompletionString *CCS = Candidates[I].CreateSignatureString( |
655 | CurrentArg, SemaRef, getAllocator(), CCTUInfo, |
656 | includeBriefComments())) { |
657 | OS << "OVERLOAD: " << getOverloadAsString(*CCS) << "\n"; |
658 | } |
659 | } |
660 | } |
661 | |
662 | |
663 | static AvailabilityResult getDeclAvailability(const Decl *D) { |
664 | AvailabilityResult AR = D->getAvailability(); |
665 | if (isa<EnumConstantDecl>(D)) |
666 | AR = std::max(AR, cast<Decl>(D->getDeclContext())->getAvailability()); |
667 | return AR; |
668 | } |
669 | |
670 | void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { |
671 | switch (Kind) { |
672 | case RK_Pattern: |
673 | if (!Declaration) { |
674 | |
675 | break; |
676 | } |
677 | LLVM_FALLTHROUGH; |
678 | |
679 | case RK_Declaration: { |
680 | |
681 | switch (getDeclAvailability(Declaration)) { |
682 | case AR_Available: |
683 | case AR_NotYetIntroduced: |
684 | Availability = CXAvailability_Available; |
685 | break; |
686 | |
687 | case AR_Deprecated: |
688 | Availability = CXAvailability_Deprecated; |
689 | break; |
690 | |
691 | case AR_Unavailable: |
692 | Availability = CXAvailability_NotAvailable; |
693 | break; |
694 | } |
695 | |
696 | if (const auto *Function = dyn_cast<FunctionDecl>(Declaration)) |
697 | if (Function->isDeleted()) |
698 | Availability = CXAvailability_NotAvailable; |
699 | |
700 | CursorKind = getCursorKindForDecl(Declaration); |
701 | if (CursorKind == CXCursor_UnexposedDecl) { |
702 | |
703 | |
704 | |
705 | if (isa<ObjCInterfaceDecl>(Declaration)) |
706 | CursorKind = CXCursor_ObjCInterfaceDecl; |
707 | else if (isa<ObjCProtocolDecl>(Declaration)) |
708 | CursorKind = CXCursor_ObjCProtocolDecl; |
709 | else |
710 | CursorKind = CXCursor_NotImplemented; |
711 | } |
712 | break; |
713 | } |
714 | |
715 | case RK_Macro: |
716 | case RK_Keyword: |
717 | llvm_unreachable("Macro and keyword kinds are handled by the constructors"); |
718 | } |
719 | |
720 | if (!Accessible) |
721 | Availability = CXAvailability_NotAccessible; |
722 | } |
723 | |
724 | |
725 | |
726 | |
727 | |
728 | StringRef CodeCompletionResult::getOrderedName(std::string &Saved) const { |
729 | switch (Kind) { |
730 | case RK_Keyword: |
731 | return Keyword; |
732 | case RK_Pattern: |
733 | return Pattern->getTypedText(); |
734 | case RK_Macro: |
735 | return Macro->getName(); |
736 | case RK_Declaration: |
737 | |
738 | break; |
739 | } |
740 | |
741 | DeclarationName Name = Declaration->getDeclName(); |
742 | |
743 | |
744 | |
745 | if (IdentifierInfo *Id = Name.getAsIdentifierInfo()) |
746 | return Id->getName(); |
747 | if (Name.isObjCZeroArgSelector()) |
748 | if (IdentifierInfo *Id = Name.getObjCSelector().getIdentifierInfoForSlot(0)) |
749 | return Id->getName(); |
750 | |
751 | Saved = Name.getAsString(); |
752 | return Saved; |
753 | } |
754 | |
755 | bool clang::operator<(const CodeCompletionResult &X, |
756 | const CodeCompletionResult &Y) { |
757 | std::string XSaved, YSaved; |
758 | StringRef XStr = X.getOrderedName(XSaved); |
759 | StringRef YStr = Y.getOrderedName(YSaved); |
760 | int cmp = XStr.compare_lower(YStr); |
761 | if (cmp) |
762 | return cmp < 0; |
763 | |
764 | |
765 | return XStr.compare(YStr) < 0; |
766 | } |
767 | |