blob: b0a7a664f5aec65daaa36af4a465bc90e8b3c9b9 [file] [log] [blame]
Douglas Gregor3545ff42009-09-21 16:56:56 +00001//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===//
Douglas Gregor2436e712009-09-17 21:32:03 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the CodeCompleteConsumer class.
11//
12//===----------------------------------------------------------------------===//
13#include "clang/Sema/CodeCompleteConsumer.h"
Douglas Gregor56c2dbc2009-09-18 17:54:00 +000014#include "clang/AST/DeclCXX.h"
Douglas Gregorf45b0cf2009-09-18 15:37:17 +000015#include "clang/Parse/Scope.h"
Douglas Gregor2436e712009-09-17 21:32:03 +000016#include "clang/Lex/Preprocessor.h"
17#include "Sema.h"
18#include "llvm/ADT/STLExtras.h"
Douglas Gregor9eb77012009-11-07 00:00:49 +000019#include "llvm/ADT/StringSwitch.h"
Douglas Gregor2436e712009-09-17 21:32:03 +000020#include "llvm/Support/raw_ostream.h"
21#include <algorithm>
Douglas Gregorfedc3282009-09-18 22:15:54 +000022#include <cstring>
23#include <functional>
Douglas Gregorab6ccb52009-11-17 16:43:05 +000024
Douglas Gregor2436e712009-09-17 21:32:03 +000025using namespace clang;
Douglas Gregorab6ccb52009-11-17 16:43:05 +000026using llvm::StringRef;
Douglas Gregor2436e712009-09-17 21:32:03 +000027
Douglas Gregorfedc3282009-09-18 22:15:54 +000028//===----------------------------------------------------------------------===//
29// Code completion string implementation
30//===----------------------------------------------------------------------===//
Douglas Gregor9eb77012009-11-07 00:00:49 +000031CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text)
Daniel Dunbarb0a19422009-11-12 18:40:12 +000032 : Kind(Kind), Text("")
Douglas Gregor5bf52692009-09-22 23:15:58 +000033{
Douglas Gregor9eb77012009-11-07 00:00:49 +000034 switch (Kind) {
35 case CK_TypedText:
36 case CK_Text:
37 case CK_Placeholder:
38 case CK_Informative:
39 case CK_CurrentParameter: {
40 char *New = new char [Text.size() + 1];
41 std::memcpy(New, Text.data(), Text.size());
42 New[Text.size()] = '\0';
43 this->Text = New;
44 break;
45 }
46
47 case CK_Optional:
48 llvm::llvm_unreachable("Optional strings cannot be created from text");
49 break;
50
51 case CK_LeftParen:
52 this->Text = "(";
53 break;
54
55 case CK_RightParen:
56 this->Text = ")";
57 break;
58
59 case CK_LeftBracket:
60 this->Text = "[";
61 break;
62
63 case CK_RightBracket:
64 this->Text = "]";
65 break;
66
67 case CK_LeftBrace:
68 this->Text = "{";
69 break;
70
71 case CK_RightBrace:
72 this->Text = "}";
73 break;
74
75 case CK_LeftAngle:
76 this->Text = "<";
77 break;
78
79 case CK_RightAngle:
80 this->Text = ">";
81 break;
82
83 case CK_Comma:
84 this->Text = ", ";
85 break;
86 }
Douglas Gregor5bf52692009-09-22 23:15:58 +000087}
88
89CodeCompletionString::Chunk
Douglas Gregorab6ccb52009-11-17 16:43:05 +000090CodeCompletionString::Chunk::CreateText(StringRef Text) {
Douglas Gregor5bf52692009-09-22 23:15:58 +000091 return Chunk(CK_Text, Text);
Douglas Gregorfedc3282009-09-18 22:15:54 +000092}
93
94CodeCompletionString::Chunk
95CodeCompletionString::Chunk::CreateOptional(
96 std::auto_ptr<CodeCompletionString> Optional) {
97 Chunk Result;
98 Result.Kind = CK_Optional;
99 Result.Optional = Optional.release();
100 return Result;
101}
102
103CodeCompletionString::Chunk
Douglas Gregorab6ccb52009-11-17 16:43:05 +0000104CodeCompletionString::Chunk::CreatePlaceholder(StringRef Placeholder) {
Douglas Gregor5bf52692009-09-22 23:15:58 +0000105 return Chunk(CK_Placeholder, Placeholder);
106}
107
108CodeCompletionString::Chunk
Douglas Gregorab6ccb52009-11-17 16:43:05 +0000109CodeCompletionString::Chunk::CreateInformative(StringRef Informative) {
Douglas Gregor5bf52692009-09-22 23:15:58 +0000110 return Chunk(CK_Informative, Informative);
Douglas Gregorfedc3282009-09-18 22:15:54 +0000111}
112
Douglas Gregor9eb77012009-11-07 00:00:49 +0000113CodeCompletionString::Chunk
114CodeCompletionString::Chunk::CreateCurrentParameter(
Douglas Gregorab6ccb52009-11-17 16:43:05 +0000115 StringRef CurrentParameter) {
Douglas Gregor9eb77012009-11-07 00:00:49 +0000116 return Chunk(CK_CurrentParameter, CurrentParameter);
117}
118
Douglas Gregor45f83ee2009-11-19 00:01:57 +0000119CodeCompletionString::Chunk CodeCompletionString::Chunk::Clone() const {
120 switch (Kind) {
121 case CK_TypedText:
122 case CK_Text:
123 case CK_Placeholder:
124 case CK_Informative:
125 case CK_CurrentParameter:
126 case CK_LeftParen:
127 case CK_RightParen:
128 case CK_LeftBracket:
129 case CK_RightBracket:
130 case CK_LeftBrace:
131 case CK_RightBrace:
132 case CK_LeftAngle:
133 case CK_RightAngle:
134 case CK_Comma:
135 return Chunk(Kind, Text);
136
137 case CK_Optional: {
138 std::auto_ptr<CodeCompletionString> Opt(Optional->Clone());
139 return CreateOptional(Opt);
140 }
141 }
142
143 // Silence GCC warning.
144 return Chunk();
145}
Douglas Gregor9eb77012009-11-07 00:00:49 +0000146
Douglas Gregorfedc3282009-09-18 22:15:54 +0000147void
148CodeCompletionString::Chunk::Destroy() {
149 switch (Kind) {
Douglas Gregor5bf52692009-09-22 23:15:58 +0000150 case CK_Optional:
151 delete Optional;
152 break;
153
Douglas Gregor9eb77012009-11-07 00:00:49 +0000154 case CK_TypedText:
Douglas Gregor5bf52692009-09-22 23:15:58 +0000155 case CK_Text:
156 case CK_Placeholder:
157 case CK_Informative:
Douglas Gregor9eb77012009-11-07 00:00:49 +0000158 case CK_CurrentParameter:
159 delete [] Text;
160 break;
161
162 case CK_LeftParen:
163 case CK_RightParen:
164 case CK_LeftBracket:
165 case CK_RightBracket:
166 case CK_LeftBrace:
167 case CK_RightBrace:
168 case CK_LeftAngle:
169 case CK_RightAngle:
170 case CK_Comma:
Douglas Gregor5bf52692009-09-22 23:15:58 +0000171 break;
Douglas Gregorfedc3282009-09-18 22:15:54 +0000172 }
173}
174
175CodeCompletionString::~CodeCompletionString() {
176 std::for_each(Chunks.begin(), Chunks.end(),
177 std::mem_fun_ref(&Chunk::Destroy));
178}
179
180std::string CodeCompletionString::getAsString() const {
181 std::string Result;
182 llvm::raw_string_ostream OS(Result);
183
184 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
185 switch (C->Kind) {
Douglas Gregorfedc3282009-09-18 22:15:54 +0000186 case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
Douglas Gregor5bf52692009-09-22 23:15:58 +0000187 case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
188 case CK_Informative: OS << "[#" << C->Text << "#]"; break;
Douglas Gregor9eb77012009-11-07 00:00:49 +0000189 case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
190 default: OS << C->Text; break;
Douglas Gregorfedc3282009-09-18 22:15:54 +0000191 }
192 }
Douglas Gregor78f0fa52009-09-29 15:13:39 +0000193 OS.flush();
Douglas Gregorfedc3282009-09-18 22:15:54 +0000194 return Result;
195}
196
Douglas Gregor45f83ee2009-11-19 00:01:57 +0000197const char *CodeCompletionString::getTypedText() const {
198 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
199 if (C->Kind == CK_TypedText)
200 return C->Text;
201
202 return 0;
203}
204
205CodeCompletionString *CodeCompletionString::Clone() const {
206 CodeCompletionString *Result = new CodeCompletionString;
207 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
208 Result->AddChunk(C->Clone());
209 return Result;
210}
Douglas Gregor9eb77012009-11-07 00:00:49 +0000211
212namespace {
213 // Escape a string for XML-like formatting.
214 struct EscapedString {
215 EscapedString(llvm::StringRef Str) : Str(Str) { }
216
217 llvm::StringRef Str;
218 };
219
220 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, EscapedString EStr) {
221 llvm::StringRef Str = EStr.Str;
222 while (!Str.empty()) {
223 // Find the next escaped character.
224 llvm::StringRef::size_type Pos = Str.find_first_of("<>&\"'");
225
226 // Print everything before that escaped character.
227 OS << Str.substr(0, Pos);
228
229 // If we didn't find any escaped characters, we're done.
230 if (Pos == llvm::StringRef::npos)
231 break;
232
233 // Print the appropriate escape sequence.
234 switch (Str[Pos]) {
235 case '<': OS << "&lt;"; break;
236 case '>': OS << "&gt;"; break;
237 case '&': OS << "&amp;"; break;
238 case '"': OS << "&quot;"; break;
239 case '\'': OS << "&apos;"; break;
240 }
241
242 // Remove everything up to and including that escaped character.
243 Str = Str.substr(Pos + 1);
244 }
245
246 return OS;
247 }
248
249 /// \brief Remove XML-like escaping from a string.
250 std::string UnescapeString(llvm::StringRef Str) {
251 using llvm::StringRef;
252
253 std::string Result;
254 llvm::raw_string_ostream OS(Result);
255
256 while (!Str.empty()) {
257 StringRef::size_type Amp = Str.find('&');
258 OS << Str.substr(0, Amp);
259
260 if (Amp == StringRef::npos)
261 break;
262
263 StringRef::size_type Semi = Str.substr(Amp).find(';');
264 if (Semi == StringRef::npos) {
265 // Malformed input; do the best we can.
266 OS << '&';
267 Str = Str.substr(Amp + 1);
268 continue;
269 }
270
271 char Unescaped = llvm::StringSwitch<char>(Str.substr(Amp + 1, Semi - 1))
272 .Case("lt", '<')
273 .Case("gt", '>')
274 .Case("amp", '&')
275 .Case("quot", '"')
276 .Case("apos", '\'')
277 .Default('\0');
278
279 if (Unescaped)
280 OS << Unescaped;
281 else
282 OS << Str.substr(Amp, Semi + 1);
283 Str = Str.substr(Amp + Semi + 1);
284 }
285
286 return OS.str();
287 }
288}
289
290void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const {
291 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
292 switch (C->Kind) {
293 case CK_TypedText:
294 OS << "<typed-text>" << EscapedString(C->Text) << "</>";
295 break;
296 case CK_Text:
297 OS << "<text>" << EscapedString(C->Text) << "</>";
298 break;
299 case CK_Optional:
300 OS << "<optional>";
301 C->Optional->Serialize(OS);
302 OS << "</>";
303 break;
304 case CK_Placeholder:
305 OS << "<placeholder>" << EscapedString(C->Text) << "</>";
306 break;
307 case CK_Informative:
308 OS << "<informative>" << EscapedString(C->Text) << "</>";
309 break;
310 case CK_CurrentParameter:
311 OS << "<current-parameter>" << EscapedString(C->Text) << "</>";
312 break;
313 case CK_LeftParen:
314 OS << "<lparen/>";
315 break;
316 case CK_RightParen:
317 OS << "<rparen/>";
318 break;
319 case CK_LeftBracket:
320 OS << "<lbracket/>";
321 break;
322 case CK_RightBracket:
323 OS << "<rbracket/>";
324 break;
325 case CK_LeftBrace:
326 OS << "<lbrace/>";
327 break;
328 case CK_RightBrace:
329 OS << "<rbrace/>";
330 break;
331 case CK_LeftAngle:
332 OS << "<langle/>";
333 break;
334 case CK_RightAngle:
335 OS << "<rangle/>";
336 break;
337 case CK_Comma:
338 OS << "<comma/>";
339 break;
340 }
341 }
342}
343
344/// \brief Parse the next XML-ish tag of the form <blah>.
345///
346/// \param Str the string in which we're looking for the next tag.
347///
348/// \param TagPos if successful, will be set to the start of the tag we found.
349///
350/// \param Standalone will indicate whether this is a "standalone" tag that
351/// has no associated data, e.g., <comma/>.
352///
353/// \param Terminator will indicate whether this is a terminating tag (that is
354/// or starts with '/').
355///
356/// \returns the tag itself, without the angle brackets.
357static llvm::StringRef ParseNextTag(llvm::StringRef Str,
358 llvm::StringRef::size_type &StartTag,
359 llvm::StringRef::size_type &AfterTag,
360 bool &Standalone, bool &Terminator) {
361 using llvm::StringRef;
362
363 Standalone = false;
364 Terminator = false;
365 AfterTag = StringRef::npos;
366
367 // Find the starting '<'.
368 StartTag = Str.find('<');
369 if (StartTag == StringRef::npos)
370 return llvm::StringRef();
371
372 // Find the corresponding '>'.
373 llvm::StringRef::size_type EndTag = Str.substr(StartTag).find('>');
374 if (EndTag == StringRef::npos)
375 return llvm::StringRef();
376 AfterTag = StartTag + EndTag + 1;
377
378 // Determine whether this is a terminating tag.
379 if (Str[StartTag + 1] == '/') {
380 Terminator = true;
381 Str = Str.substr(1);
382 --EndTag;
383 }
384
385 // Determine whether this is a standalone tag.
386 if (!Terminator && Str[StartTag + EndTag - 1] == '/') {
387 Standalone = true;
388 if (EndTag > 1)
389 --EndTag;
390 }
391
392 return Str.substr(StartTag + 1, EndTag - 1);
393}
394
395CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) {
396 using llvm::StringRef;
397
398 CodeCompletionString *Result = new CodeCompletionString;
399
400 do {
401 // Parse the next tag.
402 StringRef::size_type StartTag, AfterTag;
403 bool Standalone, Terminator;
404 StringRef Tag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
405 Terminator);
406
407 if (StartTag == StringRef::npos)
408 break;
409
410 // Figure out what kind of chunk we have.
411 const unsigned UnknownKind = 10000;
412 unsigned Kind = llvm::StringSwitch<unsigned>(Tag)
413 .Case("typed-text", CK_TypedText)
414 .Case("text", CK_Text)
415 .Case("optional", CK_Optional)
416 .Case("placeholder", CK_Placeholder)
417 .Case("informative", CK_Informative)
418 .Case("current-parameter", CK_CurrentParameter)
419 .Case("lparen", CK_LeftParen)
420 .Case("rparen", CK_RightParen)
421 .Case("lbracket", CK_LeftBracket)
422 .Case("rbracket", CK_RightBracket)
423 .Case("lbrace", CK_LeftBrace)
424 .Case("rbrace", CK_RightBrace)
425 .Case("langle", CK_LeftAngle)
426 .Case("rangle", CK_RightAngle)
427 .Case("comma", CK_Comma)
428 .Default(UnknownKind);
429
430 // If we've hit a terminator tag, we're done.
431 if (Terminator)
432 break;
433
434 // Consume the tag.
435 Str = Str.substr(AfterTag);
436
437 // Handle standalone tags now, since they don't need to be matched to
438 // anything.
439 if (Standalone) {
440 // Ignore anything we don't know about.
441 if (Kind == UnknownKind)
442 continue;
443
444 switch ((ChunkKind)Kind) {
445 case CK_TypedText:
446 case CK_Text:
447 case CK_Optional:
448 case CK_Placeholder:
449 case CK_Informative:
450 case CK_CurrentParameter:
451 // There is no point in creating empty chunks of these kinds.
452 break;
453
454 case CK_LeftParen:
455 case CK_RightParen:
456 case CK_LeftBracket:
457 case CK_RightBracket:
458 case CK_LeftBrace:
459 case CK_RightBrace:
460 case CK_LeftAngle:
461 case CK_RightAngle:
462 case CK_Comma:
463 Result->AddChunk(Chunk((ChunkKind)Kind));
464 break;
465 }
466
467 continue;
468 }
469
470 if (Kind == CK_Optional) {
471 // Deserialize the optional code-completion string.
472 std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str));
473 Result->AddOptionalChunk(Optional);
474 }
475
476 StringRef EndTag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
477 Terminator);
478 if (StartTag == StringRef::npos || !Terminator || Standalone)
479 break; // Parsing failed; just give up.
480
481 if (EndTag.empty() || Tag == EndTag) {
482 // Found the matching end tag. Add this chunk based on the text
483 // between the tags, then consume that input.
484 StringRef Text = Str.substr(0, StartTag);
485 switch ((ChunkKind)Kind) {
486 case CK_TypedText:
487 case CK_Text:
488 case CK_Placeholder:
489 case CK_Informative:
490 case CK_CurrentParameter:
491 case CK_LeftParen:
492 case CK_RightParen:
493 case CK_LeftBracket:
494 case CK_RightBracket:
495 case CK_LeftBrace:
496 case CK_RightBrace:
497 case CK_LeftAngle:
498 case CK_RightAngle:
499 case CK_Comma:
500 Result->AddChunk(Chunk((ChunkKind)Kind, UnescapeString(Text)));
501 break;
502
503 case CK_Optional:
504 // We've already added the optional chunk.
505 break;
506 }
507 }
508
509 // Remove this tag.
510 Str = Str.substr(AfterTag);
511 } while (!Str.empty());
512
513 return Result;
514}
515
Douglas Gregor45f83ee2009-11-19 00:01:57 +0000516void CodeCompleteConsumer::Result::Destroy() {
517 if (Kind == RK_Pattern) {
518 delete Pattern;
519 Pattern = 0;
520 }
521}
522
Douglas Gregorfedc3282009-09-18 22:15:54 +0000523//===----------------------------------------------------------------------===//
Douglas Gregor05f477c2009-09-23 00:16:58 +0000524// Code completion overload candidate implementation
525//===----------------------------------------------------------------------===//
526FunctionDecl *
527CodeCompleteConsumer::OverloadCandidate::getFunction() const {
528 if (getKind() == CK_Function)
529 return Function;
530 else if (getKind() == CK_FunctionTemplate)
531 return FunctionTemplate->getTemplatedDecl();
532 else
533 return 0;
534}
535
536const FunctionType *
537CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
538 switch (Kind) {
539 case CK_Function:
540 return Function->getType()->getAs<FunctionType>();
541
542 case CK_FunctionTemplate:
543 return FunctionTemplate->getTemplatedDecl()->getType()
544 ->getAs<FunctionType>();
545
546 case CK_FunctionType:
547 return Type;
548 }
549
550 return 0;
551}
552
553//===----------------------------------------------------------------------===//
Douglas Gregorfedc3282009-09-18 22:15:54 +0000554// Code completion consumer implementation
555//===----------------------------------------------------------------------===//
556
Douglas Gregor3545ff42009-09-21 16:56:56 +0000557CodeCompleteConsumer::~CodeCompleteConsumer() { }
Douglas Gregorfedc3282009-09-18 22:15:54 +0000558
Douglas Gregor2436e712009-09-17 21:32:03 +0000559void
Daniel Dunbar242ea9a2009-11-13 08:58:20 +0000560PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
561 Result *Results,
Douglas Gregor2436e712009-09-17 21:32:03 +0000562 unsigned NumResults) {
Douglas Gregor2436e712009-09-17 21:32:03 +0000563 // Print the results.
564 for (unsigned I = 0; I != NumResults; ++I) {
Douglas Gregor58acf322009-10-09 22:16:47 +0000565 OS << "COMPLETION: ";
Douglas Gregor2436e712009-09-17 21:32:03 +0000566 switch (Results[I].Kind) {
567 case Result::RK_Declaration:
568 OS << Results[I].Declaration->getNameAsString() << " : "
569 << Results[I].Rank;
570 if (Results[I].Hidden)
571 OS << " (Hidden)";
Douglas Gregor3545ff42009-09-21 16:56:56 +0000572 if (CodeCompletionString *CCS
573 = Results[I].CreateCodeCompletionString(SemaRef)) {
Douglas Gregorfedc3282009-09-18 22:15:54 +0000574 OS << " : " << CCS->getAsString();
575 delete CCS;
576 }
577
Douglas Gregor2436e712009-09-17 21:32:03 +0000578 OS << '\n';
579 break;
580
581 case Result::RK_Keyword:
582 OS << Results[I].Keyword << " : " << Results[I].Rank << '\n';
583 break;
Douglas Gregorf329c7c2009-10-30 16:50:04 +0000584
585 case Result::RK_Macro: {
586 OS << Results[I].Macro->getName() << " : " << Results[I].Rank;
587 if (CodeCompletionString *CCS
588 = Results[I].CreateCodeCompletionString(SemaRef)) {
589 OS << " : " << CCS->getAsString();
590 delete CCS;
591 }
592 OS << '\n';
593 break;
594 }
Douglas Gregor45f83ee2009-11-19 00:01:57 +0000595
596 case Result::RK_Pattern: {
597 OS << "Pattern : " << Results[I].Rank << " : "
598 << Results[I].Pattern->getAsString() << '\n';
599 break;
600 }
Douglas Gregor2436e712009-09-17 21:32:03 +0000601 }
602 }
603
604 // Once we've printed the code-completion results, suppress remaining
605 // diagnostics.
606 // FIXME: Move this somewhere else!
Douglas Gregor3545ff42009-09-21 16:56:56 +0000607 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
Douglas Gregor2436e712009-09-17 21:32:03 +0000608}
Douglas Gregor05f477c2009-09-23 00:16:58 +0000609
610void
Daniel Dunbar242ea9a2009-11-13 08:58:20 +0000611PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
612 unsigned CurrentArg,
Douglas Gregor05f477c2009-09-23 00:16:58 +0000613 OverloadCandidate *Candidates,
614 unsigned NumCandidates) {
615 for (unsigned I = 0; I != NumCandidates; ++I) {
Douglas Gregorf0f51982009-09-23 00:34:09 +0000616 if (CodeCompletionString *CCS
617 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
Douglas Gregor58acf322009-10-09 22:16:47 +0000618 OS << "OVERLOAD: " << CCS->getAsString() << "\n";
Douglas Gregorf0f51982009-09-23 00:34:09 +0000619 delete CCS;
Douglas Gregor05f477c2009-09-23 00:16:58 +0000620 }
621 }
622
623 // Once we've printed the code-completion results, suppress remaining
624 // diagnostics.
625 // FIXME: Move this somewhere else!
626 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
627}
Douglas Gregor9eb77012009-11-07 00:00:49 +0000628
629void
Daniel Dunbar242ea9a2009-11-13 08:58:20 +0000630CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
631 Result *Results,
Douglas Gregor9eb77012009-11-07 00:00:49 +0000632 unsigned NumResults) {
633 // Print the results.
634 for (unsigned I = 0; I != NumResults; ++I) {
635 OS << "COMPLETION:" << Results[I].Rank << ":";
636 switch (Results[I].Kind) {
637 case Result::RK_Declaration:
638 if (RecordDecl *Record = dyn_cast<RecordDecl>(Results[I].Declaration)) {
639 if (Record->isStruct())
640 OS << "Struct:";
641 else if (Record->isUnion())
642 OS << "Union:";
643 else
644 OS << "Class:";
645 } else if (ObjCMethodDecl *Method
646 = dyn_cast<ObjCMethodDecl>(Results[I].Declaration)) {
647 if (Method->isInstanceMethod())
648 OS << "ObjCInstanceMethod:";
649 else
650 OS << "ObjCClassMethod:";
651 } else {
652 OS << Results[I].Declaration->getDeclKindName() << ":";
653 }
654 if (CodeCompletionString *CCS
655 = Results[I].CreateCodeCompletionString(SemaRef)) {
656 CCS->Serialize(OS);
657 delete CCS;
658 } else {
659 OS << "<typed-text>"
660 << Results[I].Declaration->getNameAsString()
661 << "</>";
662 }
663
664 OS << '\n';
665 break;
666
667 case Result::RK_Keyword:
668 OS << "Keyword:<typed-text>" << Results[I].Keyword << "</>\n";
669 break;
670
671 case Result::RK_Macro: {
672 OS << "Macro:";
673 if (CodeCompletionString *CCS
674 = Results[I].CreateCodeCompletionString(SemaRef)) {
675 CCS->Serialize(OS);
676 delete CCS;
677 } else {
678 OS << "<typed-text>" << Results[I].Macro->getName() << "</>";
679 }
680 OS << '\n';
681 break;
682 }
Douglas Gregor45f83ee2009-11-19 00:01:57 +0000683
684 case Result::RK_Pattern: {
685 OS << "Pattern:";
686 Results[I].Pattern->Serialize(OS);
687 OS << '\n';
688 break;
689 }
Douglas Gregor9eb77012009-11-07 00:00:49 +0000690 }
691 }
692
693 // Once we've printed the code-completion results, suppress remaining
694 // diagnostics.
695 // FIXME: Move this somewhere else!
696 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
697}
698
699void
Daniel Dunbar242ea9a2009-11-13 08:58:20 +0000700CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
701 unsigned CurrentArg,
Douglas Gregor9eb77012009-11-07 00:00:49 +0000702 OverloadCandidate *Candidates,
703 unsigned NumCandidates) {
704 for (unsigned I = 0; I != NumCandidates; ++I) {
705 if (CodeCompletionString *CCS
706 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
707 OS << "OVERLOAD:";
708 CCS->Serialize(OS);
709 OS << '\n';
710 delete CCS;
711 }
712 }
713
714 // Once we've printed the code-completion results, suppress remaining
715 // diagnostics.
716 // FIXME: Move this somewhere else!
717 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
718}