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