CodeCompleteConsumer.cpp revision 85b4521e34dcd4a0a4a1f0819e1123128e5a3125
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 "Sema.h" 18#include "llvm/ADT/STLExtras.h" 19#include "llvm/ADT/StringSwitch.h" 20#include "llvm/Support/raw_ostream.h" 21#include <algorithm> 22#include <cstring> 23#include <functional> 24 25using namespace clang; 26using llvm::StringRef; 27 28//===----------------------------------------------------------------------===// 29// Code completion string implementation 30//===----------------------------------------------------------------------===// 31CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text) 32 : Kind(Kind), Text("") 33{ 34 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 } 87} 88 89CodeCompletionString::Chunk 90CodeCompletionString::Chunk::CreateText(StringRef Text) { 91 return Chunk(CK_Text, Text); 92} 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 104CodeCompletionString::Chunk::CreatePlaceholder(StringRef Placeholder) { 105 return Chunk(CK_Placeholder, Placeholder); 106} 107 108CodeCompletionString::Chunk 109CodeCompletionString::Chunk::CreateInformative(StringRef Informative) { 110 return Chunk(CK_Informative, Informative); 111} 112 113CodeCompletionString::Chunk 114CodeCompletionString::Chunk::CreateCurrentParameter( 115 StringRef CurrentParameter) { 116 return Chunk(CK_CurrentParameter, CurrentParameter); 117} 118 119CodeCompletionString::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} 146 147void 148CodeCompletionString::Chunk::Destroy() { 149 switch (Kind) { 150 case CK_Optional: 151 delete Optional; 152 break; 153 154 case CK_TypedText: 155 case CK_Text: 156 case CK_Placeholder: 157 case CK_Informative: 158 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: 171 break; 172 } 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) { 186 case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; 187 case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; 188 case CK_Informative: OS << "[#" << C->Text << "#]"; break; 189 case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break; 190 default: OS << C->Text; break; 191 } 192 } 193 OS.flush(); 194 return Result; 195} 196 197const 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} 211 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 << "<"; break; 236 case '>': OS << ">"; break; 237 case '&': OS << "&"; break; 238 case '"': OS << """; break; 239 case '\'': OS << "'"; 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 516void CodeCompleteConsumer::Result::Destroy() { 517 if (Kind == RK_Pattern) { 518 delete Pattern; 519 Pattern = 0; 520 } 521} 522 523//===----------------------------------------------------------------------===// 524// 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//===----------------------------------------------------------------------===// 554// Code completion consumer implementation 555//===----------------------------------------------------------------------===// 556 557CodeCompleteConsumer::~CodeCompleteConsumer() { } 558 559void 560PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, 561 Result *Results, 562 unsigned NumResults) { 563 // Print the results. 564 for (unsigned I = 0; I != NumResults; ++I) { 565 OS << "COMPLETION: "; 566 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)"; 572 if (CodeCompletionString *CCS 573 = Results[I].CreateCodeCompletionString(SemaRef)) { 574 OS << " : " << CCS->getAsString(); 575 delete CCS; 576 } 577 578 OS << '\n'; 579 break; 580 581 case Result::RK_Keyword: 582 OS << Results[I].Keyword << " : " << Results[I].Rank << '\n'; 583 break; 584 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 } 595 596 case Result::RK_Pattern: { 597 OS << "Pattern : " << Results[I].Rank << " : " 598 << Results[I].Pattern->getAsString() << '\n'; 599 break; 600 } 601 } 602 } 603 604 // Once we've printed the code-completion results, suppress remaining 605 // diagnostics. 606 // FIXME: Move this somewhere else! 607 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 608} 609 610void 611PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, 612 unsigned CurrentArg, 613 OverloadCandidate *Candidates, 614 unsigned NumCandidates) { 615 for (unsigned I = 0; I != NumCandidates; ++I) { 616 if (CodeCompletionString *CCS 617 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) { 618 OS << "OVERLOAD: " << CCS->getAsString() << "\n"; 619 delete CCS; 620 } 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} 628 629void 630CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, 631 Result *Results, 632 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 } 683 684 case Result::RK_Pattern: { 685 OS << "Pattern:"; 686 Results[I].Pattern->Serialize(OS); 687 OS << '\n'; 688 break; 689 } 690 } 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 700CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, 701 unsigned CurrentArg, 702 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} 719