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