CodeCompleteConsumer.cpp revision e8d7bebc0dd037516dd695ee1ac2eb0923753b46
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/AST/DeclTemplate.h" 19#include "clang/Lex/Preprocessor.h" 20#include "clang-c/Index.h" 21#include "llvm/ADT/STLExtras.h" 22#include "llvm/Support/raw_ostream.h" 23#include <algorithm> 24#include <cstring> 25#include <functional> 26 27using namespace clang; 28using llvm::StringRef; 29 30//===----------------------------------------------------------------------===// 31// Code completion string implementation 32//===----------------------------------------------------------------------===// 33CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text) 34 : Kind(Kind), Text("") 35{ 36 switch (Kind) { 37 case CK_TypedText: 38 case CK_Text: 39 case CK_Placeholder: 40 case CK_Informative: 41 case CK_ResultType: 42 case CK_CurrentParameter: { 43 char *New = new char [Text.size() + 1]; 44 std::memcpy(New, Text.data(), Text.size()); 45 New[Text.size()] = '\0'; 46 this->Text = New; 47 break; 48 } 49 50 case CK_Optional: 51 llvm_unreachable("Optional strings cannot be created from text"); 52 break; 53 54 case CK_LeftParen: 55 this->Text = "("; 56 break; 57 58 case CK_RightParen: 59 this->Text = ")"; 60 break; 61 62 case CK_LeftBracket: 63 this->Text = "["; 64 break; 65 66 case CK_RightBracket: 67 this->Text = "]"; 68 break; 69 70 case CK_LeftBrace: 71 this->Text = "{"; 72 break; 73 74 case CK_RightBrace: 75 this->Text = "}"; 76 break; 77 78 case CK_LeftAngle: 79 this->Text = "<"; 80 break; 81 82 case CK_RightAngle: 83 this->Text = ">"; 84 break; 85 86 case CK_Comma: 87 this->Text = ", "; 88 break; 89 90 case CK_Colon: 91 this->Text = ":"; 92 break; 93 94 case CK_SemiColon: 95 this->Text = ";"; 96 break; 97 98 case CK_Equal: 99 this->Text = " = "; 100 break; 101 102 case CK_HorizontalSpace: 103 this->Text = " "; 104 break; 105 106 case CK_VerticalSpace: 107 this->Text = "\n"; 108 break; 109 } 110} 111 112CodeCompletionString::Chunk 113CodeCompletionString::Chunk::CreateText(StringRef Text) { 114 return Chunk(CK_Text, Text); 115} 116 117CodeCompletionString::Chunk 118CodeCompletionString::Chunk::CreateOptional( 119 std::auto_ptr<CodeCompletionString> Optional) { 120 Chunk Result; 121 Result.Kind = CK_Optional; 122 Result.Optional = Optional.release(); 123 return Result; 124} 125 126CodeCompletionString::Chunk 127CodeCompletionString::Chunk::CreatePlaceholder(StringRef Placeholder) { 128 return Chunk(CK_Placeholder, Placeholder); 129} 130 131CodeCompletionString::Chunk 132CodeCompletionString::Chunk::CreateInformative(StringRef Informative) { 133 return Chunk(CK_Informative, Informative); 134} 135 136CodeCompletionString::Chunk 137CodeCompletionString::Chunk::CreateResultType(StringRef ResultType) { 138 return Chunk(CK_ResultType, ResultType); 139} 140 141CodeCompletionString::Chunk 142CodeCompletionString::Chunk::CreateCurrentParameter( 143 StringRef CurrentParameter) { 144 return Chunk(CK_CurrentParameter, CurrentParameter); 145} 146 147CodeCompletionString::Chunk CodeCompletionString::Chunk::Clone() const { 148 switch (Kind) { 149 case CK_TypedText: 150 case CK_Text: 151 case CK_Placeholder: 152 case CK_Informative: 153 case CK_ResultType: 154 case CK_CurrentParameter: 155 case CK_LeftParen: 156 case CK_RightParen: 157 case CK_LeftBracket: 158 case CK_RightBracket: 159 case CK_LeftBrace: 160 case CK_RightBrace: 161 case CK_LeftAngle: 162 case CK_RightAngle: 163 case CK_Comma: 164 case CK_Colon: 165 case CK_SemiColon: 166 case CK_Equal: 167 case CK_HorizontalSpace: 168 case CK_VerticalSpace: 169 return Chunk(Kind, Text); 170 171 case CK_Optional: { 172 std::auto_ptr<CodeCompletionString> Opt(Optional->Clone()); 173 return CreateOptional(Opt); 174 } 175 } 176 177 // Silence GCC warning. 178 return Chunk(); 179} 180 181void 182CodeCompletionString::Chunk::Destroy() { 183 switch (Kind) { 184 case CK_Optional: 185 delete Optional; 186 break; 187 188 case CK_TypedText: 189 case CK_Text: 190 case CK_Placeholder: 191 case CK_Informative: 192 case CK_ResultType: 193 case CK_CurrentParameter: 194 delete [] Text; 195 break; 196 197 case CK_LeftParen: 198 case CK_RightParen: 199 case CK_LeftBracket: 200 case CK_RightBracket: 201 case CK_LeftBrace: 202 case CK_RightBrace: 203 case CK_LeftAngle: 204 case CK_RightAngle: 205 case CK_Comma: 206 case CK_Colon: 207 case CK_SemiColon: 208 case CK_Equal: 209 case CK_HorizontalSpace: 210 case CK_VerticalSpace: 211 break; 212 } 213} 214 215void CodeCompletionString::clear() { 216 std::for_each(Chunks.begin(), Chunks.end(), 217 std::mem_fun_ref(&Chunk::Destroy)); 218 Chunks.clear(); 219} 220 221std::string CodeCompletionString::getAsString() const { 222 std::string Result; 223 llvm::raw_string_ostream OS(Result); 224 225 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { 226 switch (C->Kind) { 227 case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; 228 case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; 229 230 case CK_Informative: 231 case CK_ResultType: 232 OS << "[#" << C->Text << "#]"; 233 break; 234 235 case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break; 236 default: OS << C->Text; break; 237 } 238 } 239 return OS.str(); 240} 241 242const char *CodeCompletionString::getTypedText() const { 243 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) 244 if (C->Kind == CK_TypedText) 245 return C->Text; 246 247 return 0; 248} 249 250CodeCompletionString * 251CodeCompletionString::Clone(CodeCompletionString *Result) const { 252 if (!Result) 253 Result = new CodeCompletionString; 254 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) 255 Result->AddChunk(C->Clone()); 256 return Result; 257} 258 259static void WriteUnsigned(llvm::raw_ostream &OS, unsigned Value) { 260 OS.write((const char *)&Value, sizeof(unsigned)); 261} 262 263static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd, 264 unsigned &Value) { 265 if (Memory + sizeof(unsigned) > MemoryEnd) 266 return true; 267 268 memmove(&Value, Memory, sizeof(unsigned)); 269 Memory += sizeof(unsigned); 270 return false; 271} 272 273void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const { 274 // Write the number of chunks. 275 WriteUnsigned(OS, size()); 276 277 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { 278 WriteUnsigned(OS, C->Kind); 279 280 switch (C->Kind) { 281 case CK_TypedText: 282 case CK_Text: 283 case CK_Placeholder: 284 case CK_Informative: 285 case CK_ResultType: 286 case CK_CurrentParameter: { 287 const char *Text = C->Text; 288 unsigned StrLen = strlen(Text); 289 WriteUnsigned(OS, StrLen); 290 OS.write(Text, StrLen); 291 break; 292 } 293 294 case CK_Optional: 295 C->Optional->Serialize(OS); 296 break; 297 298 case CK_LeftParen: 299 case CK_RightParen: 300 case CK_LeftBracket: 301 case CK_RightBracket: 302 case CK_LeftBrace: 303 case CK_RightBrace: 304 case CK_LeftAngle: 305 case CK_RightAngle: 306 case CK_Comma: 307 case CK_Colon: 308 case CK_SemiColon: 309 case CK_Equal: 310 case CK_HorizontalSpace: 311 case CK_VerticalSpace: 312 break; 313 } 314 } 315} 316 317bool CodeCompletionString::Deserialize(const char *&Str, const char *StrEnd) { 318 if (Str == StrEnd || *Str == 0) 319 return false; 320 321 unsigned NumBlocks; 322 if (ReadUnsigned(Str, StrEnd, NumBlocks)) 323 return false; 324 325 for (unsigned I = 0; I != NumBlocks; ++I) { 326 if (Str + 1 >= StrEnd) 327 break; 328 329 // Parse the next kind. 330 unsigned KindValue; 331 if (ReadUnsigned(Str, StrEnd, KindValue)) 332 return false; 333 334 switch (ChunkKind Kind = (ChunkKind)KindValue) { 335 case CK_TypedText: 336 case CK_Text: 337 case CK_Placeholder: 338 case CK_Informative: 339 case CK_ResultType: 340 case CK_CurrentParameter: { 341 unsigned StrLen; 342 if (ReadUnsigned(Str, StrEnd, StrLen) || (Str + StrLen > StrEnd)) 343 return false; 344 345 AddChunk(Chunk(Kind, StringRef(Str, StrLen))); 346 Str += StrLen; 347 break; 348 } 349 350 case CK_Optional: { 351 std::auto_ptr<CodeCompletionString> Optional(new CodeCompletionString()); 352 if (Optional->Deserialize(Str, StrEnd)) 353 AddOptionalChunk(Optional); 354 break; 355 } 356 357 case CK_LeftParen: 358 case CK_RightParen: 359 case CK_LeftBracket: 360 case CK_RightBracket: 361 case CK_LeftBrace: 362 case CK_RightBrace: 363 case CK_LeftAngle: 364 case CK_RightAngle: 365 case CK_Comma: 366 case CK_Colon: 367 case CK_SemiColon: 368 case CK_Equal: 369 case CK_HorizontalSpace: 370 case CK_VerticalSpace: 371 AddChunk(Chunk(Kind)); 372 break; 373 } 374 }; 375 376 return true; 377} 378 379void CodeCompletionResult::Destroy() { 380 if (Kind == RK_Pattern) { 381 delete Pattern; 382 Pattern = 0; 383 } 384} 385 386unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) { 387 if (!ND) 388 return CCP_Unlikely; 389 390 // Context-based decisions. 391 DeclContext *DC = ND->getDeclContext()->getRedeclContext(); 392 if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) 393 return CCP_LocalDeclaration; 394 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) 395 return CCP_MemberDeclaration; 396 397 // Content-based decisions. 398 if (isa<EnumConstantDecl>(ND)) 399 return CCP_Constant; 400 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) 401 return CCP_Type; 402 return CCP_Declaration; 403} 404 405//===----------------------------------------------------------------------===// 406// Code completion overload candidate implementation 407//===----------------------------------------------------------------------===// 408FunctionDecl * 409CodeCompleteConsumer::OverloadCandidate::getFunction() const { 410 if (getKind() == CK_Function) 411 return Function; 412 else if (getKind() == CK_FunctionTemplate) 413 return FunctionTemplate->getTemplatedDecl(); 414 else 415 return 0; 416} 417 418const FunctionType * 419CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { 420 switch (Kind) { 421 case CK_Function: 422 return Function->getType()->getAs<FunctionType>(); 423 424 case CK_FunctionTemplate: 425 return FunctionTemplate->getTemplatedDecl()->getType() 426 ->getAs<FunctionType>(); 427 428 case CK_FunctionType: 429 return Type; 430 } 431 432 return 0; 433} 434 435//===----------------------------------------------------------------------===// 436// Code completion consumer implementation 437//===----------------------------------------------------------------------===// 438 439CodeCompleteConsumer::~CodeCompleteConsumer() { } 440 441void 442PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, 443 CodeCompletionContext Context, 444 CodeCompletionResult *Results, 445 unsigned NumResults) { 446 std::stable_sort(Results, Results + NumResults); 447 448 // Print the results. 449 for (unsigned I = 0; I != NumResults; ++I) { 450 OS << "COMPLETION: "; 451 switch (Results[I].Kind) { 452 case CodeCompletionResult::RK_Declaration: 453 OS << Results[I].Declaration; 454 if (Results[I].Hidden) 455 OS << " (Hidden)"; 456 if (CodeCompletionString *CCS 457 = Results[I].CreateCodeCompletionString(SemaRef)) { 458 OS << " : " << CCS->getAsString(); 459 delete CCS; 460 } 461 462 OS << '\n'; 463 break; 464 465 case CodeCompletionResult::RK_Keyword: 466 OS << Results[I].Keyword << '\n'; 467 break; 468 469 case CodeCompletionResult::RK_Macro: { 470 OS << Results[I].Macro->getName(); 471 if (CodeCompletionString *CCS 472 = Results[I].CreateCodeCompletionString(SemaRef)) { 473 OS << " : " << CCS->getAsString(); 474 delete CCS; 475 } 476 OS << '\n'; 477 break; 478 } 479 480 case CodeCompletionResult::RK_Pattern: { 481 OS << "Pattern : " 482 << Results[I].Pattern->getAsString() << '\n'; 483 break; 484 } 485 } 486 } 487} 488 489void 490PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, 491 unsigned CurrentArg, 492 OverloadCandidate *Candidates, 493 unsigned NumCandidates) { 494 for (unsigned I = 0; I != NumCandidates; ++I) { 495 if (CodeCompletionString *CCS 496 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) { 497 OS << "OVERLOAD: " << CCS->getAsString() << "\n"; 498 delete CCS; 499 } 500 } 501} 502 503void CodeCompletionResult::computeCursorKindAndAvailability() { 504 switch (Kind) { 505 case RK_Declaration: 506 // Set the availability based on attributes. 507 Availability = CXAvailability_Available; 508 if (Declaration->getAttr<UnavailableAttr>()) 509 Availability = CXAvailability_NotAvailable; 510 else if (Declaration->getAttr<DeprecatedAttr>()) 511 Availability = CXAvailability_Deprecated; 512 513 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration)) 514 if (Function->isDeleted()) 515 Availability = CXAvailability_NotAvailable; 516 517 CursorKind = getCursorKindForDecl(Declaration); 518 if (CursorKind == CXCursor_UnexposedDecl) 519 CursorKind = CXCursor_NotImplemented; 520 break; 521 522 case RK_Macro: 523 Availability = CXAvailability_Available; 524 CursorKind = CXCursor_MacroDefinition; 525 break; 526 527 case RK_Keyword: 528 Availability = CXAvailability_Available; 529 CursorKind = CXCursor_NotImplemented; 530 break; 531 532 case RK_Pattern: 533 // Do nothing: Patterns can come with cursor kinds! 534 break; 535 } 536} 537 538/// \brief Retrieve the name that should be used to order a result. 539/// 540/// If the name needs to be constructed as a string, that string will be 541/// saved into Saved and the returned StringRef will refer to it. 542static llvm::StringRef getOrderedName(const CodeCompletionResult &R, 543 std::string &Saved) { 544 switch (R.Kind) { 545 case CodeCompletionResult::RK_Keyword: 546 return R.Keyword; 547 548 case CodeCompletionResult::RK_Pattern: 549 return R.Pattern->getTypedText(); 550 551 case CodeCompletionResult::RK_Macro: 552 return R.Macro->getName(); 553 554 case CodeCompletionResult::RK_Declaration: 555 // Handle declarations below. 556 break; 557 } 558 559 DeclarationName Name = R.Declaration->getDeclName(); 560 561 // If the name is a simple identifier (by far the common case), or a 562 // zero-argument selector, just return a reference to that identifier. 563 if (IdentifierInfo *Id = Name.getAsIdentifierInfo()) 564 return Id->getName(); 565 if (Name.isObjCZeroArgSelector()) 566 if (IdentifierInfo *Id 567 = Name.getObjCSelector().getIdentifierInfoForSlot(0)) 568 return Id->getName(); 569 570 Saved = Name.getAsString(); 571 return Saved; 572} 573 574bool clang::operator<(const CodeCompletionResult &X, 575 const CodeCompletionResult &Y) { 576 std::string XSaved, YSaved; 577 llvm::StringRef XStr = getOrderedName(X, XSaved); 578 llvm::StringRef YStr = getOrderedName(Y, YSaved); 579 int cmp = XStr.compare_lower(YStr); 580 if (cmp) 581 return cmp < 0; 582 583 // If case-insensitive comparison fails, try case-sensitive comparison. 584 cmp = XStr.compare(YStr); 585 if (cmp) 586 return cmp < 0; 587 588 return false; 589} 590 591void 592CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, 593 CodeCompletionContext Context, 594 CodeCompletionResult *Results, 595 unsigned NumResults) { 596 // Print the results. 597 for (unsigned I = 0; I != NumResults; ++I) { 598 WriteUnsigned(OS, Results[I].CursorKind); 599 WriteUnsigned(OS, Results[I].Priority); 600 WriteUnsigned(OS, Results[I].Availability); 601 CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef); 602 assert(CCS && "No code-completion string?"); 603 CCS->Serialize(OS); 604 delete CCS; 605 } 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 WriteUnsigned(OS, /*Priority=*/I); 616 WriteUnsigned(OS, /*Availability=*/CXAvailability_Available); 617 CodeCompletionString *CCS 618 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef); 619 assert(CCS && "No code-completion string?"); 620 CCS->Serialize(OS); 621 delete CCS; 622 } 623} 624