CodeCompleteConsumer.cpp revision 85b4521e34dcd4a0a4a1f0819e1123128e5a3125
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/raw_ostream.h"
21#include <algorithm>
22#include <cstring>
23#include <functional>
24
25using namespace clang;
26using llvm::StringRef;
27
28//===----------------------------------------------------------------------===//
29// Code completion string implementation
30//===----------------------------------------------------------------------===//
31CodeCompletionString::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_CurrentParameter: {
40    char *New = new char [Text.size() + 1];
41    std::memcpy(New, Text.data(), Text.size());
42    New[Text.size()] = '\0';
43    this->Text = New;
44    break;
45  }
46
47  case CK_Optional:
48    llvm::llvm_unreachable("Optional strings cannot be created from text");
49    break;
50
51  case CK_LeftParen:
52    this->Text = "(";
53    break;
54
55  case CK_RightParen:
56    this->Text = ")";
57    break;
58
59  case CK_LeftBracket:
60    this->Text = "[";
61    break;
62
63  case CK_RightBracket:
64    this->Text = "]";
65    break;
66
67  case CK_LeftBrace:
68    this->Text = "{";
69    break;
70
71  case CK_RightBrace:
72    this->Text = "}";
73    break;
74
75  case CK_LeftAngle:
76    this->Text = "<";
77    break;
78
79  case CK_RightAngle:
80    this->Text = ">";
81    break;
82
83  case CK_Comma:
84    this->Text = ", ";
85    break;
86  }
87}
88
89CodeCompletionString::Chunk
90CodeCompletionString::Chunk::CreateText(StringRef Text) {
91  return Chunk(CK_Text, Text);
92}
93
94CodeCompletionString::Chunk
95CodeCompletionString::Chunk::CreateOptional(
96                                 std::auto_ptr<CodeCompletionString> Optional) {
97  Chunk Result;
98  Result.Kind = CK_Optional;
99  Result.Optional = Optional.release();
100  return Result;
101}
102
103CodeCompletionString::Chunk
104CodeCompletionString::Chunk::CreatePlaceholder(StringRef Placeholder) {
105  return Chunk(CK_Placeholder, Placeholder);
106}
107
108CodeCompletionString::Chunk
109CodeCompletionString::Chunk::CreateInformative(StringRef Informative) {
110  return Chunk(CK_Informative, Informative);
111}
112
113CodeCompletionString::Chunk
114CodeCompletionString::Chunk::CreateCurrentParameter(
115                                                StringRef CurrentParameter) {
116  return Chunk(CK_CurrentParameter, CurrentParameter);
117}
118
119CodeCompletionString::Chunk CodeCompletionString::Chunk::Clone() const {
120  switch (Kind) {
121  case CK_TypedText:
122  case CK_Text:
123  case CK_Placeholder:
124  case CK_Informative:
125  case CK_CurrentParameter:
126  case CK_LeftParen:
127  case CK_RightParen:
128  case CK_LeftBracket:
129  case CK_RightBracket:
130  case CK_LeftBrace:
131  case CK_RightBrace:
132  case CK_LeftAngle:
133  case CK_RightAngle:
134  case CK_Comma:
135    return Chunk(Kind, Text);
136
137  case CK_Optional: {
138    std::auto_ptr<CodeCompletionString> Opt(Optional->Clone());
139    return CreateOptional(Opt);
140  }
141  }
142
143  // Silence GCC warning.
144  return Chunk();
145}
146
147void
148CodeCompletionString::Chunk::Destroy() {
149  switch (Kind) {
150  case CK_Optional:
151    delete Optional;
152    break;
153
154  case CK_TypedText:
155  case CK_Text:
156  case CK_Placeholder:
157  case CK_Informative:
158  case CK_CurrentParameter:
159    delete [] Text;
160    break;
161
162  case CK_LeftParen:
163  case CK_RightParen:
164  case CK_LeftBracket:
165  case CK_RightBracket:
166  case CK_LeftBrace:
167  case CK_RightBrace:
168  case CK_LeftAngle:
169  case CK_RightAngle:
170  case CK_Comma:
171    break;
172  }
173}
174
175CodeCompletionString::~CodeCompletionString() {
176  std::for_each(Chunks.begin(), Chunks.end(),
177                std::mem_fun_ref(&Chunk::Destroy));
178}
179
180std::string CodeCompletionString::getAsString() const {
181  std::string Result;
182  llvm::raw_string_ostream OS(Result);
183
184  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
185    switch (C->Kind) {
186    case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
187    case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
188    case CK_Informative: OS << "[#" << C->Text << "#]"; break;
189    case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
190    default: OS << C->Text; break;
191    }
192  }
193  OS.flush();
194  return Result;
195}
196
197const char *CodeCompletionString::getTypedText() const {
198  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
199    if (C->Kind == CK_TypedText)
200      return C->Text;
201
202  return 0;
203}
204
205CodeCompletionString *CodeCompletionString::Clone() const {
206  CodeCompletionString *Result = new CodeCompletionString;
207  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
208    Result->AddChunk(C->Clone());
209  return Result;
210}
211
212namespace {
213  // Escape a string for XML-like formatting.
214  struct EscapedString {
215    EscapedString(llvm::StringRef Str) : Str(Str) { }
216
217    llvm::StringRef Str;
218  };
219
220  llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, EscapedString EStr) {
221    llvm::StringRef Str = EStr.Str;
222    while (!Str.empty()) {
223      // Find the next escaped character.
224      llvm::StringRef::size_type Pos = Str.find_first_of("<>&\"'");
225
226      // Print everything before that escaped character.
227      OS << Str.substr(0, Pos);
228
229      // If we didn't find any escaped characters, we're done.
230      if (Pos == llvm::StringRef::npos)
231        break;
232
233      // Print the appropriate escape sequence.
234      switch (Str[Pos]) {
235        case '<': OS << "&lt;"; break;
236        case '>': OS << "&gt;"; break;
237        case '&': OS << "&amp;"; break;
238        case '"': OS << "&quot;"; break;
239        case '\'': OS << "&apos;"; break;
240      }
241
242      // Remove everything up to and including that escaped character.
243      Str = Str.substr(Pos + 1);
244    }
245
246    return OS;
247  }
248
249  /// \brief Remove XML-like escaping from a string.
250  std::string UnescapeString(llvm::StringRef Str) {
251    using llvm::StringRef;
252
253    std::string Result;
254    llvm::raw_string_ostream OS(Result);
255
256    while (!Str.empty()) {
257      StringRef::size_type Amp = Str.find('&');
258      OS << Str.substr(0, Amp);
259
260      if (Amp == StringRef::npos)
261        break;
262
263      StringRef::size_type Semi = Str.substr(Amp).find(';');
264      if (Semi == StringRef::npos) {
265        // Malformed input; do the best we can.
266        OS << '&';
267        Str = Str.substr(Amp + 1);
268        continue;
269      }
270
271      char Unescaped = llvm::StringSwitch<char>(Str.substr(Amp + 1, Semi - 1))
272        .Case("lt", '<')
273        .Case("gt", '>')
274        .Case("amp", '&')
275        .Case("quot", '"')
276        .Case("apos", '\'')
277        .Default('\0');
278
279      if (Unescaped)
280        OS << Unescaped;
281      else
282        OS << Str.substr(Amp, Semi + 1);
283      Str = Str.substr(Amp + Semi + 1);
284    }
285
286    return OS.str();
287  }
288}
289
290void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const {
291  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
292    switch (C->Kind) {
293    case CK_TypedText:
294      OS << "<typed-text>" << EscapedString(C->Text) << "</>";
295      break;
296    case CK_Text:
297      OS << "<text>" << EscapedString(C->Text) << "</>";
298      break;
299    case CK_Optional:
300      OS << "<optional>";
301      C->Optional->Serialize(OS);
302      OS << "</>";
303      break;
304    case CK_Placeholder:
305      OS << "<placeholder>" << EscapedString(C->Text) << "</>";
306      break;
307    case CK_Informative:
308      OS << "<informative>" << EscapedString(C->Text) << "</>";
309      break;
310    case CK_CurrentParameter:
311      OS << "<current-parameter>" << EscapedString(C->Text) << "</>";
312      break;
313    case CK_LeftParen:
314      OS << "<lparen/>";
315      break;
316    case CK_RightParen:
317      OS << "<rparen/>";
318      break;
319    case CK_LeftBracket:
320      OS << "<lbracket/>";
321      break;
322    case CK_RightBracket:
323      OS << "<rbracket/>";
324      break;
325    case CK_LeftBrace:
326      OS << "<lbrace/>";
327      break;
328    case CK_RightBrace:
329      OS << "<rbrace/>";
330      break;
331    case CK_LeftAngle:
332      OS << "<langle/>";
333      break;
334    case CK_RightAngle:
335      OS << "<rangle/>";
336      break;
337    case CK_Comma:
338      OS << "<comma/>";
339      break;
340    }
341  }
342}
343
344/// \brief Parse the next XML-ish tag of the form <blah>.
345///
346/// \param Str the string in which we're looking for the next tag.
347///
348/// \param TagPos if successful, will be set to the start of the tag we found.
349///
350/// \param Standalone will indicate whether this is a "standalone" tag that
351/// has no associated data, e.g., <comma/>.
352///
353/// \param Terminator will indicate whether this is a terminating tag (that is
354/// or starts with '/').
355///
356/// \returns the tag itself, without the angle brackets.
357static llvm::StringRef ParseNextTag(llvm::StringRef Str,
358                                    llvm::StringRef::size_type &StartTag,
359                                    llvm::StringRef::size_type &AfterTag,
360                                    bool &Standalone, bool &Terminator) {
361  using llvm::StringRef;
362
363  Standalone = false;
364  Terminator = false;
365  AfterTag = StringRef::npos;
366
367  // Find the starting '<'.
368  StartTag = Str.find('<');
369  if (StartTag == StringRef::npos)
370    return llvm::StringRef();
371
372  // Find the corresponding '>'.
373  llvm::StringRef::size_type EndTag = Str.substr(StartTag).find('>');
374  if (EndTag == StringRef::npos)
375    return llvm::StringRef();
376  AfterTag = StartTag + EndTag + 1;
377
378  // Determine whether this is a terminating tag.
379  if (Str[StartTag + 1] == '/') {
380    Terminator = true;
381    Str = Str.substr(1);
382    --EndTag;
383  }
384
385  // Determine whether this is a standalone tag.
386  if (!Terminator && Str[StartTag + EndTag - 1] == '/') {
387    Standalone = true;
388    if (EndTag > 1)
389      --EndTag;
390  }
391
392  return Str.substr(StartTag + 1, EndTag - 1);
393}
394
395CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) {
396  using llvm::StringRef;
397
398  CodeCompletionString *Result = new CodeCompletionString;
399
400  do {
401    // Parse the next tag.
402    StringRef::size_type StartTag, AfterTag;
403    bool Standalone, Terminator;
404    StringRef Tag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
405                                 Terminator);
406
407    if (StartTag == StringRef::npos)
408      break;
409
410    // Figure out what kind of chunk we have.
411    const unsigned UnknownKind = 10000;
412    unsigned Kind = llvm::StringSwitch<unsigned>(Tag)
413      .Case("typed-text", CK_TypedText)
414      .Case("text", CK_Text)
415      .Case("optional", CK_Optional)
416      .Case("placeholder", CK_Placeholder)
417      .Case("informative", CK_Informative)
418      .Case("current-parameter", CK_CurrentParameter)
419      .Case("lparen", CK_LeftParen)
420      .Case("rparen", CK_RightParen)
421      .Case("lbracket", CK_LeftBracket)
422      .Case("rbracket", CK_RightBracket)
423      .Case("lbrace", CK_LeftBrace)
424      .Case("rbrace", CK_RightBrace)
425      .Case("langle", CK_LeftAngle)
426      .Case("rangle", CK_RightAngle)
427      .Case("comma", CK_Comma)
428      .Default(UnknownKind);
429
430    // If we've hit a terminator tag, we're done.
431    if (Terminator)
432      break;
433
434    // Consume the tag.
435    Str = Str.substr(AfterTag);
436
437    // Handle standalone tags now, since they don't need to be matched to
438    // anything.
439    if (Standalone) {
440      // Ignore anything we don't know about.
441      if (Kind == UnknownKind)
442        continue;
443
444      switch ((ChunkKind)Kind) {
445      case CK_TypedText:
446      case CK_Text:
447      case CK_Optional:
448      case CK_Placeholder:
449      case CK_Informative:
450      case CK_CurrentParameter:
451        // There is no point in creating empty chunks of these kinds.
452        break;
453
454      case CK_LeftParen:
455      case CK_RightParen:
456      case CK_LeftBracket:
457      case CK_RightBracket:
458      case CK_LeftBrace:
459      case CK_RightBrace:
460      case CK_LeftAngle:
461      case CK_RightAngle:
462      case CK_Comma:
463        Result->AddChunk(Chunk((ChunkKind)Kind));
464        break;
465      }
466
467      continue;
468    }
469
470    if (Kind == CK_Optional) {
471      // Deserialize the optional code-completion string.
472      std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str));
473      Result->AddOptionalChunk(Optional);
474    }
475
476    StringRef EndTag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
477                                    Terminator);
478    if (StartTag == StringRef::npos || !Terminator || Standalone)
479      break; // Parsing failed; just give up.
480
481    if (EndTag.empty() || Tag == EndTag) {
482      // Found the matching end tag. Add this chunk based on the text
483      // between the tags, then consume that input.
484      StringRef Text = Str.substr(0, StartTag);
485      switch ((ChunkKind)Kind) {
486      case CK_TypedText:
487      case CK_Text:
488      case CK_Placeholder:
489      case CK_Informative:
490      case CK_CurrentParameter:
491      case CK_LeftParen:
492      case CK_RightParen:
493      case CK_LeftBracket:
494      case CK_RightBracket:
495      case CK_LeftBrace:
496      case CK_RightBrace:
497      case CK_LeftAngle:
498      case CK_RightAngle:
499      case CK_Comma:
500        Result->AddChunk(Chunk((ChunkKind)Kind, UnescapeString(Text)));
501        break;
502
503      case CK_Optional:
504        // We've already added the optional chunk.
505        break;
506      }
507    }
508
509    // Remove this tag.
510    Str = Str.substr(AfterTag);
511  } while (!Str.empty());
512
513  return Result;
514}
515
516void CodeCompleteConsumer::Result::Destroy() {
517  if (Kind == RK_Pattern) {
518    delete Pattern;
519    Pattern = 0;
520  }
521}
522
523//===----------------------------------------------------------------------===//
524// Code completion overload candidate implementation
525//===----------------------------------------------------------------------===//
526FunctionDecl *
527CodeCompleteConsumer::OverloadCandidate::getFunction() const {
528  if (getKind() == CK_Function)
529    return Function;
530  else if (getKind() == CK_FunctionTemplate)
531    return FunctionTemplate->getTemplatedDecl();
532  else
533    return 0;
534}
535
536const FunctionType *
537CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
538  switch (Kind) {
539  case CK_Function:
540    return Function->getType()->getAs<FunctionType>();
541
542  case CK_FunctionTemplate:
543    return FunctionTemplate->getTemplatedDecl()->getType()
544             ->getAs<FunctionType>();
545
546  case CK_FunctionType:
547    return Type;
548  }
549
550  return 0;
551}
552
553//===----------------------------------------------------------------------===//
554// Code completion consumer implementation
555//===----------------------------------------------------------------------===//
556
557CodeCompleteConsumer::~CodeCompleteConsumer() { }
558
559void
560PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
561                                                         Result *Results,
562                                                         unsigned NumResults) {
563  // Print the results.
564  for (unsigned I = 0; I != NumResults; ++I) {
565    OS << "COMPLETION: ";
566    switch (Results[I].Kind) {
567    case Result::RK_Declaration:
568      OS << Results[I].Declaration->getNameAsString() << " : "
569         << Results[I].Rank;
570      if (Results[I].Hidden)
571        OS << " (Hidden)";
572      if (CodeCompletionString *CCS
573            = Results[I].CreateCodeCompletionString(SemaRef)) {
574        OS << " : " << CCS->getAsString();
575        delete CCS;
576      }
577
578      OS << '\n';
579      break;
580
581    case Result::RK_Keyword:
582      OS << Results[I].Keyword << " : " << Results[I].Rank << '\n';
583      break;
584
585    case Result::RK_Macro: {
586      OS << Results[I].Macro->getName() << " : " << Results[I].Rank;
587      if (CodeCompletionString *CCS
588          = Results[I].CreateCodeCompletionString(SemaRef)) {
589        OS << " : " << CCS->getAsString();
590        delete CCS;
591      }
592      OS << '\n';
593      break;
594    }
595
596    case Result::RK_Pattern: {
597      OS << "Pattern : " << Results[I].Rank << " : "
598         << Results[I].Pattern->getAsString() << '\n';
599      break;
600    }
601    }
602  }
603
604  // Once we've printed the code-completion results, suppress remaining
605  // diagnostics.
606  // FIXME: Move this somewhere else!
607  SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
608}
609
610void
611PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
612                                                        unsigned CurrentArg,
613                                              OverloadCandidate *Candidates,
614                                                     unsigned NumCandidates) {
615  for (unsigned I = 0; I != NumCandidates; ++I) {
616    if (CodeCompletionString *CCS
617          = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
618      OS << "OVERLOAD: " << CCS->getAsString() << "\n";
619      delete CCS;
620    }
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}
628
629void
630CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
631                                                       Result *Results,
632                                                       unsigned NumResults) {
633  // Print the results.
634  for (unsigned I = 0; I != NumResults; ++I) {
635    OS << "COMPLETION:" << Results[I].Rank << ":";
636    switch (Results[I].Kind) {
637      case Result::RK_Declaration:
638        if (RecordDecl *Record = dyn_cast<RecordDecl>(Results[I].Declaration)) {
639          if (Record->isStruct())
640            OS << "Struct:";
641          else if (Record->isUnion())
642            OS << "Union:";
643          else
644            OS << "Class:";
645        } else if (ObjCMethodDecl *Method
646                     = dyn_cast<ObjCMethodDecl>(Results[I].Declaration)) {
647          if (Method->isInstanceMethod())
648            OS << "ObjCInstanceMethod:";
649          else
650            OS << "ObjCClassMethod:";
651        } else {
652          OS << Results[I].Declaration->getDeclKindName() << ":";
653        }
654        if (CodeCompletionString *CCS
655              = Results[I].CreateCodeCompletionString(SemaRef)) {
656          CCS->Serialize(OS);
657          delete CCS;
658        } else {
659          OS << "<typed-text>"
660             << Results[I].Declaration->getNameAsString()
661             << "</>";
662        }
663
664        OS << '\n';
665        break;
666
667      case Result::RK_Keyword:
668        OS << "Keyword:<typed-text>" << Results[I].Keyword << "</>\n";
669        break;
670
671      case Result::RK_Macro: {
672        OS << "Macro:";
673        if (CodeCompletionString *CCS
674              = Results[I].CreateCodeCompletionString(SemaRef)) {
675          CCS->Serialize(OS);
676          delete CCS;
677        } else {
678          OS << "<typed-text>" << Results[I].Macro->getName() << "</>";
679        }
680        OS << '\n';
681        break;
682      }
683
684      case Result::RK_Pattern: {
685        OS << "Pattern:";
686        Results[I].Pattern->Serialize(OS);
687        OS << '\n';
688        break;
689      }
690    }
691  }
692
693  // Once we've printed the code-completion results, suppress remaining
694  // diagnostics.
695  // FIXME: Move this somewhere else!
696  SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
697}
698
699void
700CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
701                                                      unsigned CurrentArg,
702                                                OverloadCandidate *Candidates,
703                                                       unsigned NumCandidates) {
704  for (unsigned I = 0; I != NumCandidates; ++I) {
705    if (CodeCompletionString *CCS
706        = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
707      OS << "OVERLOAD:";
708      CCS->Serialize(OS);
709      OS << '\n';
710      delete CCS;
711    }
712  }
713
714  // Once we've printed the code-completion results, suppress remaining
715  // diagnostics.
716  // FIXME: Move this somewhere else!
717  SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
718}
719