blob: 88ac4e49cf9edb2d2fd412470be7846d4141e546 [file] [log] [blame]
Douglas Gregor86d9a522009-09-21 16:56:56 +00001//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===//
Douglas Gregor81b747b2009-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 Gregor75b71282009-09-18 17:54:00 +000014#include "clang/AST/DeclCXX.h"
Douglas Gregor374929f2009-09-18 15:37:17 +000015#include "clang/Parse/Scope.h"
Douglas Gregor81b747b2009-09-17 21:32:03 +000016#include "clang/Lex/Preprocessor.h"
17#include "Sema.h"
18#include "llvm/ADT/STLExtras.h"
Douglas Gregor0c8296d2009-11-07 00:00:49 +000019#include "llvm/ADT/StringSwitch.h"
Douglas Gregor81b747b2009-09-17 21:32:03 +000020#include "llvm/Support/Compiler.h"
21#include "llvm/Support/raw_ostream.h"
22#include <algorithm>
Douglas Gregore6e03612009-09-18 22:15:54 +000023#include <cstring>
24#include <functional>
Douglas Gregor92eff462009-11-17 16:43:05 +000025
Douglas Gregor81b747b2009-09-17 21:32:03 +000026using namespace clang;
Douglas Gregor92eff462009-11-17 16:43:05 +000027using llvm::StringRef;
Douglas Gregor81b747b2009-09-17 21:32:03 +000028
Douglas Gregore6e03612009-09-18 22:15:54 +000029//===----------------------------------------------------------------------===//
30// Code completion string implementation
31//===----------------------------------------------------------------------===//
Douglas Gregor0c8296d2009-11-07 00:00:49 +000032CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text)
Daniel Dunbarad5757f2009-11-12 18:40:12 +000033 : Kind(Kind), Text("")
Douglas Gregor0563c262009-09-22 23:15:58 +000034{
Douglas Gregor0c8296d2009-11-07 00:00:49 +000035 switch (Kind) {
36 case CK_TypedText:
37 case CK_Text:
38 case CK_Placeholder:
39 case CK_Informative:
40 case CK_CurrentParameter: {
41 char *New = new char [Text.size() + 1];
42 std::memcpy(New, Text.data(), Text.size());
43 New[Text.size()] = '\0';
44 this->Text = New;
45 break;
46 }
47
48 case CK_Optional:
49 llvm::llvm_unreachable("Optional strings cannot be created from text");
50 break;
51
52 case CK_LeftParen:
53 this->Text = "(";
54 break;
55
56 case CK_RightParen:
57 this->Text = ")";
58 break;
59
60 case CK_LeftBracket:
61 this->Text = "[";
62 break;
63
64 case CK_RightBracket:
65 this->Text = "]";
66 break;
67
68 case CK_LeftBrace:
69 this->Text = "{";
70 break;
71
72 case CK_RightBrace:
73 this->Text = "}";
74 break;
75
76 case CK_LeftAngle:
77 this->Text = "<";
78 break;
79
80 case CK_RightAngle:
81 this->Text = ">";
82 break;
83
84 case CK_Comma:
85 this->Text = ", ";
86 break;
87 }
Douglas Gregor0563c262009-09-22 23:15:58 +000088}
89
90CodeCompletionString::Chunk
Douglas Gregor92eff462009-11-17 16:43:05 +000091CodeCompletionString::Chunk::CreateText(StringRef Text) {
Douglas Gregor0563c262009-09-22 23:15:58 +000092 return Chunk(CK_Text, Text);
Douglas Gregore6e03612009-09-18 22:15:54 +000093}
94
95CodeCompletionString::Chunk
96CodeCompletionString::Chunk::CreateOptional(
97 std::auto_ptr<CodeCompletionString> Optional) {
98 Chunk Result;
99 Result.Kind = CK_Optional;
100 Result.Optional = Optional.release();
101 return Result;
102}
103
104CodeCompletionString::Chunk
Douglas Gregor92eff462009-11-17 16:43:05 +0000105CodeCompletionString::Chunk::CreatePlaceholder(StringRef Placeholder) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000106 return Chunk(CK_Placeholder, Placeholder);
107}
108
109CodeCompletionString::Chunk
Douglas Gregor92eff462009-11-17 16:43:05 +0000110CodeCompletionString::Chunk::CreateInformative(StringRef Informative) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000111 return Chunk(CK_Informative, Informative);
Douglas Gregore6e03612009-09-18 22:15:54 +0000112}
113
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000114CodeCompletionString::Chunk
115CodeCompletionString::Chunk::CreateCurrentParameter(
Douglas Gregor92eff462009-11-17 16:43:05 +0000116 StringRef CurrentParameter) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000117 return Chunk(CK_CurrentParameter, CurrentParameter);
118}
119
120
Douglas Gregore6e03612009-09-18 22:15:54 +0000121void
122CodeCompletionString::Chunk::Destroy() {
123 switch (Kind) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000124 case CK_Optional:
125 delete Optional;
126 break;
127
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000128 case CK_TypedText:
Douglas Gregor0563c262009-09-22 23:15:58 +0000129 case CK_Text:
130 case CK_Placeholder:
131 case CK_Informative:
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000132 case CK_CurrentParameter:
133 delete [] Text;
134 break;
135
136 case CK_LeftParen:
137 case CK_RightParen:
138 case CK_LeftBracket:
139 case CK_RightBracket:
140 case CK_LeftBrace:
141 case CK_RightBrace:
142 case CK_LeftAngle:
143 case CK_RightAngle:
144 case CK_Comma:
Douglas Gregor0563c262009-09-22 23:15:58 +0000145 break;
Douglas Gregore6e03612009-09-18 22:15:54 +0000146 }
147}
148
149CodeCompletionString::~CodeCompletionString() {
150 std::for_each(Chunks.begin(), Chunks.end(),
151 std::mem_fun_ref(&Chunk::Destroy));
152}
153
154std::string CodeCompletionString::getAsString() const {
155 std::string Result;
156 llvm::raw_string_ostream OS(Result);
157
158 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
159 switch (C->Kind) {
Douglas Gregore6e03612009-09-18 22:15:54 +0000160 case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
Douglas Gregor0563c262009-09-22 23:15:58 +0000161 case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
162 case CK_Informative: OS << "[#" << C->Text << "#]"; break;
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000163 case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
164 default: OS << C->Text; break;
Douglas Gregore6e03612009-09-18 22:15:54 +0000165 }
166 }
Douglas Gregore2b7eea2009-09-29 15:13:39 +0000167 OS.flush();
Douglas Gregore6e03612009-09-18 22:15:54 +0000168 return Result;
169}
170
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000171
172namespace {
173 // Escape a string for XML-like formatting.
174 struct EscapedString {
175 EscapedString(llvm::StringRef Str) : Str(Str) { }
176
177 llvm::StringRef Str;
178 };
179
180 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, EscapedString EStr) {
181 llvm::StringRef Str = EStr.Str;
182 while (!Str.empty()) {
183 // Find the next escaped character.
184 llvm::StringRef::size_type Pos = Str.find_first_of("<>&\"'");
185
186 // Print everything before that escaped character.
187 OS << Str.substr(0, Pos);
188
189 // If we didn't find any escaped characters, we're done.
190 if (Pos == llvm::StringRef::npos)
191 break;
192
193 // Print the appropriate escape sequence.
194 switch (Str[Pos]) {
195 case '<': OS << "&lt;"; break;
196 case '>': OS << "&gt;"; break;
197 case '&': OS << "&amp;"; break;
198 case '"': OS << "&quot;"; break;
199 case '\'': OS << "&apos;"; break;
200 }
201
202 // Remove everything up to and including that escaped character.
203 Str = Str.substr(Pos + 1);
204 }
205
206 return OS;
207 }
208
209 /// \brief Remove XML-like escaping from a string.
210 std::string UnescapeString(llvm::StringRef Str) {
211 using llvm::StringRef;
212
213 std::string Result;
214 llvm::raw_string_ostream OS(Result);
215
216 while (!Str.empty()) {
217 StringRef::size_type Amp = Str.find('&');
218 OS << Str.substr(0, Amp);
219
220 if (Amp == StringRef::npos)
221 break;
222
223 StringRef::size_type Semi = Str.substr(Amp).find(';');
224 if (Semi == StringRef::npos) {
225 // Malformed input; do the best we can.
226 OS << '&';
227 Str = Str.substr(Amp + 1);
228 continue;
229 }
230
231 char Unescaped = llvm::StringSwitch<char>(Str.substr(Amp + 1, Semi - 1))
232 .Case("lt", '<')
233 .Case("gt", '>')
234 .Case("amp", '&')
235 .Case("quot", '"')
236 .Case("apos", '\'')
237 .Default('\0');
238
239 if (Unescaped)
240 OS << Unescaped;
241 else
242 OS << Str.substr(Amp, Semi + 1);
243 Str = Str.substr(Amp + Semi + 1);
244 }
245
246 return OS.str();
247 }
248}
249
250void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const {
251 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
252 switch (C->Kind) {
253 case CK_TypedText:
254 OS << "<typed-text>" << EscapedString(C->Text) << "</>";
255 break;
256 case CK_Text:
257 OS << "<text>" << EscapedString(C->Text) << "</>";
258 break;
259 case CK_Optional:
260 OS << "<optional>";
261 C->Optional->Serialize(OS);
262 OS << "</>";
263 break;
264 case CK_Placeholder:
265 OS << "<placeholder>" << EscapedString(C->Text) << "</>";
266 break;
267 case CK_Informative:
268 OS << "<informative>" << EscapedString(C->Text) << "</>";
269 break;
270 case CK_CurrentParameter:
271 OS << "<current-parameter>" << EscapedString(C->Text) << "</>";
272 break;
273 case CK_LeftParen:
274 OS << "<lparen/>";
275 break;
276 case CK_RightParen:
277 OS << "<rparen/>";
278 break;
279 case CK_LeftBracket:
280 OS << "<lbracket/>";
281 break;
282 case CK_RightBracket:
283 OS << "<rbracket/>";
284 break;
285 case CK_LeftBrace:
286 OS << "<lbrace/>";
287 break;
288 case CK_RightBrace:
289 OS << "<rbrace/>";
290 break;
291 case CK_LeftAngle:
292 OS << "<langle/>";
293 break;
294 case CK_RightAngle:
295 OS << "<rangle/>";
296 break;
297 case CK_Comma:
298 OS << "<comma/>";
299 break;
300 }
301 }
302}
303
304/// \brief Parse the next XML-ish tag of the form <blah>.
305///
306/// \param Str the string in which we're looking for the next tag.
307///
308/// \param TagPos if successful, will be set to the start of the tag we found.
309///
310/// \param Standalone will indicate whether this is a "standalone" tag that
311/// has no associated data, e.g., <comma/>.
312///
313/// \param Terminator will indicate whether this is a terminating tag (that is
314/// or starts with '/').
315///
316/// \returns the tag itself, without the angle brackets.
317static llvm::StringRef ParseNextTag(llvm::StringRef Str,
318 llvm::StringRef::size_type &StartTag,
319 llvm::StringRef::size_type &AfterTag,
320 bool &Standalone, bool &Terminator) {
321 using llvm::StringRef;
322
323 Standalone = false;
324 Terminator = false;
325 AfterTag = StringRef::npos;
326
327 // Find the starting '<'.
328 StartTag = Str.find('<');
329 if (StartTag == StringRef::npos)
330 return llvm::StringRef();
331
332 // Find the corresponding '>'.
333 llvm::StringRef::size_type EndTag = Str.substr(StartTag).find('>');
334 if (EndTag == StringRef::npos)
335 return llvm::StringRef();
336 AfterTag = StartTag + EndTag + 1;
337
338 // Determine whether this is a terminating tag.
339 if (Str[StartTag + 1] == '/') {
340 Terminator = true;
341 Str = Str.substr(1);
342 --EndTag;
343 }
344
345 // Determine whether this is a standalone tag.
346 if (!Terminator && Str[StartTag + EndTag - 1] == '/') {
347 Standalone = true;
348 if (EndTag > 1)
349 --EndTag;
350 }
351
352 return Str.substr(StartTag + 1, EndTag - 1);
353}
354
355CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) {
356 using llvm::StringRef;
357
358 CodeCompletionString *Result = new CodeCompletionString;
359
360 do {
361 // Parse the next tag.
362 StringRef::size_type StartTag, AfterTag;
363 bool Standalone, Terminator;
364 StringRef Tag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
365 Terminator);
366
367 if (StartTag == StringRef::npos)
368 break;
369
370 // Figure out what kind of chunk we have.
371 const unsigned UnknownKind = 10000;
372 unsigned Kind = llvm::StringSwitch<unsigned>(Tag)
373 .Case("typed-text", CK_TypedText)
374 .Case("text", CK_Text)
375 .Case("optional", CK_Optional)
376 .Case("placeholder", CK_Placeholder)
377 .Case("informative", CK_Informative)
378 .Case("current-parameter", CK_CurrentParameter)
379 .Case("lparen", CK_LeftParen)
380 .Case("rparen", CK_RightParen)
381 .Case("lbracket", CK_LeftBracket)
382 .Case("rbracket", CK_RightBracket)
383 .Case("lbrace", CK_LeftBrace)
384 .Case("rbrace", CK_RightBrace)
385 .Case("langle", CK_LeftAngle)
386 .Case("rangle", CK_RightAngle)
387 .Case("comma", CK_Comma)
388 .Default(UnknownKind);
389
390 // If we've hit a terminator tag, we're done.
391 if (Terminator)
392 break;
393
394 // Consume the tag.
395 Str = Str.substr(AfterTag);
396
397 // Handle standalone tags now, since they don't need to be matched to
398 // anything.
399 if (Standalone) {
400 // Ignore anything we don't know about.
401 if (Kind == UnknownKind)
402 continue;
403
404 switch ((ChunkKind)Kind) {
405 case CK_TypedText:
406 case CK_Text:
407 case CK_Optional:
408 case CK_Placeholder:
409 case CK_Informative:
410 case CK_CurrentParameter:
411 // There is no point in creating empty chunks of these kinds.
412 break;
413
414 case CK_LeftParen:
415 case CK_RightParen:
416 case CK_LeftBracket:
417 case CK_RightBracket:
418 case CK_LeftBrace:
419 case CK_RightBrace:
420 case CK_LeftAngle:
421 case CK_RightAngle:
422 case CK_Comma:
423 Result->AddChunk(Chunk((ChunkKind)Kind));
424 break;
425 }
426
427 continue;
428 }
429
430 if (Kind == CK_Optional) {
431 // Deserialize the optional code-completion string.
432 std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str));
433 Result->AddOptionalChunk(Optional);
434 }
435
436 StringRef EndTag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
437 Terminator);
438 if (StartTag == StringRef::npos || !Terminator || Standalone)
439 break; // Parsing failed; just give up.
440
441 if (EndTag.empty() || Tag == EndTag) {
442 // Found the matching end tag. Add this chunk based on the text
443 // between the tags, then consume that input.
444 StringRef Text = Str.substr(0, StartTag);
445 switch ((ChunkKind)Kind) {
446 case CK_TypedText:
447 case CK_Text:
448 case CK_Placeholder:
449 case CK_Informative:
450 case CK_CurrentParameter:
451 case CK_LeftParen:
452 case CK_RightParen:
453 case CK_LeftBracket:
454 case CK_RightBracket:
455 case CK_LeftBrace:
456 case CK_RightBrace:
457 case CK_LeftAngle:
458 case CK_RightAngle:
459 case CK_Comma:
460 Result->AddChunk(Chunk((ChunkKind)Kind, UnescapeString(Text)));
461 break;
462
463 case CK_Optional:
464 // We've already added the optional chunk.
465 break;
466 }
467 }
468
469 // Remove this tag.
470 Str = Str.substr(AfterTag);
471 } while (!Str.empty());
472
473 return Result;
474}
475
Douglas Gregore6e03612009-09-18 22:15:54 +0000476//===----------------------------------------------------------------------===//
Douglas Gregor05944382009-09-23 00:16:58 +0000477// Code completion overload candidate implementation
478//===----------------------------------------------------------------------===//
479FunctionDecl *
480CodeCompleteConsumer::OverloadCandidate::getFunction() const {
481 if (getKind() == CK_Function)
482 return Function;
483 else if (getKind() == CK_FunctionTemplate)
484 return FunctionTemplate->getTemplatedDecl();
485 else
486 return 0;
487}
488
489const FunctionType *
490CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
491 switch (Kind) {
492 case CK_Function:
493 return Function->getType()->getAs<FunctionType>();
494
495 case CK_FunctionTemplate:
496 return FunctionTemplate->getTemplatedDecl()->getType()
497 ->getAs<FunctionType>();
498
499 case CK_FunctionType:
500 return Type;
501 }
502
503 return 0;
504}
505
506//===----------------------------------------------------------------------===//
Douglas Gregore6e03612009-09-18 22:15:54 +0000507// Code completion consumer implementation
508//===----------------------------------------------------------------------===//
509
Douglas Gregor86d9a522009-09-21 16:56:56 +0000510CodeCompleteConsumer::~CodeCompleteConsumer() { }
Douglas Gregore6e03612009-09-18 22:15:54 +0000511
Douglas Gregor81b747b2009-09-17 21:32:03 +0000512void
Daniel Dunbar3a2838d2009-11-13 08:58:20 +0000513PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
514 Result *Results,
Douglas Gregor81b747b2009-09-17 21:32:03 +0000515 unsigned NumResults) {
Douglas Gregor81b747b2009-09-17 21:32:03 +0000516 // Print the results.
517 for (unsigned I = 0; I != NumResults; ++I) {
Douglas Gregorf52cede2009-10-09 22:16:47 +0000518 OS << "COMPLETION: ";
Douglas Gregor81b747b2009-09-17 21:32:03 +0000519 switch (Results[I].Kind) {
520 case Result::RK_Declaration:
521 OS << Results[I].Declaration->getNameAsString() << " : "
522 << Results[I].Rank;
523 if (Results[I].Hidden)
524 OS << " (Hidden)";
Douglas Gregor86d9a522009-09-21 16:56:56 +0000525 if (CodeCompletionString *CCS
526 = Results[I].CreateCodeCompletionString(SemaRef)) {
Douglas Gregore6e03612009-09-18 22:15:54 +0000527 OS << " : " << CCS->getAsString();
528 delete CCS;
529 }
530
Douglas Gregor81b747b2009-09-17 21:32:03 +0000531 OS << '\n';
532 break;
533
534 case Result::RK_Keyword:
535 OS << Results[I].Keyword << " : " << Results[I].Rank << '\n';
536 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +0000537
538 case Result::RK_Macro: {
539 OS << Results[I].Macro->getName() << " : " << Results[I].Rank;
540 if (CodeCompletionString *CCS
541 = Results[I].CreateCodeCompletionString(SemaRef)) {
542 OS << " : " << CCS->getAsString();
543 delete CCS;
544 }
545 OS << '\n';
546 break;
547 }
Douglas Gregor81b747b2009-09-17 21:32:03 +0000548 }
549 }
550
551 // Once we've printed the code-completion results, suppress remaining
552 // diagnostics.
553 // FIXME: Move this somewhere else!
Douglas Gregor86d9a522009-09-21 16:56:56 +0000554 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
Douglas Gregor81b747b2009-09-17 21:32:03 +0000555}
Douglas Gregor05944382009-09-23 00:16:58 +0000556
557void
Daniel Dunbar3a2838d2009-11-13 08:58:20 +0000558PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
559 unsigned CurrentArg,
Douglas Gregor05944382009-09-23 00:16:58 +0000560 OverloadCandidate *Candidates,
561 unsigned NumCandidates) {
562 for (unsigned I = 0; I != NumCandidates; ++I) {
Douglas Gregor86d802e2009-09-23 00:34:09 +0000563 if (CodeCompletionString *CCS
564 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
Douglas Gregorf52cede2009-10-09 22:16:47 +0000565 OS << "OVERLOAD: " << CCS->getAsString() << "\n";
Douglas Gregor86d802e2009-09-23 00:34:09 +0000566 delete CCS;
Douglas Gregor05944382009-09-23 00:16:58 +0000567 }
568 }
569
570 // Once we've printed the code-completion results, suppress remaining
571 // diagnostics.
572 // FIXME: Move this somewhere else!
573 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
574}
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000575
576void
Daniel Dunbar3a2838d2009-11-13 08:58:20 +0000577CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
578 Result *Results,
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000579 unsigned NumResults) {
580 // Print the results.
581 for (unsigned I = 0; I != NumResults; ++I) {
582 OS << "COMPLETION:" << Results[I].Rank << ":";
583 switch (Results[I].Kind) {
584 case Result::RK_Declaration:
585 if (RecordDecl *Record = dyn_cast<RecordDecl>(Results[I].Declaration)) {
586 if (Record->isStruct())
587 OS << "Struct:";
588 else if (Record->isUnion())
589 OS << "Union:";
590 else
591 OS << "Class:";
592 } else if (ObjCMethodDecl *Method
593 = dyn_cast<ObjCMethodDecl>(Results[I].Declaration)) {
594 if (Method->isInstanceMethod())
595 OS << "ObjCInstanceMethod:";
596 else
597 OS << "ObjCClassMethod:";
598 } else {
599 OS << Results[I].Declaration->getDeclKindName() << ":";
600 }
601 if (CodeCompletionString *CCS
602 = Results[I].CreateCodeCompletionString(SemaRef)) {
603 CCS->Serialize(OS);
604 delete CCS;
605 } else {
606 OS << "<typed-text>"
607 << Results[I].Declaration->getNameAsString()
608 << "</>";
609 }
610
611 OS << '\n';
612 break;
613
614 case Result::RK_Keyword:
615 OS << "Keyword:<typed-text>" << Results[I].Keyword << "</>\n";
616 break;
617
618 case Result::RK_Macro: {
619 OS << "Macro:";
620 if (CodeCompletionString *CCS
621 = Results[I].CreateCodeCompletionString(SemaRef)) {
622 CCS->Serialize(OS);
623 delete CCS;
624 } else {
625 OS << "<typed-text>" << Results[I].Macro->getName() << "</>";
626 }
627 OS << '\n';
628 break;
629 }
630 }
631 }
632
633 // Once we've printed the code-completion results, suppress remaining
634 // diagnostics.
635 // FIXME: Move this somewhere else!
636 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
637}
638
639void
Daniel Dunbar3a2838d2009-11-13 08:58:20 +0000640CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
641 unsigned CurrentArg,
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000642 OverloadCandidate *Candidates,
643 unsigned NumCandidates) {
644 for (unsigned I = 0; I != NumCandidates; ++I) {
645 if (CodeCompletionString *CCS
646 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
647 OS << "OVERLOAD:";
648 CCS->Serialize(OS);
649 OS << '\n';
650 delete CCS;
651 }
652 }
653
654 // Once we've printed the code-completion results, suppress remaining
655 // diagnostics.
656 // FIXME: Move this somewhere else!
657 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
658}