CodeCompleteConsumer.cpp revision 01dfea02d1da297e8b53db8eea3d3cc652acda8d
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" 18#include "Sema.h" 19#include "llvm/ADT/STLExtras.h" 20#include "llvm/ADT/StringSwitch.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 29//===----------------------------------------------------------------------===// 30// Code completion string implementation 31//===----------------------------------------------------------------------===// 32CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text) 33 : Kind(Kind), Text("") 34{ 35 switch (Kind) { 36 case CK_TypedText: 37 case CK_Text: 38 case CK_Placeholder: 39 case CK_Informative: 40 case CK_ResultType: 41 case CK_CurrentParameter: { 42 char *New = new char [Text.size() + 1]; 43 std::memcpy(New, Text.data(), Text.size()); 44 New[Text.size()] = '\0'; 45 this->Text = New; 46 break; 47 } 48 49 case CK_Optional: 50 llvm_unreachable("Optional strings cannot be created from text"); 51 break; 52 53 case CK_LeftParen: 54 this->Text = "("; 55 break; 56 57 case CK_RightParen: 58 this->Text = ")"; 59 break; 60 61 case CK_LeftBracket: 62 this->Text = "["; 63 break; 64 65 case CK_RightBracket: 66 this->Text = "]"; 67 break; 68 69 case CK_LeftBrace: 70 this->Text = "{"; 71 break; 72 73 case CK_RightBrace: 74 this->Text = "}"; 75 break; 76 77 case CK_LeftAngle: 78 this->Text = "<"; 79 break; 80 81 case CK_RightAngle: 82 this->Text = ">"; 83 break; 84 85 case CK_Comma: 86 this->Text = ", "; 87 break; 88 89 case CK_Colon: 90 this->Text = ": "; 91 break; 92 93 case CK_SemiColon: 94 this->Text = ";"; 95 break; 96 97 case CK_Equal: 98 this->Text = " = "; 99 break; 100 101 case CK_HorizontalSpace: 102 this->Text = " "; 103 break; 104 105 case CK_VerticalSpace: 106 this->Text = "\n"; 107 break; 108 } 109} 110 111CodeCompletionString::Chunk 112CodeCompletionString::Chunk::CreateText(StringRef Text) { 113 return Chunk(CK_Text, Text); 114} 115 116CodeCompletionString::Chunk 117CodeCompletionString::Chunk::CreateOptional( 118 std::auto_ptr<CodeCompletionString> Optional) { 119 Chunk Result; 120 Result.Kind = CK_Optional; 121 Result.Optional = Optional.release(); 122 return Result; 123} 124 125CodeCompletionString::Chunk 126CodeCompletionString::Chunk::CreatePlaceholder(StringRef Placeholder) { 127 return Chunk(CK_Placeholder, Placeholder); 128} 129 130CodeCompletionString::Chunk 131CodeCompletionString::Chunk::CreateInformative(StringRef Informative) { 132 return Chunk(CK_Informative, Informative); 133} 134 135CodeCompletionString::Chunk 136CodeCompletionString::Chunk::CreateResultType(StringRef ResultType) { 137 return Chunk(CK_ResultType, ResultType); 138} 139 140CodeCompletionString::Chunk 141CodeCompletionString::Chunk::CreateCurrentParameter( 142 StringRef CurrentParameter) { 143 return Chunk(CK_CurrentParameter, CurrentParameter); 144} 145 146CodeCompletionString::Chunk CodeCompletionString::Chunk::Clone() const { 147 switch (Kind) { 148 case CK_TypedText: 149 case CK_Text: 150 case CK_Placeholder: 151 case CK_Informative: 152 case CK_ResultType: 153 case CK_CurrentParameter: 154 case CK_LeftParen: 155 case CK_RightParen: 156 case CK_LeftBracket: 157 case CK_RightBracket: 158 case CK_LeftBrace: 159 case CK_RightBrace: 160 case CK_LeftAngle: 161 case CK_RightAngle: 162 case CK_Comma: 163 case CK_Colon: 164 case CK_SemiColon: 165 case CK_Equal: 166 case CK_HorizontalSpace: 167 case CK_VerticalSpace: 168 return Chunk(Kind, Text); 169 170 case CK_Optional: { 171 std::auto_ptr<CodeCompletionString> Opt(Optional->Clone()); 172 return CreateOptional(Opt); 173 } 174 } 175 176 // Silence GCC warning. 177 return Chunk(); 178} 179 180void 181CodeCompletionString::Chunk::Destroy() { 182 switch (Kind) { 183 case CK_Optional: 184 delete Optional; 185 break; 186 187 case CK_TypedText: 188 case CK_Text: 189 case CK_Placeholder: 190 case CK_Informative: 191 case CK_ResultType: 192 case CK_CurrentParameter: 193 delete [] Text; 194 break; 195 196 case CK_LeftParen: 197 case CK_RightParen: 198 case CK_LeftBracket: 199 case CK_RightBracket: 200 case CK_LeftBrace: 201 case CK_RightBrace: 202 case CK_LeftAngle: 203 case CK_RightAngle: 204 case CK_Comma: 205 case CK_Colon: 206 case CK_SemiColon: 207 case CK_Equal: 208 case CK_HorizontalSpace: 209 case CK_VerticalSpace: 210 break; 211 } 212} 213 214CodeCompletionString::~CodeCompletionString() { 215 std::for_each(Chunks.begin(), Chunks.end(), 216 std::mem_fun_ref(&Chunk::Destroy)); 217} 218 219std::string CodeCompletionString::getAsString() const { 220 std::string Result; 221 llvm::raw_string_ostream OS(Result); 222 223 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { 224 switch (C->Kind) { 225 case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; 226 case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; 227 228 case CK_Informative: 229 case CK_ResultType: 230 OS << "[#" << C->Text << "#]"; 231 break; 232 233 case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break; 234 default: OS << C->Text; break; 235 } 236 } 237 OS.flush(); 238 return Result; 239} 240 241const char *CodeCompletionString::getTypedText() const { 242 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) 243 if (C->Kind == CK_TypedText) 244 return C->Text; 245 246 return 0; 247} 248 249CodeCompletionString *CodeCompletionString::Clone() const { 250 CodeCompletionString *Result = new CodeCompletionString; 251 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) 252 Result->AddChunk(C->Clone()); 253 return Result; 254} 255 256static void WriteUnsigned(llvm::raw_ostream &OS, unsigned Value) { 257 OS.write((const char *)&Value, sizeof(unsigned)); 258} 259 260static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd, 261 unsigned &Value) { 262 if (Memory + sizeof(unsigned) > MemoryEnd) 263 return true; 264 265 memmove(&Value, Memory, sizeof(unsigned)); 266 Memory += sizeof(unsigned); 267 return false; 268} 269 270void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const { 271 // Write the number of chunks. 272 WriteUnsigned(OS, size()); 273 274 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { 275 WriteUnsigned(OS, C->Kind); 276 277 switch (C->Kind) { 278 case CK_TypedText: 279 case CK_Text: 280 case CK_Placeholder: 281 case CK_Informative: 282 case CK_ResultType: 283 case CK_CurrentParameter: { 284 const char *Text = C->Text; 285 unsigned StrLen = strlen(Text); 286 WriteUnsigned(OS, StrLen); 287 OS.write(Text, StrLen); 288 break; 289 } 290 291 case CK_Optional: 292 C->Optional->Serialize(OS); 293 break; 294 295 case CK_LeftParen: 296 case CK_RightParen: 297 case CK_LeftBracket: 298 case CK_RightBracket: 299 case CK_LeftBrace: 300 case CK_RightBrace: 301 case CK_LeftAngle: 302 case CK_RightAngle: 303 case CK_Comma: 304 case CK_Colon: 305 case CK_SemiColon: 306 case CK_Equal: 307 case CK_HorizontalSpace: 308 case CK_VerticalSpace: 309 break; 310 } 311 } 312} 313 314CodeCompletionString *CodeCompletionString::Deserialize(const char *&Str, 315 const char *StrEnd) { 316 if (Str == StrEnd || *Str == 0) 317 return 0; 318 319 CodeCompletionString *Result = new CodeCompletionString; 320 unsigned NumBlocks; 321 if (ReadUnsigned(Str, StrEnd, NumBlocks)) 322 return Result; 323 324 for (unsigned I = 0; I != NumBlocks; ++I) { 325 if (Str + 1 >= StrEnd) 326 break; 327 328 // Parse the next kind. 329 unsigned KindValue; 330 if (ReadUnsigned(Str, StrEnd, KindValue)) 331 return Result; 332 333 switch (ChunkKind Kind = (ChunkKind)KindValue) { 334 case CK_TypedText: 335 case CK_Text: 336 case CK_Placeholder: 337 case CK_Informative: 338 case CK_ResultType: 339 case CK_CurrentParameter: { 340 unsigned StrLen; 341 if (ReadUnsigned(Str, StrEnd, StrLen) || (Str + StrLen > StrEnd)) 342 return Result; 343 344 Result->AddChunk(Chunk(Kind, StringRef(Str, StrLen))); 345 Str += StrLen; 346 break; 347 } 348 349 case CK_Optional: { 350 std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str, StrEnd)); 351 Result->AddOptionalChunk(Optional); 352 break; 353 } 354 355 case CK_LeftParen: 356 case CK_RightParen: 357 case CK_LeftBracket: 358 case CK_RightBracket: 359 case CK_LeftBrace: 360 case CK_RightBrace: 361 case CK_LeftAngle: 362 case CK_RightAngle: 363 case CK_Comma: 364 case CK_Colon: 365 case CK_SemiColon: 366 case CK_Equal: 367 case CK_HorizontalSpace: 368 case CK_VerticalSpace: 369 Result->AddChunk(Chunk(Kind)); 370 break; 371 } 372 }; 373 374 return Result; 375} 376 377void CodeCompleteConsumer::Result::Destroy() { 378 if (Kind == RK_Pattern) { 379 delete Pattern; 380 Pattern = 0; 381 } 382} 383 384//===----------------------------------------------------------------------===// 385// Code completion overload candidate implementation 386//===----------------------------------------------------------------------===// 387FunctionDecl * 388CodeCompleteConsumer::OverloadCandidate::getFunction() const { 389 if (getKind() == CK_Function) 390 return Function; 391 else if (getKind() == CK_FunctionTemplate) 392 return FunctionTemplate->getTemplatedDecl(); 393 else 394 return 0; 395} 396 397const FunctionType * 398CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { 399 switch (Kind) { 400 case CK_Function: 401 return Function->getType()->getAs<FunctionType>(); 402 403 case CK_FunctionTemplate: 404 return FunctionTemplate->getTemplatedDecl()->getType() 405 ->getAs<FunctionType>(); 406 407 case CK_FunctionType: 408 return Type; 409 } 410 411 return 0; 412} 413 414//===----------------------------------------------------------------------===// 415// Code completion consumer implementation 416//===----------------------------------------------------------------------===// 417 418CodeCompleteConsumer::~CodeCompleteConsumer() { } 419 420void 421PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, 422 Result *Results, 423 unsigned NumResults) { 424 // Print the results. 425 for (unsigned I = 0; I != NumResults; ++I) { 426 OS << "COMPLETION: "; 427 switch (Results[I].Kind) { 428 case Result::RK_Declaration: 429 OS << Results[I].Declaration->getNameAsString() << " : " 430 << Results[I].Rank; 431 if (Results[I].Hidden) 432 OS << " (Hidden)"; 433 if (CodeCompletionString *CCS 434 = Results[I].CreateCodeCompletionString(SemaRef)) { 435 OS << " : " << CCS->getAsString(); 436 delete CCS; 437 } 438 439 OS << '\n'; 440 break; 441 442 case Result::RK_Keyword: 443 OS << Results[I].Keyword << " : " << Results[I].Rank << '\n'; 444 break; 445 446 case Result::RK_Macro: { 447 OS << Results[I].Macro->getName() << " : " << Results[I].Rank; 448 if (CodeCompletionString *CCS 449 = Results[I].CreateCodeCompletionString(SemaRef)) { 450 OS << " : " << CCS->getAsString(); 451 delete CCS; 452 } 453 OS << '\n'; 454 break; 455 } 456 457 case Result::RK_Pattern: { 458 OS << "Pattern : " << Results[I].Rank << " : " 459 << Results[I].Pattern->getAsString() << '\n'; 460 break; 461 } 462 } 463 } 464 465 // Once we've printed the code-completion results, suppress remaining 466 // diagnostics. 467 // FIXME: Move this somewhere else! 468 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 469} 470 471void 472PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, 473 unsigned CurrentArg, 474 OverloadCandidate *Candidates, 475 unsigned NumCandidates) { 476 for (unsigned I = 0; I != NumCandidates; ++I) { 477 if (CodeCompletionString *CCS 478 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) { 479 OS << "OVERLOAD: " << CCS->getAsString() << "\n"; 480 delete CCS; 481 } 482 } 483 484 // Once we've printed the code-completion results, suppress remaining 485 // diagnostics. 486 // FIXME: Move this somewhere else! 487 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 488} 489 490void 491CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, 492 Result *Results, 493 unsigned NumResults) { 494 // Print the results. 495 for (unsigned I = 0; I != NumResults; ++I) { 496 CXCursorKind Kind = CXCursor_NotImplemented; 497 498 switch (Results[I].Kind) { 499 case Result::RK_Declaration: 500 switch (Results[I].Declaration->getKind()) { 501 case Decl::Record: 502 case Decl::CXXRecord: 503 case Decl::ClassTemplateSpecialization: { 504 RecordDecl *Record = cast<RecordDecl>(Results[I].Declaration); 505 if (Record->isStruct()) 506 Kind = CXCursor_StructDecl; 507 else if (Record->isUnion()) 508 Kind = CXCursor_UnionDecl; 509 else 510 Kind = CXCursor_ClassDecl; 511 break; 512 } 513 514 case Decl::ObjCMethod: { 515 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(Results[I].Declaration); 516 if (Method->isInstanceMethod()) 517 Kind = CXCursor_ObjCInstanceMethodDecl; 518 else 519 Kind = CXCursor_ObjCClassMethodDecl; 520 break; 521 } 522 523 case Decl::Typedef: 524 Kind = CXCursor_TypedefDecl; 525 break; 526 527 case Decl::Enum: 528 Kind = CXCursor_EnumDecl; 529 break; 530 531 case Decl::Field: 532 Kind = CXCursor_FieldDecl; 533 break; 534 535 case Decl::EnumConstant: 536 Kind = CXCursor_EnumConstantDecl; 537 break; 538 539 case Decl::Function: 540 case Decl::CXXMethod: 541 case Decl::CXXConstructor: 542 case Decl::CXXDestructor: 543 case Decl::CXXConversion: 544 Kind = CXCursor_FunctionDecl; 545 break; 546 547 case Decl::Var: 548 Kind = CXCursor_VarDecl; 549 break; 550 551 case Decl::ParmVar: 552 Kind = CXCursor_ParmDecl; 553 break; 554 555 case Decl::ObjCInterface: 556 Kind = CXCursor_ObjCInterfaceDecl; 557 break; 558 559 case Decl::ObjCCategory: 560 Kind = CXCursor_ObjCCategoryDecl; 561 break; 562 563 case Decl::ObjCProtocol: 564 Kind = CXCursor_ObjCProtocolDecl; 565 break; 566 567 case Decl::ObjCProperty: 568 Kind = CXCursor_ObjCPropertyDecl; 569 break; 570 571 case Decl::ObjCIvar: 572 Kind = CXCursor_ObjCIvarDecl; 573 break; 574 575 case Decl::ObjCImplementation: 576 Kind = CXCursor_ObjCClassDefn; 577 break; 578 579 case Decl::ObjCCategoryImpl: 580 Kind = CXCursor_ObjCCategoryDefn; 581 break; 582 583 default: 584 break; 585 } 586 break; 587 588 case Result::RK_Keyword: 589 case Result::RK_Macro: 590 case Result::RK_Pattern: 591 Kind = CXCursor_NotImplemented; 592 break; 593 } 594 595 WriteUnsigned(OS, Kind); 596 CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef); 597 assert(CCS && "No code-completion string?"); 598 CCS->Serialize(OS); 599 delete CCS; 600 } 601 602 // Once we've printed the code-completion results, suppress remaining 603 // diagnostics. 604 // FIXME: Move this somewhere else! 605 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 606} 607 608void 609CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, 610 unsigned CurrentArg, 611 OverloadCandidate *Candidates, 612 unsigned NumCandidates) { 613 for (unsigned I = 0; I != NumCandidates; ++I) { 614 WriteUnsigned(OS, CXCursor_NotImplemented); 615 CodeCompletionString *CCS 616 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef); 617 assert(CCS && "No code-completion string?"); 618 CCS->Serialize(OS); 619 delete CCS; 620 } 621 622 // Once we've printed the code-completion results, suppress remaining 623 // diagnostics. 624 // FIXME: Move this somewhere else! 625 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 626} 627