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