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