CodeCompleteConsumer.cpp revision b699866820102a69d83d6ac6941985c5ef4e8c40
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 if (Results[I].Hidden) 431 OS << " (Hidden)"; 432 if (CodeCompletionString *CCS 433 = Results[I].CreateCodeCompletionString(SemaRef)) { 434 OS << " : " << CCS->getAsString(); 435 delete CCS; 436 } 437 438 OS << '\n'; 439 break; 440 441 case Result::RK_Keyword: 442 OS << Results[I].Keyword << '\n'; 443 break; 444 445 case Result::RK_Macro: { 446 OS << Results[I].Macro->getName(); 447 if (CodeCompletionString *CCS 448 = Results[I].CreateCodeCompletionString(SemaRef)) { 449 OS << " : " << CCS->getAsString(); 450 delete CCS; 451 } 452 OS << '\n'; 453 break; 454 } 455 456 case Result::RK_Pattern: { 457 OS << "Pattern : " 458 << Results[I].Pattern->getAsString() << '\n'; 459 break; 460 } 461 } 462 } 463 464 // Once we've printed the code-completion results, suppress remaining 465 // diagnostics. 466 // FIXME: Move this somewhere else! 467 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 468} 469 470void 471PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, 472 unsigned CurrentArg, 473 OverloadCandidate *Candidates, 474 unsigned NumCandidates) { 475 for (unsigned I = 0; I != NumCandidates; ++I) { 476 if (CodeCompletionString *CCS 477 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) { 478 OS << "OVERLOAD: " << CCS->getAsString() << "\n"; 479 delete CCS; 480 } 481 } 482 483 // Once we've printed the code-completion results, suppress remaining 484 // diagnostics. 485 // FIXME: Move this somewhere else! 486 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 487} 488 489void 490CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, 491 Result *Results, 492 unsigned NumResults) { 493 // Print the results. 494 for (unsigned I = 0; I != NumResults; ++I) { 495 CXCursorKind Kind = CXCursor_NotImplemented; 496 497 switch (Results[I].Kind) { 498 case Result::RK_Declaration: 499 switch (Results[I].Declaration->getKind()) { 500 case Decl::Record: 501 case Decl::CXXRecord: 502 case Decl::ClassTemplateSpecialization: { 503 RecordDecl *Record = cast<RecordDecl>(Results[I].Declaration); 504 if (Record->isStruct()) 505 Kind = CXCursor_StructDecl; 506 else if (Record->isUnion()) 507 Kind = CXCursor_UnionDecl; 508 else 509 Kind = CXCursor_ClassDecl; 510 break; 511 } 512 513 case Decl::ObjCMethod: { 514 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(Results[I].Declaration); 515 if (Method->isInstanceMethod()) 516 Kind = CXCursor_ObjCInstanceMethodDecl; 517 else 518 Kind = CXCursor_ObjCClassMethodDecl; 519 break; 520 } 521 522 case Decl::Typedef: 523 Kind = CXCursor_TypedefDecl; 524 break; 525 526 case Decl::Enum: 527 Kind = CXCursor_EnumDecl; 528 break; 529 530 case Decl::Field: 531 Kind = CXCursor_FieldDecl; 532 break; 533 534 case Decl::EnumConstant: 535 Kind = CXCursor_EnumConstantDecl; 536 break; 537 538 case Decl::Function: 539 case Decl::CXXMethod: 540 case Decl::CXXConstructor: 541 case Decl::CXXDestructor: 542 case Decl::CXXConversion: 543 Kind = CXCursor_FunctionDecl; 544 break; 545 546 case Decl::Var: 547 Kind = CXCursor_VarDecl; 548 break; 549 550 case Decl::ParmVar: 551 Kind = CXCursor_ParmDecl; 552 break; 553 554 case Decl::ObjCInterface: 555 Kind = CXCursor_ObjCInterfaceDecl; 556 break; 557 558 case Decl::ObjCCategory: 559 Kind = CXCursor_ObjCCategoryDecl; 560 break; 561 562 case Decl::ObjCProtocol: 563 Kind = CXCursor_ObjCProtocolDecl; 564 break; 565 566 case Decl::ObjCProperty: 567 Kind = CXCursor_ObjCPropertyDecl; 568 break; 569 570 case Decl::ObjCIvar: 571 Kind = CXCursor_ObjCIvarDecl; 572 break; 573 574 case Decl::ObjCImplementation: 575 Kind = CXCursor_ObjCImplementationDecl; 576 break; 577 578 case Decl::ObjCCategoryImpl: 579 Kind = CXCursor_ObjCCategoryImplDecl; 580 break; 581 582 default: 583 break; 584 } 585 break; 586 587 case Result::RK_Keyword: 588 case Result::RK_Macro: 589 case Result::RK_Pattern: 590 Kind = CXCursor_NotImplemented; 591 break; 592 } 593 594 WriteUnsigned(OS, Kind); 595 CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef); 596 assert(CCS && "No code-completion string?"); 597 CCS->Serialize(OS); 598 delete CCS; 599 } 600 601 // Once we've printed the code-completion results, suppress remaining 602 // diagnostics. 603 // FIXME: Move this somewhere else! 604 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 605} 606 607void 608CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, 609 unsigned CurrentArg, 610 OverloadCandidate *Candidates, 611 unsigned NumCandidates) { 612 for (unsigned I = 0; I != NumCandidates; ++I) { 613 WriteUnsigned(OS, CXCursor_NotImplemented); 614 CodeCompletionString *CCS 615 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef); 616 assert(CCS && "No code-completion string?"); 617 CCS->Serialize(OS); 618 delete CCS; 619 } 620 621 // Once we've printed the code-completion results, suppress remaining 622 // diagnostics. 623 // FIXME: Move this somewhere else! 624 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 625} 626