Deleted Added
sdiff udiff text old ( 199512 ) new ( 199990 )
full compact
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
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_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
90CodeCompletionString::Chunk
91CodeCompletionString::Chunk::CreateText(StringRef Text) {
92 return Chunk(CK_Text, Text);
93}
94
95CodeCompletionString::Chunk
96CodeCompletionString::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
104CodeCompletionString::Chunk
105CodeCompletionString::Chunk::CreatePlaceholder(StringRef Placeholder) {
106 return Chunk(CK_Placeholder, Placeholder);
107}
108
109CodeCompletionString::Chunk
110CodeCompletionString::Chunk::CreateInformative(StringRef Informative) {
111 return Chunk(CK_Informative, Informative);
112}
113
114CodeCompletionString::Chunk
115CodeCompletionString::Chunk::CreateCurrentParameter(
116 StringRef CurrentParameter) {
117 return Chunk(CK_CurrentParameter, CurrentParameter);
118}
119
120CodeCompletionString::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
148void
149CodeCompletionString::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
176CodeCompletionString::~CodeCompletionString() {
177 std::for_each(Chunks.begin(), Chunks.end(),
178 std::mem_fun_ref(&Chunk::Destroy));
179}
180
181std::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
198const 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
206CodeCompletionString *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
213static void WriteUnsigned(llvm::raw_ostream &OS, unsigned Value) {
214 OS.write((const char *)&Value, sizeof(unsigned));
215}
216
217static 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
227void 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
265CodeCompletionString *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
322void 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//===----------------------------------------------------------------------===//
332FunctionDecl *
333CodeCompleteConsumer::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
342const FunctionType *
343CodeCompleteConsumer::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
363CodeCompleteConsumer::~CodeCompleteConsumer() { }
364
365void
366PrintingCodeCompleteConsumer::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
416void
417PrintingCodeCompleteConsumer::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
435void
436CIndexCodeCompleteConsumer::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
553void
554CIndexCodeCompleteConsumer::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}