CodeCompleteConsumer.cpp revision 218893
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/Sema/Scope.h"
15#include "clang/Sema/Sema.h"
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/DeclObjC.h"
18#include "clang/AST/DeclTemplate.h"
19#include "clang/Lex/Preprocessor.h"
20#include "clang-c/Index.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/Twine.h"
23#include "llvm/Support/raw_ostream.h"
24#include <algorithm>
25#include <cstring>
26#include <functional>
27
28using namespace clang;
29using llvm::StringRef;
30
31//===----------------------------------------------------------------------===//
32// Code completion context implementation
33//===----------------------------------------------------------------------===//
34
35bool CodeCompletionContext::wantConstructorResults() const {
36  switch (Kind) {
37  case CCC_Recovery:
38  case CCC_Statement:
39  case CCC_Expression:
40  case CCC_ObjCMessageReceiver:
41  case CCC_ParenthesizedExpression:
42    return true;
43
44  case CCC_TopLevel:
45  case CCC_ObjCInterface:
46  case CCC_ObjCImplementation:
47  case CCC_ObjCIvarList:
48  case CCC_ClassStructUnion:
49  case CCC_MemberAccess:
50  case CCC_EnumTag:
51  case CCC_UnionTag:
52  case CCC_ClassOrStructTag:
53  case CCC_ObjCProtocolName:
54  case CCC_Namespace:
55  case CCC_Type:
56  case CCC_Name:
57  case CCC_PotentiallyQualifiedName:
58  case CCC_MacroName:
59  case CCC_MacroNameUse:
60  case CCC_PreprocessorExpression:
61  case CCC_PreprocessorDirective:
62  case CCC_NaturalLanguage:
63  case CCC_SelectorName:
64  case CCC_TypeQualifiers:
65  case CCC_Other:
66  case CCC_OtherWithMacros:
67    return false;
68  }
69
70  return false;
71}
72
73//===----------------------------------------------------------------------===//
74// Code completion string implementation
75//===----------------------------------------------------------------------===//
76CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text)
77  : Kind(Kind), Text("")
78{
79  switch (Kind) {
80  case CK_TypedText:
81  case CK_Text:
82  case CK_Placeholder:
83  case CK_Informative:
84  case CK_ResultType:
85  case CK_CurrentParameter:
86    this->Text = Text;
87    break;
88
89  case CK_Optional:
90    llvm_unreachable("Optional strings cannot be created from text");
91    break;
92
93  case CK_LeftParen:
94    this->Text = "(";
95    break;
96
97  case CK_RightParen:
98    this->Text = ")";
99    break;
100
101  case CK_LeftBracket:
102    this->Text = "[";
103    break;
104
105  case CK_RightBracket:
106    this->Text = "]";
107    break;
108
109  case CK_LeftBrace:
110    this->Text = "{";
111    break;
112
113  case CK_RightBrace:
114    this->Text = "}";
115    break;
116
117  case CK_LeftAngle:
118    this->Text = "<";
119    break;
120
121  case CK_RightAngle:
122    this->Text = ">";
123    break;
124
125  case CK_Comma:
126    this->Text = ", ";
127    break;
128
129  case CK_Colon:
130    this->Text = ":";
131    break;
132
133  case CK_SemiColon:
134    this->Text = ";";
135    break;
136
137  case CK_Equal:
138    this->Text = " = ";
139    break;
140
141  case CK_HorizontalSpace:
142    this->Text = " ";
143    break;
144
145  case CK_VerticalSpace:
146    this->Text = "\n";
147    break;
148  }
149}
150
151CodeCompletionString::Chunk
152CodeCompletionString::Chunk::CreateText(const char *Text) {
153  return Chunk(CK_Text, Text);
154}
155
156CodeCompletionString::Chunk
157CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) {
158  Chunk Result;
159  Result.Kind = CK_Optional;
160  Result.Optional = Optional;
161  return Result;
162}
163
164CodeCompletionString::Chunk
165CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) {
166  return Chunk(CK_Placeholder, Placeholder);
167}
168
169CodeCompletionString::Chunk
170CodeCompletionString::Chunk::CreateInformative(const char *Informative) {
171  return Chunk(CK_Informative, Informative);
172}
173
174CodeCompletionString::Chunk
175CodeCompletionString::Chunk::CreateResultType(const char *ResultType) {
176  return Chunk(CK_ResultType, ResultType);
177}
178
179CodeCompletionString::Chunk
180CodeCompletionString::Chunk::CreateCurrentParameter(
181                                                const char *CurrentParameter) {
182  return Chunk(CK_CurrentParameter, CurrentParameter);
183}
184
185CodeCompletionString::CodeCompletionString(const Chunk *Chunks,
186                                           unsigned NumChunks,
187                                           unsigned Priority,
188                                           CXAvailabilityKind Availability)
189  : NumChunks(NumChunks), Priority(Priority), Availability(Availability)
190{
191  Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1);
192  for (unsigned I = 0; I != NumChunks; ++I)
193    StoredChunks[I] = Chunks[I];
194}
195
196std::string CodeCompletionString::getAsString() const {
197  std::string Result;
198  llvm::raw_string_ostream OS(Result);
199
200  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
201    switch (C->Kind) {
202    case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
203    case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
204
205    case CK_Informative:
206    case CK_ResultType:
207      OS << "[#" << C->Text << "#]";
208      break;
209
210    case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
211    default: OS << C->Text; break;
212    }
213  }
214  return OS.str();
215}
216
217const char *CodeCompletionString::getTypedText() const {
218  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
219    if (C->Kind == CK_TypedText)
220      return C->Text;
221
222  return 0;
223}
224
225const char *CodeCompletionAllocator::CopyString(llvm::StringRef String) {
226  char *Mem = (char *)Allocate(String.size() + 1, 1);
227  std::copy(String.begin(), String.end(), Mem);
228  Mem[String.size()] = 0;
229  return Mem;
230}
231
232const char *CodeCompletionAllocator::CopyString(llvm::Twine String) {
233  // FIXME: It would be more efficient to teach Twine to tell us its size and
234  // then add a routine there to fill in an allocated char* with the contents
235  // of the string.
236  llvm::SmallString<128> Data;
237  return CopyString(String.toStringRef(Data));
238}
239
240CodeCompletionString *CodeCompletionBuilder::TakeString() {
241  void *Mem = Allocator.Allocate(
242                  sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size(),
243                                 llvm::alignOf<CodeCompletionString>());
244  CodeCompletionString *Result
245    = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(),
246                               Priority, Availability);
247  Chunks.clear();
248  return Result;
249}
250
251unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) {
252  if (!ND)
253    return CCP_Unlikely;
254
255  // Context-based decisions.
256  DeclContext *DC = ND->getDeclContext()->getRedeclContext();
257  if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) {
258    // _cmd is relatively rare
259    if (ImplicitParamDecl *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
260      if (ImplicitParam->getIdentifier() &&
261          ImplicitParam->getIdentifier()->isStr("_cmd"))
262        return CCP_ObjC_cmd;
263
264    return CCP_LocalDeclaration;
265  }
266  if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
267    return CCP_MemberDeclaration;
268
269  // Content-based decisions.
270  if (isa<EnumConstantDecl>(ND))
271    return CCP_Constant;
272  if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
273    return CCP_Type;
274
275  return CCP_Declaration;
276}
277
278//===----------------------------------------------------------------------===//
279// Code completion overload candidate implementation
280//===----------------------------------------------------------------------===//
281FunctionDecl *
282CodeCompleteConsumer::OverloadCandidate::getFunction() const {
283  if (getKind() == CK_Function)
284    return Function;
285  else if (getKind() == CK_FunctionTemplate)
286    return FunctionTemplate->getTemplatedDecl();
287  else
288    return 0;
289}
290
291const FunctionType *
292CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
293  switch (Kind) {
294  case CK_Function:
295    return Function->getType()->getAs<FunctionType>();
296
297  case CK_FunctionTemplate:
298    return FunctionTemplate->getTemplatedDecl()->getType()
299             ->getAs<FunctionType>();
300
301  case CK_FunctionType:
302    return Type;
303  }
304
305  return 0;
306}
307
308//===----------------------------------------------------------------------===//
309// Code completion consumer implementation
310//===----------------------------------------------------------------------===//
311
312CodeCompleteConsumer::~CodeCompleteConsumer() { }
313
314void
315PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
316                                                 CodeCompletionContext Context,
317                                                 CodeCompletionResult *Results,
318                                                         unsigned NumResults) {
319  std::stable_sort(Results, Results + NumResults);
320
321  // Print the results.
322  for (unsigned I = 0; I != NumResults; ++I) {
323    OS << "COMPLETION: ";
324    switch (Results[I].Kind) {
325    case CodeCompletionResult::RK_Declaration:
326      OS << Results[I].Declaration;
327      if (Results[I].Hidden)
328        OS << " (Hidden)";
329      if (CodeCompletionString *CCS
330            = Results[I].CreateCodeCompletionString(SemaRef, Allocator)) {
331        OS << " : " << CCS->getAsString();
332      }
333
334      OS << '\n';
335      break;
336
337    case CodeCompletionResult::RK_Keyword:
338      OS << Results[I].Keyword << '\n';
339      break;
340
341    case CodeCompletionResult::RK_Macro: {
342      OS << Results[I].Macro->getName();
343      if (CodeCompletionString *CCS
344            = Results[I].CreateCodeCompletionString(SemaRef, Allocator)) {
345        OS << " : " << CCS->getAsString();
346      }
347      OS << '\n';
348      break;
349    }
350
351    case CodeCompletionResult::RK_Pattern: {
352      OS << "Pattern : "
353         << Results[I].Pattern->getAsString() << '\n';
354      break;
355    }
356    }
357  }
358}
359
360void
361PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
362                                                        unsigned CurrentArg,
363                                              OverloadCandidate *Candidates,
364                                                     unsigned NumCandidates) {
365  for (unsigned I = 0; I != NumCandidates; ++I) {
366    if (CodeCompletionString *CCS
367          = Candidates[I].CreateSignatureString(CurrentArg, SemaRef,
368                                                Allocator)) {
369      OS << "OVERLOAD: " << CCS->getAsString() << "\n";
370    }
371  }
372}
373
374void CodeCompletionResult::computeCursorKindAndAvailability() {
375  switch (Kind) {
376  case RK_Declaration:
377    // Set the availability based on attributes.
378    Availability = CXAvailability_Available;
379    if (Declaration->getAttr<UnavailableAttr>())
380      Availability = CXAvailability_NotAvailable;
381    else if (Declaration->getAttr<DeprecatedAttr>())
382      Availability = CXAvailability_Deprecated;
383
384    if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration))
385      if (Function->isDeleted())
386        Availability = CXAvailability_NotAvailable;
387
388    CursorKind = getCursorKindForDecl(Declaration);
389    if (CursorKind == CXCursor_UnexposedDecl)
390      CursorKind = CXCursor_NotImplemented;
391    break;
392
393  case RK_Macro:
394    Availability = CXAvailability_Available;
395    CursorKind = CXCursor_MacroDefinition;
396    break;
397
398  case RK_Keyword:
399    Availability = CXAvailability_Available;
400    CursorKind = CXCursor_NotImplemented;
401    break;
402
403  case RK_Pattern:
404    // Do nothing: Patterns can come with cursor kinds!
405    break;
406  }
407}
408
409/// \brief Retrieve the name that should be used to order a result.
410///
411/// If the name needs to be constructed as a string, that string will be
412/// saved into Saved and the returned StringRef will refer to it.
413static llvm::StringRef getOrderedName(const CodeCompletionResult &R,
414                                    std::string &Saved) {
415  switch (R.Kind) {
416    case CodeCompletionResult::RK_Keyword:
417      return R.Keyword;
418
419    case CodeCompletionResult::RK_Pattern:
420      return R.Pattern->getTypedText();
421
422    case CodeCompletionResult::RK_Macro:
423      return R.Macro->getName();
424
425    case CodeCompletionResult::RK_Declaration:
426      // Handle declarations below.
427      break;
428  }
429
430  DeclarationName Name = R.Declaration->getDeclName();
431
432  // If the name is a simple identifier (by far the common case), or a
433  // zero-argument selector, just return a reference to that identifier.
434  if (IdentifierInfo *Id = Name.getAsIdentifierInfo())
435    return Id->getName();
436  if (Name.isObjCZeroArgSelector())
437    if (IdentifierInfo *Id
438        = Name.getObjCSelector().getIdentifierInfoForSlot(0))
439      return Id->getName();
440
441  Saved = Name.getAsString();
442  return Saved;
443}
444
445bool clang::operator<(const CodeCompletionResult &X,
446                      const CodeCompletionResult &Y) {
447  std::string XSaved, YSaved;
448  llvm::StringRef XStr = getOrderedName(X, XSaved);
449  llvm::StringRef YStr = getOrderedName(Y, YSaved);
450  int cmp = XStr.compare_lower(YStr);
451  if (cmp)
452    return cmp < 0;
453
454  // If case-insensitive comparison fails, try case-sensitive comparison.
455  cmp = XStr.compare(YStr);
456  if (cmp)
457    return cmp < 0;
458
459  return false;
460}
461