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