CodeCompleteConsumer.cpp revision 199512
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 "Sema.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringSwitch.h"
20#include "llvm/Support/Compiler.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
213namespace {
214  // Escape a string for XML-like formatting.
215  struct EscapedString {
216    EscapedString(llvm::StringRef Str) : Str(Str) { }
217
218    llvm::StringRef Str;
219  };
220
221  llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, EscapedString EStr) {
222    llvm::StringRef Str = EStr.Str;
223    while (!Str.empty()) {
224      // Find the next escaped character.
225      llvm::StringRef::size_type Pos = Str.find_first_of("<>&\"'");
226
227      // Print everything before that escaped character.
228      OS << Str.substr(0, Pos);
229
230      // If we didn't find any escaped characters, we're done.
231      if (Pos == llvm::StringRef::npos)
232        break;
233
234      // Print the appropriate escape sequence.
235      switch (Str[Pos]) {
236        case '<': OS << "&lt;"; break;
237        case '>': OS << "&gt;"; break;
238        case '&': OS << "&amp;"; break;
239        case '"': OS << "&quot;"; break;
240        case '\'': OS << "&apos;"; break;
241      }
242
243      // Remove everything up to and including that escaped character.
244      Str = Str.substr(Pos + 1);
245    }
246
247    return OS;
248  }
249
250  /// \brief Remove XML-like escaping from a string.
251  std::string UnescapeString(llvm::StringRef Str) {
252    using llvm::StringRef;
253
254    std::string Result;
255    llvm::raw_string_ostream OS(Result);
256
257    while (!Str.empty()) {
258      StringRef::size_type Amp = Str.find('&');
259      OS << Str.substr(0, Amp);
260
261      if (Amp == StringRef::npos)
262        break;
263
264      StringRef::size_type Semi = Str.substr(Amp).find(';');
265      if (Semi == StringRef::npos) {
266        // Malformed input; do the best we can.
267        OS << '&';
268        Str = Str.substr(Amp + 1);
269        continue;
270      }
271
272      char Unescaped = llvm::StringSwitch<char>(Str.substr(Amp + 1, Semi - 1))
273        .Case("lt", '<')
274        .Case("gt", '>')
275        .Case("amp", '&')
276        .Case("quot", '"')
277        .Case("apos", '\'')
278        .Default('\0');
279
280      if (Unescaped)
281        OS << Unescaped;
282      else
283        OS << Str.substr(Amp, Semi + 1);
284      Str = Str.substr(Amp + Semi + 1);
285    }
286
287    return OS.str();
288  }
289}
290
291void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const {
292  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
293    switch (C->Kind) {
294    case CK_TypedText:
295      OS << "<typed-text>" << EscapedString(C->Text) << "</>";
296      break;
297    case CK_Text:
298      OS << "<text>" << EscapedString(C->Text) << "</>";
299      break;
300    case CK_Optional:
301      OS << "<optional>";
302      C->Optional->Serialize(OS);
303      OS << "</>";
304      break;
305    case CK_Placeholder:
306      OS << "<placeholder>" << EscapedString(C->Text) << "</>";
307      break;
308    case CK_Informative:
309      OS << "<informative>" << EscapedString(C->Text) << "</>";
310      break;
311    case CK_CurrentParameter:
312      OS << "<current-parameter>" << EscapedString(C->Text) << "</>";
313      break;
314    case CK_LeftParen:
315      OS << "<lparen/>";
316      break;
317    case CK_RightParen:
318      OS << "<rparen/>";
319      break;
320    case CK_LeftBracket:
321      OS << "<lbracket/>";
322      break;
323    case CK_RightBracket:
324      OS << "<rbracket/>";
325      break;
326    case CK_LeftBrace:
327      OS << "<lbrace/>";
328      break;
329    case CK_RightBrace:
330      OS << "<rbrace/>";
331      break;
332    case CK_LeftAngle:
333      OS << "<langle/>";
334      break;
335    case CK_RightAngle:
336      OS << "<rangle/>";
337      break;
338    case CK_Comma:
339      OS << "<comma/>";
340      break;
341    }
342  }
343}
344
345/// \brief Parse the next XML-ish tag of the form <blah>.
346///
347/// \param Str the string in which we're looking for the next tag.
348///
349/// \param TagPos if successful, will be set to the start of the tag we found.
350///
351/// \param Standalone will indicate whether this is a "standalone" tag that
352/// has no associated data, e.g., <comma/>.
353///
354/// \param Terminator will indicate whether this is a terminating tag (that is
355/// or starts with '/').
356///
357/// \returns the tag itself, without the angle brackets.
358static llvm::StringRef ParseNextTag(llvm::StringRef Str,
359                                    llvm::StringRef::size_type &StartTag,
360                                    llvm::StringRef::size_type &AfterTag,
361                                    bool &Standalone, bool &Terminator) {
362  using llvm::StringRef;
363
364  Standalone = false;
365  Terminator = false;
366  AfterTag = StringRef::npos;
367
368  // Find the starting '<'.
369  StartTag = Str.find('<');
370  if (StartTag == StringRef::npos)
371    return llvm::StringRef();
372
373  // Find the corresponding '>'.
374  llvm::StringRef::size_type EndTag = Str.substr(StartTag).find('>');
375  if (EndTag == StringRef::npos)
376    return llvm::StringRef();
377  AfterTag = StartTag + EndTag + 1;
378
379  // Determine whether this is a terminating tag.
380  if (Str[StartTag + 1] == '/') {
381    Terminator = true;
382    Str = Str.substr(1);
383    --EndTag;
384  }
385
386  // Determine whether this is a standalone tag.
387  if (!Terminator && Str[StartTag + EndTag - 1] == '/') {
388    Standalone = true;
389    if (EndTag > 1)
390      --EndTag;
391  }
392
393  return Str.substr(StartTag + 1, EndTag - 1);
394}
395
396CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) {
397  using llvm::StringRef;
398
399  CodeCompletionString *Result = new CodeCompletionString;
400
401  do {
402    // Parse the next tag.
403    StringRef::size_type StartTag, AfterTag;
404    bool Standalone, Terminator;
405    StringRef Tag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
406                                 Terminator);
407
408    if (StartTag == StringRef::npos)
409      break;
410
411    // Figure out what kind of chunk we have.
412    const unsigned UnknownKind = 10000;
413    unsigned Kind = llvm::StringSwitch<unsigned>(Tag)
414      .Case("typed-text", CK_TypedText)
415      .Case("text", CK_Text)
416      .Case("optional", CK_Optional)
417      .Case("placeholder", CK_Placeholder)
418      .Case("informative", CK_Informative)
419      .Case("current-parameter", CK_CurrentParameter)
420      .Case("lparen", CK_LeftParen)
421      .Case("rparen", CK_RightParen)
422      .Case("lbracket", CK_LeftBracket)
423      .Case("rbracket", CK_RightBracket)
424      .Case("lbrace", CK_LeftBrace)
425      .Case("rbrace", CK_RightBrace)
426      .Case("langle", CK_LeftAngle)
427      .Case("rangle", CK_RightAngle)
428      .Case("comma", CK_Comma)
429      .Default(UnknownKind);
430
431    // If we've hit a terminator tag, we're done.
432    if (Terminator)
433      break;
434
435    // Consume the tag.
436    Str = Str.substr(AfterTag);
437
438    // Handle standalone tags now, since they don't need to be matched to
439    // anything.
440    if (Standalone) {
441      // Ignore anything we don't know about.
442      if (Kind == UnknownKind)
443        continue;
444
445      switch ((ChunkKind)Kind) {
446      case CK_TypedText:
447      case CK_Text:
448      case CK_Optional:
449      case CK_Placeholder:
450      case CK_Informative:
451      case CK_CurrentParameter:
452        // There is no point in creating empty chunks of these kinds.
453        break;
454
455      case CK_LeftParen:
456      case CK_RightParen:
457      case CK_LeftBracket:
458      case CK_RightBracket:
459      case CK_LeftBrace:
460      case CK_RightBrace:
461      case CK_LeftAngle:
462      case CK_RightAngle:
463      case CK_Comma:
464        Result->AddChunk(Chunk((ChunkKind)Kind));
465        break;
466      }
467
468      continue;
469    }
470
471    if (Kind == CK_Optional) {
472      // Deserialize the optional code-completion string.
473      std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str));
474      Result->AddOptionalChunk(Optional);
475    }
476
477    StringRef EndTag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
478                                    Terminator);
479    if (StartTag == StringRef::npos || !Terminator || Standalone)
480      break; // Parsing failed; just give up.
481
482    if (EndTag.empty() || Tag == EndTag) {
483      // Found the matching end tag. Add this chunk based on the text
484      // between the tags, then consume that input.
485      StringRef Text = Str.substr(0, StartTag);
486      switch ((ChunkKind)Kind) {
487      case CK_TypedText:
488      case CK_Text:
489      case CK_Placeholder:
490      case CK_Informative:
491      case CK_CurrentParameter:
492      case CK_LeftParen:
493      case CK_RightParen:
494      case CK_LeftBracket:
495      case CK_RightBracket:
496      case CK_LeftBrace:
497      case CK_RightBrace:
498      case CK_LeftAngle:
499      case CK_RightAngle:
500      case CK_Comma:
501        Result->AddChunk(Chunk((ChunkKind)Kind, UnescapeString(Text)));
502        break;
503
504      case CK_Optional:
505        // We've already added the optional chunk.
506        break;
507      }
508    }
509
510    // Remove this tag.
511    Str = Str.substr(AfterTag);
512  } while (!Str.empty());
513
514  return Result;
515}
516
517void CodeCompleteConsumer::Result::Destroy() {
518  if (Kind == RK_Pattern) {
519    delete Pattern;
520    Pattern = 0;
521  }
522}
523
524//===----------------------------------------------------------------------===//
525// Code completion overload candidate implementation
526//===----------------------------------------------------------------------===//
527FunctionDecl *
528CodeCompleteConsumer::OverloadCandidate::getFunction() const {
529  if (getKind() == CK_Function)
530    return Function;
531  else if (getKind() == CK_FunctionTemplate)
532    return FunctionTemplate->getTemplatedDecl();
533  else
534    return 0;
535}
536
537const FunctionType *
538CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
539  switch (Kind) {
540  case CK_Function:
541    return Function->getType()->getAs<FunctionType>();
542
543  case CK_FunctionTemplate:
544    return FunctionTemplate->getTemplatedDecl()->getType()
545             ->getAs<FunctionType>();
546
547  case CK_FunctionType:
548    return Type;
549  }
550
551  return 0;
552}
553
554//===----------------------------------------------------------------------===//
555// Code completion consumer implementation
556//===----------------------------------------------------------------------===//
557
558CodeCompleteConsumer::~CodeCompleteConsumer() { }
559
560void
561PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
562                                                         Result *Results,
563                                                         unsigned NumResults) {
564  // Print the results.
565  for (unsigned I = 0; I != NumResults; ++I) {
566    OS << "COMPLETION: ";
567    switch (Results[I].Kind) {
568    case Result::RK_Declaration:
569      OS << Results[I].Declaration->getNameAsString() << " : "
570         << Results[I].Rank;
571      if (Results[I].Hidden)
572        OS << " (Hidden)";
573      if (CodeCompletionString *CCS
574            = Results[I].CreateCodeCompletionString(SemaRef)) {
575        OS << " : " << CCS->getAsString();
576        delete CCS;
577      }
578
579      OS << '\n';
580      break;
581
582    case Result::RK_Keyword:
583      OS << Results[I].Keyword << " : " << Results[I].Rank << '\n';
584      break;
585
586    case Result::RK_Macro: {
587      OS << Results[I].Macro->getName() << " : " << Results[I].Rank;
588      if (CodeCompletionString *CCS
589          = Results[I].CreateCodeCompletionString(SemaRef)) {
590        OS << " : " << CCS->getAsString();
591        delete CCS;
592      }
593      OS << '\n';
594      break;
595    }
596
597    case Result::RK_Pattern: {
598      OS << "Pattern : " << Results[I].Rank << " : "
599         << Results[I].Pattern->getAsString() << '\n';
600      break;
601    }
602    }
603  }
604
605  // Once we've printed the code-completion results, suppress remaining
606  // diagnostics.
607  // FIXME: Move this somewhere else!
608  SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
609}
610
611void
612PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
613                                                        unsigned CurrentArg,
614                                              OverloadCandidate *Candidates,
615                                                     unsigned NumCandidates) {
616  for (unsigned I = 0; I != NumCandidates; ++I) {
617    if (CodeCompletionString *CCS
618          = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
619      OS << "OVERLOAD: " << CCS->getAsString() << "\n";
620      delete CCS;
621    }
622  }
623
624  // Once we've printed the code-completion results, suppress remaining
625  // diagnostics.
626  // FIXME: Move this somewhere else!
627  SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
628}
629
630void
631CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
632                                                       Result *Results,
633                                                       unsigned NumResults) {
634  // Print the results.
635  for (unsigned I = 0; I != NumResults; ++I) {
636    OS << "COMPLETION:" << Results[I].Rank << ":";
637    switch (Results[I].Kind) {
638      case Result::RK_Declaration:
639        if (RecordDecl *Record = dyn_cast<RecordDecl>(Results[I].Declaration)) {
640          if (Record->isStruct())
641            OS << "Struct:";
642          else if (Record->isUnion())
643            OS << "Union:";
644          else
645            OS << "Class:";
646        } else if (ObjCMethodDecl *Method
647                     = dyn_cast<ObjCMethodDecl>(Results[I].Declaration)) {
648          if (Method->isInstanceMethod())
649            OS << "ObjCInstanceMethod:";
650          else
651            OS << "ObjCClassMethod:";
652        } else {
653          OS << Results[I].Declaration->getDeclKindName() << ":";
654        }
655        if (CodeCompletionString *CCS
656              = Results[I].CreateCodeCompletionString(SemaRef)) {
657          CCS->Serialize(OS);
658          delete CCS;
659        } else {
660          OS << "<typed-text>"
661             << Results[I].Declaration->getNameAsString()
662             << "</>";
663        }
664
665        OS << '\n';
666        break;
667
668      case Result::RK_Keyword:
669        OS << "Keyword:<typed-text>" << Results[I].Keyword << "</>\n";
670        break;
671
672      case Result::RK_Macro: {
673        OS << "Macro:";
674        if (CodeCompletionString *CCS
675              = Results[I].CreateCodeCompletionString(SemaRef)) {
676          CCS->Serialize(OS);
677          delete CCS;
678        } else {
679          OS << "<typed-text>" << Results[I].Macro->getName() << "</>";
680        }
681        OS << '\n';
682        break;
683      }
684
685      case Result::RK_Pattern: {
686        OS << "Pattern:";
687        Results[I].Pattern->Serialize(OS);
688        OS << '\n';
689        break;
690      }
691    }
692  }
693
694  // Once we've printed the code-completion results, suppress remaining
695  // diagnostics.
696  // FIXME: Move this somewhere else!
697  SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
698}
699
700void
701CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
702                                                      unsigned CurrentArg,
703                                                OverloadCandidate *Candidates,
704                                                       unsigned NumCandidates) {
705  for (unsigned I = 0; I != NumCandidates; ++I) {
706    if (CodeCompletionString *CCS
707        = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
708      OS << "OVERLOAD:";
709      CCS->Serialize(OS);
710      OS << '\n';
711      delete CCS;
712    }
713  }
714
715  // Once we've printed the code-completion results, suppress remaining
716  // diagnostics.
717  // FIXME: Move this somewhere else!
718  SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
719}
720