Deleted Added
full compact
CodeCompleteConsumer.cpp (199512) CodeCompleteConsumer.cpp (199990)
1//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===//
2//
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"
14#include "clang/AST/DeclCXX.h"
15#include "clang/Parse/Scope.h"
16#include "clang/Lex/Preprocessor.h"
1//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===//
2//
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"
14#include "clang/AST/DeclCXX.h"
15#include "clang/Parse/Scope.h"
16#include "clang/Lex/Preprocessor.h"
17#include "clang-c/Index.h"
17#include "Sema.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringSwitch.h"
18#include "Sema.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/StringSwitch.h"
20#include "llvm/Support/Compiler.h"
21#include "llvm/Support/raw_ostream.h"
22#include <algorithm>
23#include <cstring>
24#include <functional>
25
26using namespace clang;
27using llvm::StringRef;
28

--- 176 unchanged lines hidden (view full) ---

205
206CodeCompletionString *CodeCompletionString::Clone() const {
207 CodeCompletionString *Result = new CodeCompletionString;
208 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
209 Result->AddChunk(C->Clone());
210 return Result;
211}
212
21#include "llvm/Support/raw_ostream.h"
22#include <algorithm>
23#include <cstring>
24#include <functional>
25
26using namespace clang;
27using llvm::StringRef;
28

--- 176 unchanged lines hidden (view full) ---

205
206CodeCompletionString *CodeCompletionString::Clone() const {
207 CodeCompletionString *Result = new CodeCompletionString;
208 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
209 Result->AddChunk(C->Clone());
210 return Result;
211}
212
213namespace {
214 // Escape a string for XML-like formatting.
215 struct EscapedString {
216 EscapedString(llvm::StringRef Str) : Str(Str) { }
217
218 llvm::StringRef Str;
219 };
220
221 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, EscapedString EStr) {
222 llvm::StringRef Str = EStr.Str;
223 while (!Str.empty()) {
224 // Find the next escaped character.
225 llvm::StringRef::size_type Pos = Str.find_first_of("<>&\"'");
226
227 // Print everything before that escaped character.
228 OS << Str.substr(0, Pos);
213static void WriteUnsigned(llvm::raw_ostream &OS, unsigned Value) {
214 OS.write((const char *)&Value, sizeof(unsigned));
215}
229
216
230 // If we didn't find any escaped characters, we're done.
231 if (Pos == llvm::StringRef::npos)
232 break;
233
234 // Print the appropriate escape sequence.
235 switch (Str[Pos]) {
236 case '<': OS << "&lt;"; break;
237 case '>': OS << "&gt;"; break;
238 case '&': OS << "&amp;"; break;
239 case '"': OS << "&quot;"; break;
240 case '\'': OS << "&apos;"; break;
241 }
242
243 // Remove everything up to and including that escaped character.
244 Str = Str.substr(Pos + 1);
245 }
246
247 return OS;
248 }
249
250 /// \brief Remove XML-like escaping from a string.
251 std::string UnescapeString(llvm::StringRef Str) {
252 using llvm::StringRef;
253
254 std::string Result;
255 llvm::raw_string_ostream OS(Result);
256
257 while (!Str.empty()) {
258 StringRef::size_type Amp = Str.find('&');
259 OS << Str.substr(0, Amp);
260
261 if (Amp == StringRef::npos)
262 break;
263
264 StringRef::size_type Semi = Str.substr(Amp).find(';');
265 if (Semi == StringRef::npos) {
266 // Malformed input; do the best we can.
267 OS << '&';
268 Str = Str.substr(Amp + 1);
269 continue;
270 }
271
272 char Unescaped = llvm::StringSwitch<char>(Str.substr(Amp + 1, Semi - 1))
273 .Case("lt", '<')
274 .Case("gt", '>')
275 .Case("amp", '&')
276 .Case("quot", '"')
277 .Case("apos", '\'')
278 .Default('\0');
279
280 if (Unescaped)
281 OS << Unescaped;
282 else
283 OS << Str.substr(Amp, Semi + 1);
284 Str = Str.substr(Amp + Semi + 1);
285 }
286
287 return OS.str();
288 }
217static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd,
218 unsigned &Value) {
219 if (Memory + sizeof(unsigned) > MemoryEnd)
220 return true;
221
222 memmove(&Value, Memory, sizeof(unsigned));
223 Memory += sizeof(unsigned);
224 return false;
289}
290
291void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const {
225}
226
227void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const {
228 // Write the number of chunks.
229 WriteUnsigned(OS, size());
230
292 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
231 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
232 WriteUnsigned(OS, C->Kind);
233
293 switch (C->Kind) {
294 case CK_TypedText:
234 switch (C->Kind) {
235 case CK_TypedText:
295 OS << "<typed-text>" << EscapedString(C->Text) << "</>";
296 break;
297 case CK_Text:
236 case CK_Text:
298 OS << "<text>" << EscapedString(C->Text) << "</>";
237 case CK_Placeholder:
238 case CK_Informative:
239 case CK_CurrentParameter: {
240 const char *Text = C->Text;
241 unsigned StrLen = strlen(Text);
242 WriteUnsigned(OS, StrLen);
243 OS.write(Text, StrLen);
299 break;
244 break;
245 }
246
300 case CK_Optional:
247 case CK_Optional:
301 OS << "<optional>";
302 C->Optional->Serialize(OS);
248 C->Optional->Serialize(OS);
303 OS << "</>";
304 break;
249 break;
305 case CK_Placeholder:
306 OS << "<placeholder>" << EscapedString(C->Text) << "</>";
307 break;
308 case CK_Informative:
309 OS << "<informative>" << EscapedString(C->Text) << "</>";
310 break;
311 case CK_CurrentParameter:
312 OS << "<current-parameter>" << EscapedString(C->Text) << "</>";
313 break;
250
314 case CK_LeftParen:
251 case CK_LeftParen:
315 OS << "<lparen/>";
316 break;
317 case CK_RightParen:
252 case CK_RightParen:
318 OS << "<rparen/>";
319 break;
320 case CK_LeftBracket:
253 case CK_LeftBracket:
321 OS << "<lbracket/>";
322 break;
323 case CK_RightBracket:
254 case CK_RightBracket:
324 OS << "<rbracket/>";
325 break;
326 case CK_LeftBrace:
255 case CK_LeftBrace:
327 OS << "<lbrace/>";
328 break;
329 case CK_RightBrace:
256 case CK_RightBrace:
330 OS << "<rbrace/>";
331 break;
332 case CK_LeftAngle:
257 case CK_LeftAngle:
333 OS << "<langle/>";
334 break;
335 case CK_RightAngle:
258 case CK_RightAngle:
336 OS << "<rangle/>";
337 break;
338 case CK_Comma:
259 case CK_Comma:
339 OS << "<comma/>";
340 break;
260 break;
341 }
261 }
342 }
343}
344
262 }
263}
264
345/// \brief Parse the next XML-ish tag of the form <blah>.
346///
347/// \param Str the string in which we're looking for the next tag.
348///
349/// \param TagPos if successful, will be set to the start of the tag we found.
350///
351/// \param Standalone will indicate whether this is a "standalone" tag that
352/// has no associated data, e.g., <comma/>.
353///
354/// \param Terminator will indicate whether this is a terminating tag (that is
355/// or starts with '/').
356///
357/// \returns the tag itself, without the angle brackets.
358static llvm::StringRef ParseNextTag(llvm::StringRef Str,
359 llvm::StringRef::size_type &StartTag,
360 llvm::StringRef::size_type &AfterTag,
361 bool &Standalone, bool &Terminator) {
362 using llvm::StringRef;
363
364 Standalone = false;
365 Terminator = false;
366 AfterTag = StringRef::npos;
367
368 // Find the starting '<'.
369 StartTag = Str.find('<');
370 if (StartTag == StringRef::npos)
371 return llvm::StringRef();
372
373 // Find the corresponding '>'.
374 llvm::StringRef::size_type EndTag = Str.substr(StartTag).find('>');
375 if (EndTag == StringRef::npos)
376 return llvm::StringRef();
377 AfterTag = StartTag + EndTag + 1;
378
379 // Determine whether this is a terminating tag.
380 if (Str[StartTag + 1] == '/') {
381 Terminator = true;
382 Str = Str.substr(1);
383 --EndTag;
384 }
385
386 // Determine whether this is a standalone tag.
387 if (!Terminator && Str[StartTag + EndTag - 1] == '/') {
388 Standalone = true;
389 if (EndTag > 1)
390 --EndTag;
391 }
265CodeCompletionString *CodeCompletionString::Deserialize(const char *&Str,
266 const char *StrEnd) {
267 if (Str == StrEnd || *Str == 0)
268 return 0;
392
269
393 return Str.substr(StartTag + 1, EndTag - 1);
394}
395
396CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) {
397 using llvm::StringRef;
398
399 CodeCompletionString *Result = new CodeCompletionString;
270 CodeCompletionString *Result = new CodeCompletionString;
400
401 do {
402 // Parse the next tag.
403 StringRef::size_type StartTag, AfterTag;
404 bool Standalone, Terminator;
405 StringRef Tag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
406 Terminator);
407
408 if (StartTag == StringRef::npos)
271 unsigned NumBlocks;
272 if (ReadUnsigned(Str, StrEnd, NumBlocks))
273 return Result;
274
275 for (unsigned I = 0; I != NumBlocks; ++I) {
276 if (Str + 1 >= StrEnd)
409 break;
277 break;
410
411 // Figure out what kind of chunk we have.
412 const unsigned UnknownKind = 10000;
413 unsigned Kind = llvm::StringSwitch<unsigned>(Tag)
414 .Case("typed-text", CK_TypedText)
415 .Case("text", CK_Text)
416 .Case("optional", CK_Optional)
417 .Case("placeholder", CK_Placeholder)
418 .Case("informative", CK_Informative)
419 .Case("current-parameter", CK_CurrentParameter)
420 .Case("lparen", CK_LeftParen)
421 .Case("rparen", CK_RightParen)
422 .Case("lbracket", CK_LeftBracket)
423 .Case("rbracket", CK_RightBracket)
424 .Case("lbrace", CK_LeftBrace)
425 .Case("rbrace", CK_RightBrace)
426 .Case("langle", CK_LeftAngle)
427 .Case("rangle", CK_RightAngle)
428 .Case("comma", CK_Comma)
429 .Default(UnknownKind);
430
431 // If we've hit a terminator tag, we're done.
432 if (Terminator)
433 break;
434
435 // Consume the tag.
436 Str = Str.substr(AfterTag);
437
278
438 // Handle standalone tags now, since they don't need to be matched to
439 // anything.
440 if (Standalone) {
441 // Ignore anything we don't know about.
442 if (Kind == UnknownKind)
443 continue;
444
445 switch ((ChunkKind)Kind) {
446 case CK_TypedText:
447 case CK_Text:
448 case CK_Optional:
449 case CK_Placeholder:
450 case CK_Informative:
451 case CK_CurrentParameter:
452 // There is no point in creating empty chunks of these kinds.
453 break;
454
455 case CK_LeftParen:
456 case CK_RightParen:
457 case CK_LeftBracket:
458 case CK_RightBracket:
459 case CK_LeftBrace:
460 case CK_RightBrace:
461 case CK_LeftAngle:
462 case CK_RightAngle:
463 case CK_Comma:
464 Result->AddChunk(Chunk((ChunkKind)Kind));
465 break;
466 }
467
468 continue;
279 // Parse the next kind.
280 unsigned KindValue;
281 if (ReadUnsigned(Str, StrEnd, KindValue))
282 return Result;
283
284 switch (ChunkKind Kind = (ChunkKind)KindValue) {
285 case CK_TypedText:
286 case CK_Text:
287 case CK_Placeholder:
288 case CK_Informative:
289 case CK_CurrentParameter: {
290 unsigned StrLen;
291 if (ReadUnsigned(Str, StrEnd, StrLen) || (Str + StrLen > StrEnd))
292 return Result;
293
294 Result->AddChunk(Chunk(Kind, StringRef(Str, StrLen)));
295 Str += StrLen;
296 break;
469 }
297 }
470
471 if (Kind == CK_Optional) {
472 // Deserialize the optional code-completion string.
473 std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str));
298
299 case CK_Optional: {
300 std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str, StrEnd));
474 Result->AddOptionalChunk(Optional);
301 Result->AddOptionalChunk(Optional);
302 break;
475 }
303 }
476
477 StringRef EndTag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
478 Terminator);
479 if (StartTag == StringRef::npos || !Terminator || Standalone)
480 break; // Parsing failed; just give up.
481
482 if (EndTag.empty() || Tag == EndTag) {
483 // Found the matching end tag. Add this chunk based on the text
484 // between the tags, then consume that input.
485 StringRef Text = Str.substr(0, StartTag);
486 switch ((ChunkKind)Kind) {
487 case CK_TypedText:
488 case CK_Text:
489 case CK_Placeholder:
490 case CK_Informative:
491 case CK_CurrentParameter:
492 case CK_LeftParen:
493 case CK_RightParen:
494 case CK_LeftBracket:
495 case CK_RightBracket:
496 case CK_LeftBrace:
497 case CK_RightBrace:
498 case CK_LeftAngle:
499 case CK_RightAngle:
500 case CK_Comma:
501 Result->AddChunk(Chunk((ChunkKind)Kind, UnescapeString(Text)));
502 break;
503
504 case CK_Optional:
505 // We've already added the optional chunk.
506 break;
507 }
304
305 case CK_LeftParen:
306 case CK_RightParen:
307 case CK_LeftBracket:
308 case CK_RightBracket:
309 case CK_LeftBrace:
310 case CK_RightBrace:
311 case CK_LeftAngle:
312 case CK_RightAngle:
313 case CK_Comma:
314 Result->AddChunk(Chunk(Kind));
315 break;
508 }
316 }
509
510 // Remove this tag.
511 Str = Str.substr(AfterTag);
512 } while (!Str.empty());
317 };
513
514 return Result;
515}
516
517void CodeCompleteConsumer::Result::Destroy() {
518 if (Kind == RK_Pattern) {
519 delete Pattern;
520 Pattern = 0;

--- 107 unchanged lines hidden (view full) ---

628}
629
630void
631CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
632 Result *Results,
633 unsigned NumResults) {
634 // Print the results.
635 for (unsigned I = 0; I != NumResults; ++I) {
318
319 return Result;
320}
321
322void CodeCompleteConsumer::Result::Destroy() {
323 if (Kind == RK_Pattern) {
324 delete Pattern;
325 Pattern = 0;

--- 107 unchanged lines hidden (view full) ---

433}
434
435void
436CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
437 Result *Results,
438 unsigned NumResults) {
439 // Print the results.
440 for (unsigned I = 0; I != NumResults; ++I) {
636 OS << "COMPLETION:" << Results[I].Rank << ":";
441 CXCursorKind Kind = CXCursor_NotImplemented;
442
637 switch (Results[I].Kind) {
443 switch (Results[I].Kind) {
638 case Result::RK_Declaration:
639 if (RecordDecl *Record = dyn_cast<RecordDecl>(Results[I].Declaration)) {
640 if (Record->isStruct())
641 OS << "Struct:";
642 else if (Record->isUnion())
643 OS << "Union:";
644 else
645 OS << "Class:";
646 } else if (ObjCMethodDecl *Method
647 = dyn_cast<ObjCMethodDecl>(Results[I].Declaration)) {
648 if (Method->isInstanceMethod())
649 OS << "ObjCInstanceMethod:";
650 else
651 OS << "ObjCClassMethod:";
652 } else {
653 OS << Results[I].Declaration->getDeclKindName() << ":";
654 }
655 if (CodeCompletionString *CCS
656 = Results[I].CreateCodeCompletionString(SemaRef)) {
657 CCS->Serialize(OS);
658 delete CCS;
659 } else {
660 OS << "<typed-text>"
661 << Results[I].Declaration->getNameAsString()
662 << "</>";
663 }
444 case Result::RK_Declaration:
445 switch (Results[I].Declaration->getKind()) {
446 case Decl::Record:
447 case Decl::CXXRecord:
448 case Decl::ClassTemplateSpecialization: {
449 RecordDecl *Record = cast<RecordDecl>(Results[I].Declaration);
450 if (Record->isStruct())
451 Kind = CXCursor_StructDecl;
452 else if (Record->isUnion())
453 Kind = CXCursor_UnionDecl;
454 else
455 Kind = CXCursor_ClassDecl;
456 break;
457 }
664
458
665 OS << '\n';
459 case Decl::ObjCMethod: {
460 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(Results[I].Declaration);
461 if (Method->isInstanceMethod())
462 Kind = CXCursor_ObjCInstanceMethodDecl;
463 else
464 Kind = CXCursor_ObjCClassMethodDecl;
666 break;
465 break;
466 }
667
467
668 case Result::RK_Keyword:
669 OS << "Keyword:<typed-text>" << Results[I].Keyword << "</>\n";
468 case Decl::Typedef:
469 Kind = CXCursor_TypedefDecl;
670 break;
671
470 break;
471
672 case Result::RK_Macro: {
673 OS << "Macro:";
674 if (CodeCompletionString *CCS
675 = Results[I].CreateCodeCompletionString(SemaRef)) {
676 CCS->Serialize(OS);
677 delete CCS;
678 } else {
679 OS << "<typed-text>" << Results[I].Macro->getName() << "</>";
680 }
681 OS << '\n';
472 case Decl::Enum:
473 Kind = CXCursor_EnumDecl;
682 break;
474 break;
683 }
684
475
685 case Result::RK_Pattern: {
686 OS << "Pattern:";
687 Results[I].Pattern->Serialize(OS);
688 OS << '\n';
476 case Decl::Field:
477 Kind = CXCursor_FieldDecl;
689 break;
478 break;
479
480 case Decl::EnumConstant:
481 Kind = CXCursor_EnumConstantDecl;
482 break;
483
484 case Decl::Function:
485 case Decl::CXXMethod:
486 case Decl::CXXConstructor:
487 case Decl::CXXDestructor:
488 case Decl::CXXConversion:
489 Kind = CXCursor_FunctionDecl;
490 break;
491
492 case Decl::Var:
493 Kind = CXCursor_VarDecl;
494 break;
495
496 case Decl::ParmVar:
497 Kind = CXCursor_ParmDecl;
498 break;
499
500 case Decl::ObjCInterface:
501 Kind = CXCursor_ObjCInterfaceDecl;
502 break;
503
504 case Decl::ObjCCategory:
505 Kind = CXCursor_ObjCCategoryDecl;
506 break;
507
508 case Decl::ObjCProtocol:
509 Kind = CXCursor_ObjCProtocolDecl;
510 break;
511
512 case Decl::ObjCProperty:
513 Kind = CXCursor_ObjCPropertyDecl;
514 break;
515
516 case Decl::ObjCIvar:
517 Kind = CXCursor_ObjCIvarDecl;
518 break;
519
520 case Decl::ObjCImplementation:
521 Kind = CXCursor_ObjCClassDefn;
522 break;
523
524 case Decl::ObjCCategoryImpl:
525 Kind = CXCursor_ObjCCategoryDefn;
526 break;
527
528 default:
529 break;
690 }
530 }
531 break;
532
533 case Result::RK_Keyword:
534 case Result::RK_Macro:
535 case Result::RK_Pattern:
536 Kind = CXCursor_NotImplemented;
537 break;
691 }
538 }
539
540 WriteUnsigned(OS, Kind);
541 CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef);
542 assert(CCS && "No code-completion string?");
543 CCS->Serialize(OS);
544 delete CCS;
692 }
693
694 // Once we've printed the code-completion results, suppress remaining
695 // diagnostics.
696 // FIXME: Move this somewhere else!
697 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
698}
699
700void
701CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
702 unsigned CurrentArg,
703 OverloadCandidate *Candidates,
704 unsigned NumCandidates) {
705 for (unsigned I = 0; I != NumCandidates; ++I) {
545 }
546
547 // Once we've printed the code-completion results, suppress remaining
548 // diagnostics.
549 // FIXME: Move this somewhere else!
550 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
551}
552
553void
554CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
555 unsigned CurrentArg,
556 OverloadCandidate *Candidates,
557 unsigned NumCandidates) {
558 for (unsigned I = 0; I != NumCandidates; ++I) {
706 if (CodeCompletionString *CCS
707 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
708 OS << "OVERLOAD:";
709 CCS->Serialize(OS);
710 OS << '\n';
711 delete CCS;
712 }
559 WriteUnsigned(OS, CXCursor_NotImplemented);
560 CodeCompletionString *CCS
561 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef);
562 assert(CCS && "No code-completion string?");
563 CCS->Serialize(OS);
564 delete CCS;
713 }
714
715 // Once we've printed the code-completion results, suppress remaining
716 // diagnostics.
717 // FIXME: Move this somewhere else!
718 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
719}
565 }
566
567 // Once we've printed the code-completion results, suppress remaining
568 // diagnostics.
569 // FIXME: Move this somewhere else!
570 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
571}