CodeCompleteConsumer.cpp revision 7cd088e519d7e6caa4c4c12db52e0e4ae35d25c2
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/Sema/Scope.h" 15#include "clang/Sema/Sema.h" 16#include "clang/AST/DeclCXX.h" 17#include "clang/AST/DeclObjC.h" 18#include "clang/Lex/Preprocessor.h" 19#include "clang-c/Index.h" 20#include "llvm/ADT/STLExtras.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 214void CodeCompletionString::clear() { 215 std::for_each(Chunks.begin(), Chunks.end(), 216 std::mem_fun_ref(&Chunk::Destroy)); 217 Chunks.clear(); 218} 219 220std::string CodeCompletionString::getAsString() const { 221 std::string Result; 222 llvm::raw_string_ostream OS(Result); 223 224 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { 225 switch (C->Kind) { 226 case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; 227 case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; 228 229 case CK_Informative: 230 case CK_ResultType: 231 OS << "[#" << C->Text << "#]"; 232 break; 233 234 case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break; 235 default: OS << C->Text; break; 236 } 237 } 238 return OS.str(); 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 * 250CodeCompletionString::Clone(CodeCompletionString *Result) const { 251 if (!Result) 252 Result = new CodeCompletionString; 253 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) 254 Result->AddChunk(C->Clone()); 255 return Result; 256} 257 258static void WriteUnsigned(llvm::raw_ostream &OS, unsigned Value) { 259 OS.write((const char *)&Value, sizeof(unsigned)); 260} 261 262static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd, 263 unsigned &Value) { 264 if (Memory + sizeof(unsigned) > MemoryEnd) 265 return true; 266 267 memmove(&Value, Memory, sizeof(unsigned)); 268 Memory += sizeof(unsigned); 269 return false; 270} 271 272void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const { 273 // Write the number of chunks. 274 WriteUnsigned(OS, size()); 275 276 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { 277 WriteUnsigned(OS, C->Kind); 278 279 switch (C->Kind) { 280 case CK_TypedText: 281 case CK_Text: 282 case CK_Placeholder: 283 case CK_Informative: 284 case CK_ResultType: 285 case CK_CurrentParameter: { 286 const char *Text = C->Text; 287 unsigned StrLen = strlen(Text); 288 WriteUnsigned(OS, StrLen); 289 OS.write(Text, StrLen); 290 break; 291 } 292 293 case CK_Optional: 294 C->Optional->Serialize(OS); 295 break; 296 297 case CK_LeftParen: 298 case CK_RightParen: 299 case CK_LeftBracket: 300 case CK_RightBracket: 301 case CK_LeftBrace: 302 case CK_RightBrace: 303 case CK_LeftAngle: 304 case CK_RightAngle: 305 case CK_Comma: 306 case CK_Colon: 307 case CK_SemiColon: 308 case CK_Equal: 309 case CK_HorizontalSpace: 310 case CK_VerticalSpace: 311 break; 312 } 313 } 314} 315 316bool CodeCompletionString::Deserialize(const char *&Str, const char *StrEnd) { 317 if (Str == StrEnd || *Str == 0) 318 return false; 319 320 unsigned NumBlocks; 321 if (ReadUnsigned(Str, StrEnd, NumBlocks)) 322 return false; 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 false; 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 false; 343 344 AddChunk(Chunk(Kind, StringRef(Str, StrLen))); 345 Str += StrLen; 346 break; 347 } 348 349 case CK_Optional: { 350 std::auto_ptr<CodeCompletionString> Optional(new CodeCompletionString()); 351 if (Optional->Deserialize(Str, StrEnd)) 352 AddOptionalChunk(Optional); 353 break; 354 } 355 356 case CK_LeftParen: 357 case CK_RightParen: 358 case CK_LeftBracket: 359 case CK_RightBracket: 360 case CK_LeftBrace: 361 case CK_RightBrace: 362 case CK_LeftAngle: 363 case CK_RightAngle: 364 case CK_Comma: 365 case CK_Colon: 366 case CK_SemiColon: 367 case CK_Equal: 368 case CK_HorizontalSpace: 369 case CK_VerticalSpace: 370 AddChunk(Chunk(Kind)); 371 break; 372 } 373 }; 374 375 return true; 376} 377 378void CodeCompleteConsumer::Result::Destroy() { 379 if (Kind == RK_Pattern) { 380 delete Pattern; 381 Pattern = 0; 382 } 383} 384 385unsigned CodeCompleteConsumer::Result::getPriorityFromDecl(NamedDecl *ND) { 386 if (!ND) 387 return CCP_Unlikely; 388 389 // Context-based decisions. 390 DeclContext *DC = ND->getDeclContext()->getLookupContext(); 391 if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) 392 return CCP_LocalDeclaration; 393 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) 394 return CCP_MemberDeclaration; 395 396 // Content-based decisions. 397 if (isa<EnumConstantDecl>(ND)) 398 return CCP_Constant; 399 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) 400 return CCP_Type; 401 return CCP_Declaration; 402} 403 404//===----------------------------------------------------------------------===// 405// Code completion overload candidate implementation 406//===----------------------------------------------------------------------===// 407FunctionDecl * 408CodeCompleteConsumer::OverloadCandidate::getFunction() const { 409 if (getKind() == CK_Function) 410 return Function; 411 else if (getKind() == CK_FunctionTemplate) 412 return FunctionTemplate->getTemplatedDecl(); 413 else 414 return 0; 415} 416 417const FunctionType * 418CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { 419 switch (Kind) { 420 case CK_Function: 421 return Function->getType()->getAs<FunctionType>(); 422 423 case CK_FunctionTemplate: 424 return FunctionTemplate->getTemplatedDecl()->getType() 425 ->getAs<FunctionType>(); 426 427 case CK_FunctionType: 428 return Type; 429 } 430 431 return 0; 432} 433 434//===----------------------------------------------------------------------===// 435// Code completion consumer implementation 436//===----------------------------------------------------------------------===// 437 438CodeCompleteConsumer::~CodeCompleteConsumer() { } 439 440void 441PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, 442 CodeCompletionContext Context, 443 Result *Results, 444 unsigned NumResults) { 445 // Print the results. 446 for (unsigned I = 0; I != NumResults; ++I) { 447 OS << "COMPLETION: "; 448 switch (Results[I].Kind) { 449 case Result::RK_Declaration: 450 OS << Results[I].Declaration; 451 if (Results[I].Hidden) 452 OS << " (Hidden)"; 453 if (CodeCompletionString *CCS 454 = Results[I].CreateCodeCompletionString(SemaRef)) { 455 OS << " : " << CCS->getAsString(); 456 delete CCS; 457 } 458 459 OS << '\n'; 460 break; 461 462 case Result::RK_Keyword: 463 OS << Results[I].Keyword << '\n'; 464 break; 465 466 case Result::RK_Macro: { 467 OS << Results[I].Macro->getName(); 468 if (CodeCompletionString *CCS 469 = Results[I].CreateCodeCompletionString(SemaRef)) { 470 OS << " : " << CCS->getAsString(); 471 delete CCS; 472 } 473 OS << '\n'; 474 break; 475 } 476 477 case Result::RK_Pattern: { 478 OS << "Pattern : " 479 << Results[I].Pattern->getAsString() << '\n'; 480 break; 481 } 482 } 483 } 484} 485 486void 487PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, 488 unsigned CurrentArg, 489 OverloadCandidate *Candidates, 490 unsigned NumCandidates) { 491 for (unsigned I = 0; I != NumCandidates; ++I) { 492 if (CodeCompletionString *CCS 493 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) { 494 OS << "OVERLOAD: " << CCS->getAsString() << "\n"; 495 delete CCS; 496 } 497 } 498} 499 500void CodeCompleteConsumer::Result::computeCursorKindAndAvailability() { 501 switch (Kind) { 502 case RK_Declaration: 503 // Set the availability based on attributes. 504 Availability = CXAvailability_Available; 505 if (Declaration->getAttr<UnavailableAttr>()) 506 Availability = CXAvailability_NotAvailable; 507 else if (Declaration->getAttr<DeprecatedAttr>()) 508 Availability = CXAvailability_Deprecated; 509 510 switch (Declaration->getKind()) { 511 case Decl::Record: 512 case Decl::CXXRecord: 513 case Decl::ClassTemplateSpecialization: { 514 RecordDecl *Record = cast<RecordDecl>(Declaration); 515 if (Record->isStruct()) 516 CursorKind = CXCursor_StructDecl; 517 else if (Record->isUnion()) 518 CursorKind = CXCursor_UnionDecl; 519 else 520 CursorKind = CXCursor_ClassDecl; 521 break; 522 } 523 524 case Decl::ObjCMethod: { 525 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(Declaration); 526 if (Method->isInstanceMethod()) 527 CursorKind = CXCursor_ObjCInstanceMethodDecl; 528 else 529 CursorKind = CXCursor_ObjCClassMethodDecl; 530 break; 531 } 532 533 case Decl::Typedef: 534 CursorKind = CXCursor_TypedefDecl; 535 break; 536 537 case Decl::Enum: 538 CursorKind = CXCursor_EnumDecl; 539 break; 540 541 case Decl::Field: 542 CursorKind = CXCursor_FieldDecl; 543 break; 544 545 case Decl::EnumConstant: 546 CursorKind = CXCursor_EnumConstantDecl; 547 break; 548 549 case Decl::Function: 550 case Decl::CXXMethod: 551 case Decl::CXXConstructor: 552 case Decl::CXXDestructor: 553 case Decl::CXXConversion: 554 CursorKind = CXCursor_FunctionDecl; 555 if (cast<FunctionDecl>(Declaration)->isDeleted()) 556 Availability = CXAvailability_NotAvailable; 557 break; 558 559 case Decl::Var: 560 CursorKind = CXCursor_VarDecl; 561 break; 562 563 case Decl::ParmVar: 564 CursorKind = CXCursor_ParmDecl; 565 break; 566 567 case Decl::ObjCInterface: 568 CursorKind = CXCursor_ObjCInterfaceDecl; 569 break; 570 571 case Decl::ObjCCategory: 572 CursorKind = CXCursor_ObjCCategoryDecl; 573 break; 574 575 case Decl::ObjCProtocol: 576 CursorKind = CXCursor_ObjCProtocolDecl; 577 break; 578 579 case Decl::ObjCProperty: 580 CursorKind = CXCursor_ObjCPropertyDecl; 581 break; 582 583 case Decl::ObjCIvar: 584 CursorKind = CXCursor_ObjCIvarDecl; 585 break; 586 587 case Decl::ObjCImplementation: 588 CursorKind = CXCursor_ObjCImplementationDecl; 589 break; 590 591 case Decl::ObjCCategoryImpl: 592 CursorKind = CXCursor_ObjCCategoryImplDecl; 593 break; 594 595 default: 596 CursorKind = CXCursor_NotImplemented; 597 break; 598 } 599 break; 600 601 case Result::RK_Macro: 602 Availability = CXAvailability_Available; 603 CursorKind = CXCursor_MacroDefinition; 604 break; 605 606 case Result::RK_Keyword: 607 Availability = CXAvailability_Available; 608 CursorKind = CXCursor_NotImplemented; 609 break; 610 611 case Result::RK_Pattern: 612 // Do nothing: Patterns can come with cursor kinds! 613 break; 614 } 615} 616 617void 618CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, 619 CodeCompletionContext Context, 620 Result *Results, 621 unsigned NumResults) { 622 // Print the results. 623 for (unsigned I = 0; I != NumResults; ++I) { 624 WriteUnsigned(OS, Results[I].CursorKind); 625 WriteUnsigned(OS, Results[I].Priority); 626 WriteUnsigned(OS, Results[I].Availability); 627 CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef); 628 assert(CCS && "No code-completion string?"); 629 CCS->Serialize(OS); 630 delete CCS; 631 } 632} 633 634void 635CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, 636 unsigned CurrentArg, 637 OverloadCandidate *Candidates, 638 unsigned NumCandidates) { 639 for (unsigned I = 0; I != NumCandidates; ++I) { 640 WriteUnsigned(OS, CXCursor_NotImplemented); 641 WriteUnsigned(OS, /*Priority=*/0); 642 WriteUnsigned(OS, /*Availability=*/CXAvailability_Available); 643 CodeCompletionString *CCS 644 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef); 645 assert(CCS && "No code-completion string?"); 646 CCS->Serialize(OS); 647 delete CCS; 648 } 649} 650