blob: e9df17d6a11593d24a858dc782ae1e09cb08273a [file] [log] [blame]
Douglas Gregor2436e712009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- 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 defines the code-completion semantic actions.
11//
12//===----------------------------------------------------------------------===//
13#include "Sema.h"
14#include "clang/Sema/CodeCompleteConsumer.h"
Douglas Gregorf2510672009-09-21 19:57:38 +000015#include "clang/AST/ExprCXX.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000016#include "clang/Lex/MacroInfo.h"
17#include "clang/Lex/Preprocessor.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000018#include "llvm/ADT/SmallPtrSet.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000019#include "llvm/ADT/StringExtras.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000020#include <list>
21#include <map>
22#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000023
24using namespace clang;
25
26/// \brief Set the code-completion consumer for semantic analysis.
27void Sema::setCodeCompleteConsumer(CodeCompleteConsumer *CCC) {
28 assert(((CodeCompleter != 0) != (CCC != 0)) &&
29 "Already set or cleared a code-completion consumer?");
30 CodeCompleter = CCC;
31}
32
Douglas Gregor3545ff42009-09-21 16:56:56 +000033namespace {
34 /// \brief A container of code-completion results.
35 class ResultBuilder {
36 public:
37 /// \brief The type of a name-lookup filter, which can be provided to the
38 /// name-lookup routines to specify which declarations should be included in
39 /// the result set (when it returns true) and which declarations should be
40 /// filtered out (returns false).
41 typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
42
43 typedef CodeCompleteConsumer::Result Result;
44
45 private:
46 /// \brief The actual results we have found.
47 std::vector<Result> Results;
48
49 /// \brief A record of all of the declarations we have found and placed
50 /// into the result set, used to ensure that no declaration ever gets into
51 /// the result set twice.
52 llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
53
54 /// \brief A mapping from declaration names to the declarations that have
55 /// this name within a particular scope and their index within the list of
56 /// results.
57 typedef std::multimap<DeclarationName,
58 std::pair<NamedDecl *, unsigned> > ShadowMap;
59
60 /// \brief The semantic analysis object for which results are being
61 /// produced.
62 Sema &SemaRef;
63
64 /// \brief If non-NULL, a filter function used to remove any code-completion
65 /// results that are not desirable.
66 LookupFilter Filter;
67
68 /// \brief A list of shadow maps, which is used to model name hiding at
69 /// different levels of, e.g., the inheritance hierarchy.
70 std::list<ShadowMap> ShadowMaps;
71
72 public:
73 explicit ResultBuilder(Sema &SemaRef, LookupFilter Filter = 0)
74 : SemaRef(SemaRef), Filter(Filter) { }
75
76 /// \brief Set the filter used for code-completion results.
77 void setFilter(LookupFilter Filter) {
78 this->Filter = Filter;
79 }
80
81 typedef std::vector<Result>::iterator iterator;
82 iterator begin() { return Results.begin(); }
83 iterator end() { return Results.end(); }
84
85 Result *data() { return Results.empty()? 0 : &Results.front(); }
86 unsigned size() const { return Results.size(); }
87 bool empty() const { return Results.empty(); }
88
89 /// \brief Add a new result to this result set (if it isn't already in one
90 /// of the shadow maps), or replace an existing result (for, e.g., a
91 /// redeclaration).
Douglas Gregor2af2f672009-09-21 20:12:40 +000092 ///
93 /// \param R the result to add (if it is unique).
94 ///
95 /// \param R the context in which this result will be named.
96 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor3545ff42009-09-21 16:56:56 +000097
98 /// \brief Enter into a new scope.
99 void EnterNewScope();
100
101 /// \brief Exit from the current scope.
102 void ExitScope();
103
104 /// \name Name lookup predicates
105 ///
106 /// These predicates can be passed to the name lookup functions to filter the
107 /// results of name lookup. All of the predicates have the same type, so that
108 ///
109 //@{
Douglas Gregor9d64c5e2009-09-21 20:51:25 +0000110 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000111 bool IsNestedNameSpecifier(NamedDecl *ND) const;
112 bool IsEnum(NamedDecl *ND) const;
113 bool IsClassOrStruct(NamedDecl *ND) const;
114 bool IsUnion(NamedDecl *ND) const;
115 bool IsNamespace(NamedDecl *ND) const;
116 bool IsNamespaceOrAlias(NamedDecl *ND) const;
117 bool IsType(NamedDecl *ND) const;
Douglas Gregore412a5a2009-09-23 22:26:46 +0000118 bool IsMember(NamedDecl *ND) const;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000119 //@}
120 };
121}
122
123/// \brief Determines whether the given hidden result could be found with
124/// some extra work, e.g., by qualifying the name.
125///
126/// \param Hidden the declaration that is hidden by the currenly \p Visible
127/// declaration.
128///
129/// \param Visible the declaration with the same name that is already visible.
130///
131/// \returns true if the hidden result can be found by some mechanism,
132/// false otherwise.
133static bool canHiddenResultBeFound(const LangOptions &LangOpts,
134 NamedDecl *Hidden, NamedDecl *Visible) {
135 // In C, there is no way to refer to a hidden name.
136 if (!LangOpts.CPlusPlus)
137 return false;
138
139 DeclContext *HiddenCtx = Hidden->getDeclContext()->getLookupContext();
140
141 // There is no way to qualify a name declared in a function or method.
142 if (HiddenCtx->isFunctionOrMethod())
143 return false;
144
Douglas Gregor3545ff42009-09-21 16:56:56 +0000145 return HiddenCtx != Visible->getDeclContext()->getLookupContext();
146}
147
Douglas Gregor2af2f672009-09-21 20:12:40 +0000148/// \brief Compute the qualification required to get from the current context
149/// (\p CurContext) to the target context (\p TargetContext).
150///
151/// \param Context the AST context in which the qualification will be used.
152///
153/// \param CurContext the context where an entity is being named, which is
154/// typically based on the current scope.
155///
156/// \param TargetContext the context in which the named entity actually
157/// resides.
158///
159/// \returns a nested name specifier that refers into the target context, or
160/// NULL if no qualification is needed.
161static NestedNameSpecifier *
162getRequiredQualification(ASTContext &Context,
163 DeclContext *CurContext,
164 DeclContext *TargetContext) {
165 llvm::SmallVector<DeclContext *, 4> TargetParents;
166
167 for (DeclContext *CommonAncestor = TargetContext;
168 CommonAncestor && !CommonAncestor->Encloses(CurContext);
169 CommonAncestor = CommonAncestor->getLookupParent()) {
170 if (CommonAncestor->isTransparentContext() ||
171 CommonAncestor->isFunctionOrMethod())
172 continue;
173
174 TargetParents.push_back(CommonAncestor);
175 }
176
177 NestedNameSpecifier *Result = 0;
178 while (!TargetParents.empty()) {
179 DeclContext *Parent = TargetParents.back();
180 TargetParents.pop_back();
181
182 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent))
183 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
184 else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
185 Result = NestedNameSpecifier::Create(Context, Result,
186 false,
187 Context.getTypeDeclType(TD).getTypePtr());
188 else
189 assert(Parent->isTranslationUnit());
190 }
191
192 return Result;
193}
194
195void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
Douglas Gregor64b12b52009-09-22 23:31:26 +0000196 assert(!ShadowMaps.empty() && "Must enter into a results scope");
197
Douglas Gregor3545ff42009-09-21 16:56:56 +0000198 if (R.Kind != Result::RK_Declaration) {
199 // For non-declaration results, just add the result.
200 Results.push_back(R);
201 return;
202 }
Douglas Gregor58acf322009-10-09 22:16:47 +0000203
204 // Skip unnamed entities.
205 if (!R.Declaration->getDeclName())
206 return;
207
Douglas Gregor3545ff42009-09-21 16:56:56 +0000208 // Look through using declarations.
209 if (UsingDecl *Using = dyn_cast<UsingDecl>(R.Declaration))
Douglas Gregor5bf52692009-09-22 23:15:58 +0000210 MaybeAddResult(Result(Using->getTargetDecl(), R.Rank, R.Qualifier),
211 CurContext);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000212
213 // Handle each declaration in an overload set separately.
214 if (OverloadedFunctionDecl *Ovl
215 = dyn_cast<OverloadedFunctionDecl>(R.Declaration)) {
216 for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
217 FEnd = Ovl->function_end();
218 F != FEnd; ++F)
Douglas Gregor2af2f672009-09-21 20:12:40 +0000219 MaybeAddResult(Result(*F, R.Rank, R.Qualifier), CurContext);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000220
221 return;
222 }
223
224 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
225 unsigned IDNS = CanonDecl->getIdentifierNamespace();
226
227 // Friend declarations and declarations introduced due to friends are never
228 // added as results.
229 if (isa<FriendDecl>(CanonDecl) ||
230 (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend)))
231 return;
232
233 if (const IdentifierInfo *Id = R.Declaration->getIdentifier()) {
234 // __va_list_tag is a freak of nature. Find it and skip it.
235 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
236 return;
237
Douglas Gregor58acf322009-10-09 22:16:47 +0000238 // Filter out names reserved for the implementation (C99 7.1.3,
239 // C++ [lib.global.names]). Users don't need to see those.
Daniel Dunbar2c422dc92009-10-18 20:26:12 +0000240 //
241 // FIXME: Add predicate for this.
Douglas Gregor58acf322009-10-09 22:16:47 +0000242 if (Id->getLength() >= 2) {
Daniel Dunbar2c422dc92009-10-18 20:26:12 +0000243 const char *Name = Id->getNameStart();
Douglas Gregor58acf322009-10-09 22:16:47 +0000244 if (Name[0] == '_' &&
245 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')))
246 return;
247 }
Douglas Gregor3545ff42009-09-21 16:56:56 +0000248 }
249
250 // C++ constructors are never found by name lookup.
251 if (isa<CXXConstructorDecl>(CanonDecl))
252 return;
253
254 // Filter out any unwanted results.
255 if (Filter && !(this->*Filter)(R.Declaration))
256 return;
257
258 ShadowMap &SMap = ShadowMaps.back();
259 ShadowMap::iterator I, IEnd;
260 for (llvm::tie(I, IEnd) = SMap.equal_range(R.Declaration->getDeclName());
261 I != IEnd; ++I) {
262 NamedDecl *ND = I->second.first;
263 unsigned Index = I->second.second;
264 if (ND->getCanonicalDecl() == CanonDecl) {
265 // This is a redeclaration. Always pick the newer declaration.
266 I->second.first = R.Declaration;
267 Results[Index].Declaration = R.Declaration;
268
269 // Pick the best rank of the two.
270 Results[Index].Rank = std::min(Results[Index].Rank, R.Rank);
271
272 // We're done.
273 return;
274 }
275 }
276
277 // This is a new declaration in this scope. However, check whether this
278 // declaration name is hidden by a similarly-named declaration in an outer
279 // scope.
280 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
281 --SMEnd;
282 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
283 for (llvm::tie(I, IEnd) = SM->equal_range(R.Declaration->getDeclName());
284 I != IEnd; ++I) {
285 // A tag declaration does not hide a non-tag declaration.
286 if (I->second.first->getIdentifierNamespace() == Decl::IDNS_Tag &&
287 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
288 Decl::IDNS_ObjCProtocol)))
289 continue;
290
291 // Protocols are in distinct namespaces from everything else.
292 if (((I->second.first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
293 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
294 I->second.first->getIdentifierNamespace() != IDNS)
295 continue;
296
297 // The newly-added result is hidden by an entry in the shadow map.
298 if (canHiddenResultBeFound(SemaRef.getLangOptions(), R.Declaration,
299 I->second.first)) {
300 // Note that this result was hidden.
301 R.Hidden = true;
Douglas Gregor5bf52692009-09-22 23:15:58 +0000302 R.QualifierIsInformative = false;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000303
304 if (!R.Qualifier)
305 R.Qualifier = getRequiredQualification(SemaRef.Context,
306 CurContext,
307 R.Declaration->getDeclContext());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000308 } else {
309 // This result was hidden and cannot be found; don't bother adding
310 // it.
311 return;
312 }
313
314 break;
315 }
316 }
317
318 // Make sure that any given declaration only shows up in the result set once.
319 if (!AllDeclsFound.insert(CanonDecl))
320 return;
321
Douglas Gregore412a5a2009-09-23 22:26:46 +0000322 // If the filter is for nested-name-specifiers, then this result starts a
323 // nested-name-specifier.
324 if ((Filter == &ResultBuilder::IsNestedNameSpecifier) ||
325 (Filter == &ResultBuilder::IsMember &&
326 isa<CXXRecordDecl>(R.Declaration) &&
327 cast<CXXRecordDecl>(R.Declaration)->isInjectedClassName()))
328 R.StartsNestedNameSpecifier = true;
329
Douglas Gregor5bf52692009-09-22 23:15:58 +0000330 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000331 if (R.QualifierIsInformative && !R.Qualifier &&
332 !R.StartsNestedNameSpecifier) {
Douglas Gregor5bf52692009-09-22 23:15:58 +0000333 DeclContext *Ctx = R.Declaration->getDeclContext();
334 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
335 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
336 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
337 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
338 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
339 else
340 R.QualifierIsInformative = false;
341 }
Douglas Gregore412a5a2009-09-23 22:26:46 +0000342
Douglas Gregor3545ff42009-09-21 16:56:56 +0000343 // Insert this result into the set of results and into the current shadow
344 // map.
345 SMap.insert(std::make_pair(R.Declaration->getDeclName(),
346 std::make_pair(R.Declaration, Results.size())));
347 Results.push_back(R);
348}
349
350/// \brief Enter into a new scope.
351void ResultBuilder::EnterNewScope() {
352 ShadowMaps.push_back(ShadowMap());
353}
354
355/// \brief Exit from the current scope.
356void ResultBuilder::ExitScope() {
357 ShadowMaps.pop_back();
358}
359
Douglas Gregor9d64c5e2009-09-21 20:51:25 +0000360/// \brief Determines whether this given declaration will be found by
361/// ordinary name lookup.
362bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
363 unsigned IDNS = Decl::IDNS_Ordinary;
364 if (SemaRef.getLangOptions().CPlusPlus)
365 IDNS |= Decl::IDNS_Tag;
366
367 return ND->getIdentifierNamespace() & IDNS;
368}
369
Douglas Gregor3545ff42009-09-21 16:56:56 +0000370/// \brief Determines whether the given declaration is suitable as the
371/// start of a C++ nested-name-specifier, e.g., a class or namespace.
372bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
373 // Allow us to find class templates, too.
374 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
375 ND = ClassTemplate->getTemplatedDecl();
376
377 return SemaRef.isAcceptableNestedNameSpecifier(ND);
378}
379
380/// \brief Determines whether the given declaration is an enumeration.
381bool ResultBuilder::IsEnum(NamedDecl *ND) const {
382 return isa<EnumDecl>(ND);
383}
384
385/// \brief Determines whether the given declaration is a class or struct.
386bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
387 // Allow us to find class templates, too.
388 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
389 ND = ClassTemplate->getTemplatedDecl();
390
391 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
392 return RD->getTagKind() == TagDecl::TK_class ||
393 RD->getTagKind() == TagDecl::TK_struct;
394
395 return false;
396}
397
398/// \brief Determines whether the given declaration is a union.
399bool ResultBuilder::IsUnion(NamedDecl *ND) const {
400 // Allow us to find class templates, too.
401 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
402 ND = ClassTemplate->getTemplatedDecl();
403
404 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
405 return RD->getTagKind() == TagDecl::TK_union;
406
407 return false;
408}
409
410/// \brief Determines whether the given declaration is a namespace.
411bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
412 return isa<NamespaceDecl>(ND);
413}
414
415/// \brief Determines whether the given declaration is a namespace or
416/// namespace alias.
417bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
418 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
419}
420
421/// \brief Brief determines whether the given declaration is a namespace or
422/// namespace alias.
423bool ResultBuilder::IsType(NamedDecl *ND) const {
424 return isa<TypeDecl>(ND);
425}
426
Douglas Gregore412a5a2009-09-23 22:26:46 +0000427/// \brief Since every declaration found within a class is a member that we
428/// care about, always returns true. This predicate exists mostly to
429/// communicate to the result builder that we are performing a lookup for
430/// member access.
431bool ResultBuilder::IsMember(NamedDecl *ND) const {
432 return true;
433}
434
Douglas Gregor3545ff42009-09-21 16:56:56 +0000435// Find the next outer declaration context corresponding to this scope.
436static DeclContext *findOuterContext(Scope *S) {
437 for (S = S->getParent(); S; S = S->getParent())
438 if (S->getEntity())
439 return static_cast<DeclContext *>(S->getEntity())->getPrimaryContext();
440
441 return 0;
442}
443
444/// \brief Collect the results of searching for members within the given
445/// declaration context.
446///
447/// \param Ctx the declaration context from which we will gather results.
448///
Douglas Gregor5bf52692009-09-22 23:15:58 +0000449/// \param Rank the rank given to results in this declaration context.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000450///
451/// \param Visited the set of declaration contexts that have already been
452/// visited. Declaration contexts will only be visited once.
453///
454/// \param Results the result set that will be extended with any results
455/// found within this declaration context (and, for a C++ class, its bases).
456///
Douglas Gregor5bf52692009-09-22 23:15:58 +0000457/// \param InBaseClass whether we are in a base class.
458///
Douglas Gregor3545ff42009-09-21 16:56:56 +0000459/// \returns the next higher rank value, after considering all of the
460/// names within this declaration context.
461static unsigned CollectMemberLookupResults(DeclContext *Ctx,
Douglas Gregor5bf52692009-09-22 23:15:58 +0000462 unsigned Rank,
Douglas Gregor2af2f672009-09-21 20:12:40 +0000463 DeclContext *CurContext,
464 llvm::SmallPtrSet<DeclContext *, 16> &Visited,
Douglas Gregor5bf52692009-09-22 23:15:58 +0000465 ResultBuilder &Results,
466 bool InBaseClass = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000467 // Make sure we don't visit the same context twice.
468 if (!Visited.insert(Ctx->getPrimaryContext()))
Douglas Gregor5bf52692009-09-22 23:15:58 +0000469 return Rank;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000470
471 // Enumerate all of the results in this context.
Douglas Gregor5bf52692009-09-22 23:15:58 +0000472 typedef CodeCompleteConsumer::Result Result;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000473 Results.EnterNewScope();
474 for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx;
475 CurCtx = CurCtx->getNextContext()) {
476 for (DeclContext::decl_iterator D = CurCtx->decls_begin(),
477 DEnd = CurCtx->decls_end();
478 D != DEnd; ++D) {
479 if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
Douglas Gregor5bf52692009-09-22 23:15:58 +0000480 Results.MaybeAddResult(Result(ND, Rank, 0, InBaseClass), CurContext);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000481 }
482 }
483
484 // Traverse the contexts of inherited classes.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000485 if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
486 for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
487 BEnd = Record->bases_end();
488 B != BEnd; ++B) {
489 QualType BaseType = B->getType();
490
491 // Don't look into dependent bases, because name lookup can't look
492 // there anyway.
493 if (BaseType->isDependentType())
494 continue;
495
496 const RecordType *Record = BaseType->getAs<RecordType>();
497 if (!Record)
498 continue;
499
500 // FIXME: It would be nice to be able to determine whether referencing
501 // a particular member would be ambiguous. For example, given
502 //
503 // struct A { int member; };
504 // struct B { int member; };
505 // struct C : A, B { };
506 //
507 // void f(C *c) { c->### }
508 // accessing 'member' would result in an ambiguity. However, code
509 // completion could be smart enough to qualify the member with the
510 // base class, e.g.,
511 //
512 // c->B::member
513 //
514 // or
515 //
516 // c->A::member
517
518 // Collect results from this base class (and its bases).
Douglas Gregor5bf52692009-09-22 23:15:58 +0000519 CollectMemberLookupResults(Record->getDecl(), Rank, CurContext, Visited,
520 Results, /*InBaseClass=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000521 }
522 }
523
524 // FIXME: Look into base classes in Objective-C!
525
526 Results.ExitScope();
Douglas Gregor5bf52692009-09-22 23:15:58 +0000527 return Rank + 1;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000528}
529
530/// \brief Collect the results of searching for members within the given
531/// declaration context.
532///
533/// \param Ctx the declaration context from which we will gather results.
534///
535/// \param InitialRank the initial rank given to results in this declaration
536/// context. Larger rank values will be used for, e.g., members found in
537/// base classes.
538///
539/// \param Results the result set that will be extended with any results
540/// found within this declaration context (and, for a C++ class, its bases).
541///
542/// \returns the next higher rank value, after considering all of the
543/// names within this declaration context.
544static unsigned CollectMemberLookupResults(DeclContext *Ctx,
545 unsigned InitialRank,
Douglas Gregor2af2f672009-09-21 20:12:40 +0000546 DeclContext *CurContext,
Douglas Gregor3545ff42009-09-21 16:56:56 +0000547 ResultBuilder &Results) {
548 llvm::SmallPtrSet<DeclContext *, 16> Visited;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000549 return CollectMemberLookupResults(Ctx, InitialRank, CurContext, Visited,
550 Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000551}
552
553/// \brief Collect the results of searching for declarations within the given
554/// scope and its parent scopes.
555///
556/// \param S the scope in which we will start looking for declarations.
557///
558/// \param InitialRank the initial rank given to results in this scope.
559/// Larger rank values will be used for results found in parent scopes.
560///
Douglas Gregor2af2f672009-09-21 20:12:40 +0000561/// \param CurContext the context from which lookup results will be found.
562///
Douglas Gregor3545ff42009-09-21 16:56:56 +0000563/// \param Results the builder object that will receive each result.
564static unsigned CollectLookupResults(Scope *S,
565 TranslationUnitDecl *TranslationUnit,
566 unsigned InitialRank,
Douglas Gregor2af2f672009-09-21 20:12:40 +0000567 DeclContext *CurContext,
Douglas Gregor3545ff42009-09-21 16:56:56 +0000568 ResultBuilder &Results) {
569 if (!S)
570 return InitialRank;
571
572 // FIXME: Using directives!
573
574 unsigned NextRank = InitialRank;
575 Results.EnterNewScope();
576 if (S->getEntity() &&
577 !((DeclContext *)S->getEntity())->isFunctionOrMethod()) {
578 // Look into this scope's declaration context, along with any of its
579 // parent lookup contexts (e.g., enclosing classes), up to the point
580 // where we hit the context stored in the next outer scope.
581 DeclContext *Ctx = (DeclContext *)S->getEntity();
582 DeclContext *OuterCtx = findOuterContext(S);
583
584 for (; Ctx && Ctx->getPrimaryContext() != OuterCtx;
585 Ctx = Ctx->getLookupParent()) {
586 if (Ctx->isFunctionOrMethod())
587 continue;
588
Douglas Gregor2af2f672009-09-21 20:12:40 +0000589 NextRank = CollectMemberLookupResults(Ctx, NextRank + 1, CurContext,
590 Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000591 }
592 } else if (!S->getParent()) {
593 // Look into the translation unit scope. We walk through the translation
594 // unit's declaration context, because the Scope itself won't have all of
595 // the declarations if we loaded a precompiled header.
596 // FIXME: We would like the translation unit's Scope object to point to the
597 // translation unit, so we don't need this special "if" branch. However,
598 // doing so would force the normal C++ name-lookup code to look into the
599 // translation unit decl when the IdentifierInfo chains would suffice.
600 // Once we fix that problem (which is part of a more general "don't look
601 // in DeclContexts unless we have to" optimization), we can eliminate the
602 // TranslationUnit parameter entirely.
603 NextRank = CollectMemberLookupResults(TranslationUnit, NextRank + 1,
Douglas Gregor2af2f672009-09-21 20:12:40 +0000604 CurContext, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000605 } else {
606 // Walk through the declarations in this Scope.
607 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
608 D != DEnd; ++D) {
609 if (NamedDecl *ND = dyn_cast<NamedDecl>((Decl *)((*D).get())))
Douglas Gregor2af2f672009-09-21 20:12:40 +0000610 Results.MaybeAddResult(CodeCompleteConsumer::Result(ND, NextRank),
611 CurContext);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000612 }
613
614 NextRank = NextRank + 1;
615 }
616
617 // Lookup names in the parent scope.
618 NextRank = CollectLookupResults(S->getParent(), TranslationUnit, NextRank,
Douglas Gregor2af2f672009-09-21 20:12:40 +0000619 CurContext, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000620 Results.ExitScope();
621
622 return NextRank;
623}
624
625/// \brief Add type specifiers for the current language as keyword results.
626static void AddTypeSpecifierResults(const LangOptions &LangOpts, unsigned Rank,
627 ResultBuilder &Results) {
628 typedef CodeCompleteConsumer::Result Result;
629 Results.MaybeAddResult(Result("short", Rank));
630 Results.MaybeAddResult(Result("long", Rank));
631 Results.MaybeAddResult(Result("signed", Rank));
632 Results.MaybeAddResult(Result("unsigned", Rank));
633 Results.MaybeAddResult(Result("void", Rank));
634 Results.MaybeAddResult(Result("char", Rank));
635 Results.MaybeAddResult(Result("int", Rank));
636 Results.MaybeAddResult(Result("float", Rank));
637 Results.MaybeAddResult(Result("double", Rank));
638 Results.MaybeAddResult(Result("enum", Rank));
639 Results.MaybeAddResult(Result("struct", Rank));
640 Results.MaybeAddResult(Result("union", Rank));
641
642 if (LangOpts.C99) {
643 // C99-specific
644 Results.MaybeAddResult(Result("_Complex", Rank));
645 Results.MaybeAddResult(Result("_Imaginary", Rank));
646 Results.MaybeAddResult(Result("_Bool", Rank));
647 }
648
649 if (LangOpts.CPlusPlus) {
650 // C++-specific
651 Results.MaybeAddResult(Result("bool", Rank));
652 Results.MaybeAddResult(Result("class", Rank));
653 Results.MaybeAddResult(Result("typename", Rank));
654 Results.MaybeAddResult(Result("wchar_t", Rank));
655
656 if (LangOpts.CPlusPlus0x) {
657 Results.MaybeAddResult(Result("char16_t", Rank));
658 Results.MaybeAddResult(Result("char32_t", Rank));
659 Results.MaybeAddResult(Result("decltype", Rank));
660 }
661 }
662
663 // GNU extensions
664 if (LangOpts.GNUMode) {
665 // FIXME: Enable when we actually support decimal floating point.
666 // Results.MaybeAddResult(Result("_Decimal32", Rank));
667 // Results.MaybeAddResult(Result("_Decimal64", Rank));
668 // Results.MaybeAddResult(Result("_Decimal128", Rank));
669 Results.MaybeAddResult(Result("typeof", Rank));
670 }
671}
672
673/// \brief Add function parameter chunks to the given code completion string.
674static void AddFunctionParameterChunks(ASTContext &Context,
675 FunctionDecl *Function,
676 CodeCompletionString *Result) {
677 CodeCompletionString *CCStr = Result;
678
679 for (unsigned P = 0, N = Function->getNumParams(); P != N; ++P) {
680 ParmVarDecl *Param = Function->getParamDecl(P);
681
682 if (Param->hasDefaultArg()) {
683 // When we see an optional default argument, put that argument and
684 // the remaining default arguments into a new, optional string.
685 CodeCompletionString *Opt = new CodeCompletionString;
686 CCStr->AddOptionalChunk(std::auto_ptr<CodeCompletionString>(Opt));
687 CCStr = Opt;
688 }
689
690 if (P != 0)
691 CCStr->AddTextChunk(", ");
692
693 // Format the placeholder string.
694 std::string PlaceholderStr;
695 if (Param->getIdentifier())
696 PlaceholderStr = Param->getIdentifier()->getName();
697
698 Param->getType().getAsStringInternal(PlaceholderStr,
699 Context.PrintingPolicy);
700
701 // Add the placeholder string.
702 CCStr->AddPlaceholderChunk(PlaceholderStr.c_str());
703 }
Douglas Gregorba449032009-09-22 21:42:17 +0000704
705 if (const FunctionProtoType *Proto
706 = Function->getType()->getAs<FunctionProtoType>())
707 if (Proto->isVariadic())
708 CCStr->AddPlaceholderChunk(", ...");
Douglas Gregor3545ff42009-09-21 16:56:56 +0000709}
710
711/// \brief Add template parameter chunks to the given code completion string.
712static void AddTemplateParameterChunks(ASTContext &Context,
713 TemplateDecl *Template,
714 CodeCompletionString *Result,
715 unsigned MaxParameters = 0) {
716 CodeCompletionString *CCStr = Result;
717 bool FirstParameter = true;
718
719 TemplateParameterList *Params = Template->getTemplateParameters();
720 TemplateParameterList::iterator PEnd = Params->end();
721 if (MaxParameters)
722 PEnd = Params->begin() + MaxParameters;
723 for (TemplateParameterList::iterator P = Params->begin(); P != PEnd; ++P) {
724 bool HasDefaultArg = false;
725 std::string PlaceholderStr;
726 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
727 if (TTP->wasDeclaredWithTypename())
728 PlaceholderStr = "typename";
729 else
730 PlaceholderStr = "class";
731
732 if (TTP->getIdentifier()) {
733 PlaceholderStr += ' ';
734 PlaceholderStr += TTP->getIdentifier()->getName();
735 }
736
737 HasDefaultArg = TTP->hasDefaultArgument();
738 } else if (NonTypeTemplateParmDecl *NTTP
739 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
740 if (NTTP->getIdentifier())
741 PlaceholderStr = NTTP->getIdentifier()->getName();
742 NTTP->getType().getAsStringInternal(PlaceholderStr,
743 Context.PrintingPolicy);
744 HasDefaultArg = NTTP->hasDefaultArgument();
745 } else {
746 assert(isa<TemplateTemplateParmDecl>(*P));
747 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
748
749 // Since putting the template argument list into the placeholder would
750 // be very, very long, we just use an abbreviation.
751 PlaceholderStr = "template<...> class";
752 if (TTP->getIdentifier()) {
753 PlaceholderStr += ' ';
754 PlaceholderStr += TTP->getIdentifier()->getName();
755 }
756
757 HasDefaultArg = TTP->hasDefaultArgument();
758 }
759
760 if (HasDefaultArg) {
761 // When we see an optional default argument, put that argument and
762 // the remaining default arguments into a new, optional string.
763 CodeCompletionString *Opt = new CodeCompletionString;
764 CCStr->AddOptionalChunk(std::auto_ptr<CodeCompletionString>(Opt));
765 CCStr = Opt;
766 }
767
768 if (FirstParameter)
769 FirstParameter = false;
770 else
771 CCStr->AddTextChunk(", ");
772
773 // Add the placeholder string.
774 CCStr->AddPlaceholderChunk(PlaceholderStr.c_str());
775 }
776}
777
Douglas Gregorf2510672009-09-21 19:57:38 +0000778/// \brief Add a qualifier to the given code-completion string, if the
779/// provided nested-name-specifier is non-NULL.
780void AddQualifierToCompletionString(CodeCompletionString *Result,
781 NestedNameSpecifier *Qualifier,
Douglas Gregor5bf52692009-09-22 23:15:58 +0000782 bool QualifierIsInformative,
Douglas Gregorf2510672009-09-21 19:57:38 +0000783 ASTContext &Context) {
784 if (!Qualifier)
785 return;
786
787 std::string PrintedNNS;
788 {
789 llvm::raw_string_ostream OS(PrintedNNS);
790 Qualifier->print(OS, Context.PrintingPolicy);
791 }
Douglas Gregor5bf52692009-09-22 23:15:58 +0000792 if (QualifierIsInformative)
793 Result->AddInformativeChunk(PrintedNNS.c_str());
794 else
795 Result->AddTextChunk(PrintedNNS.c_str());
Douglas Gregorf2510672009-09-21 19:57:38 +0000796}
797
Douglas Gregor3545ff42009-09-21 16:56:56 +0000798/// \brief If possible, create a new code completion string for the given
799/// result.
800///
801/// \returns Either a new, heap-allocated code completion string describing
802/// how to use this result, or NULL to indicate that the string or name of the
803/// result is all that is needed.
804CodeCompletionString *
805CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
Douglas Gregorf329c7c2009-10-30 16:50:04 +0000806 if (Kind == RK_Keyword)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000807 return 0;
808
Douglas Gregorf329c7c2009-10-30 16:50:04 +0000809 if (Kind == RK_Macro) {
810 MacroInfo *MI = S.PP.getMacroInfo(Macro);
811 if (!MI || !MI->isFunctionLike())
812 return 0;
813
814 // Format a function-like macro with placeholders for the arguments.
815 CodeCompletionString *Result = new CodeCompletionString;
816 Result->AddTextChunk(Macro->getName().str().c_str());
817 Result->AddTextChunk("(");
818 for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
819 A != AEnd; ++A) {
820 if (A != MI->arg_begin())
821 Result->AddTextChunk(", ");
822
823 if (!MI->isVariadic() || A != AEnd - 1) {
824 // Non-variadic argument.
825 Result->AddPlaceholderChunk((*A)->getName().str().c_str());
826 continue;
827 }
828
829 // Variadic argument; cope with the different between GNU and C99
830 // variadic macros, providing a single placeholder for the rest of the
831 // arguments.
832 if ((*A)->isStr("__VA_ARGS__"))
833 Result->AddPlaceholderChunk("...");
834 else {
835 std::string Arg = (*A)->getName();
836 Arg += "...";
837 Result->AddPlaceholderChunk(Arg.c_str());
838 }
839 }
840 Result->AddTextChunk(")");
841 return Result;
842 }
843
844 assert(Kind == RK_Declaration && "Missed a macro kind?");
Douglas Gregor3545ff42009-09-21 16:56:56 +0000845 NamedDecl *ND = Declaration;
846
847 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
848 CodeCompletionString *Result = new CodeCompletionString;
Douglas Gregor5bf52692009-09-22 23:15:58 +0000849 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
850 S.Context);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000851 Result->AddTextChunk(Function->getNameAsString().c_str());
852 Result->AddTextChunk("(");
853 AddFunctionParameterChunks(S.Context, Function, Result);
854 Result->AddTextChunk(")");
855 return Result;
856 }
857
858 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
859 CodeCompletionString *Result = new CodeCompletionString;
Douglas Gregor5bf52692009-09-22 23:15:58 +0000860 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
861 S.Context);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000862 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
863 Result->AddTextChunk(Function->getNameAsString().c_str());
864
865 // Figure out which template parameters are deduced (or have default
866 // arguments).
867 llvm::SmallVector<bool, 16> Deduced;
868 S.MarkDeducedTemplateParameters(FunTmpl, Deduced);
869 unsigned LastDeducibleArgument;
870 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
871 --LastDeducibleArgument) {
872 if (!Deduced[LastDeducibleArgument - 1]) {
873 // C++0x: Figure out if the template argument has a default. If so,
874 // the user doesn't need to type this argument.
875 // FIXME: We need to abstract template parameters better!
876 bool HasDefaultArg = false;
877 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
878 LastDeducibleArgument - 1);
879 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
880 HasDefaultArg = TTP->hasDefaultArgument();
881 else if (NonTypeTemplateParmDecl *NTTP
882 = dyn_cast<NonTypeTemplateParmDecl>(Param))
883 HasDefaultArg = NTTP->hasDefaultArgument();
884 else {
885 assert(isa<TemplateTemplateParmDecl>(Param));
886 HasDefaultArg
887 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
888 }
889
890 if (!HasDefaultArg)
891 break;
892 }
893 }
894
895 if (LastDeducibleArgument) {
896 // Some of the function template arguments cannot be deduced from a
897 // function call, so we introduce an explicit template argument list
898 // containing all of the arguments up to the first deducible argument.
899 Result->AddTextChunk("<");
900 AddTemplateParameterChunks(S.Context, FunTmpl, Result,
901 LastDeducibleArgument);
902 Result->AddTextChunk(">");
903 }
904
905 // Add the function parameters
906 Result->AddTextChunk("(");
907 AddFunctionParameterChunks(S.Context, Function, Result);
908 Result->AddTextChunk(")");
909 return Result;
910 }
911
912 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
913 CodeCompletionString *Result = new CodeCompletionString;
Douglas Gregor5bf52692009-09-22 23:15:58 +0000914 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
915 S.Context);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000916 Result->AddTextChunk(Template->getNameAsString().c_str());
917 Result->AddTextChunk("<");
918 AddTemplateParameterChunks(S.Context, Template, Result);
919 Result->AddTextChunk(">");
920 return Result;
921 }
922
Douglas Gregor2b3ee152009-09-22 23:22:24 +0000923 if (Qualifier || StartsNestedNameSpecifier) {
Douglas Gregorf2510672009-09-21 19:57:38 +0000924 CodeCompletionString *Result = new CodeCompletionString;
Douglas Gregor5bf52692009-09-22 23:15:58 +0000925 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
926 S.Context);
Douglas Gregorf2510672009-09-21 19:57:38 +0000927 Result->AddTextChunk(ND->getNameAsString().c_str());
Douglas Gregor2b3ee152009-09-22 23:22:24 +0000928 if (StartsNestedNameSpecifier)
929 Result->AddTextChunk("::");
Douglas Gregorf2510672009-09-21 19:57:38 +0000930 return Result;
931 }
932
Douglas Gregor3545ff42009-09-21 16:56:56 +0000933 return 0;
934}
935
Douglas Gregorf0f51982009-09-23 00:34:09 +0000936CodeCompletionString *
937CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
938 unsigned CurrentArg,
939 Sema &S) const {
940 CodeCompletionString *Result = new CodeCompletionString;
941 FunctionDecl *FDecl = getFunction();
942 const FunctionProtoType *Proto
943 = dyn_cast<FunctionProtoType>(getFunctionType());
944 if (!FDecl && !Proto) {
945 // Function without a prototype. Just give the return type and a
946 // highlighted ellipsis.
947 const FunctionType *FT = getFunctionType();
948 Result->AddTextChunk(
949 FT->getResultType().getAsString(S.Context.PrintingPolicy).c_str());
950 Result->AddTextChunk("(");
951 Result->AddPlaceholderChunk("...");
952 Result->AddTextChunk("(");
953 return Result;
954 }
955
956 if (FDecl)
957 Result->AddTextChunk(FDecl->getNameAsString().c_str());
958 else
959 Result->AddTextChunk(
960 Proto->getResultType().getAsString(S.Context.PrintingPolicy).c_str());
961
962 Result->AddTextChunk("(");
963 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
964 for (unsigned I = 0; I != NumParams; ++I) {
965 if (I)
966 Result->AddTextChunk(", ");
967
968 std::string ArgString;
969 QualType ArgType;
970
971 if (FDecl) {
972 ArgString = FDecl->getParamDecl(I)->getNameAsString();
973 ArgType = FDecl->getParamDecl(I)->getOriginalType();
974 } else {
975 ArgType = Proto->getArgType(I);
976 }
977
978 ArgType.getAsStringInternal(ArgString, S.Context.PrintingPolicy);
979
980 if (I == CurrentArg)
981 Result->AddPlaceholderChunk(ArgString.c_str());
982 else
983 Result->AddTextChunk(ArgString.c_str());
984 }
985
986 if (Proto && Proto->isVariadic()) {
987 Result->AddTextChunk(", ");
988 if (CurrentArg < NumParams)
989 Result->AddTextChunk("...");
990 else
991 Result->AddPlaceholderChunk("...");
992 }
993 Result->AddTextChunk(")");
994
995 return Result;
996}
997
Douglas Gregor3545ff42009-09-21 16:56:56 +0000998namespace {
999 struct SortCodeCompleteResult {
1000 typedef CodeCompleteConsumer::Result Result;
1001
Douglas Gregore6688e62009-09-28 03:51:44 +00001002 bool isEarlierDeclarationName(DeclarationName X, DeclarationName Y) const {
1003 if (X.getNameKind() != Y.getNameKind())
1004 return X.getNameKind() < Y.getNameKind();
1005
1006 return llvm::LowercaseString(X.getAsString())
1007 < llvm::LowercaseString(Y.getAsString());
1008 }
1009
Douglas Gregor3545ff42009-09-21 16:56:56 +00001010 bool operator()(const Result &X, const Result &Y) const {
1011 // Sort first by rank.
1012 if (X.Rank < Y.Rank)
1013 return true;
1014 else if (X.Rank > Y.Rank)
1015 return false;
1016
1017 // Result kinds are ordered by decreasing importance.
1018 if (X.Kind < Y.Kind)
1019 return true;
1020 else if (X.Kind > Y.Kind)
1021 return false;
1022
1023 // Non-hidden names precede hidden names.
1024 if (X.Hidden != Y.Hidden)
1025 return !X.Hidden;
1026
Douglas Gregore412a5a2009-09-23 22:26:46 +00001027 // Non-nested-name-specifiers precede nested-name-specifiers.
1028 if (X.StartsNestedNameSpecifier != Y.StartsNestedNameSpecifier)
1029 return !X.StartsNestedNameSpecifier;
1030
Douglas Gregor3545ff42009-09-21 16:56:56 +00001031 // Ordering depends on the kind of result.
1032 switch (X.Kind) {
1033 case Result::RK_Declaration:
1034 // Order based on the declaration names.
Douglas Gregore6688e62009-09-28 03:51:44 +00001035 return isEarlierDeclarationName(X.Declaration->getDeclName(),
1036 Y.Declaration->getDeclName());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001037
1038 case Result::RK_Keyword:
Steve Naroff3b086302009-10-08 23:45:10 +00001039 return strcmp(X.Keyword, Y.Keyword) < 0;
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001040
1041 case Result::RK_Macro:
1042 return llvm::LowercaseString(X.Macro->getName()) <
1043 llvm::LowercaseString(Y.Macro->getName());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001044 }
1045
1046 // Silence GCC warning.
1047 return false;
1048 }
1049 };
1050}
1051
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001052// Add all of the known macros as code-completion results.
1053static void AddMacroResults(Preprocessor &PP, unsigned Rank,
1054 ResultBuilder &Results) {
1055 Results.EnterNewScope();
1056 for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end();
1057 M != MEnd; ++M)
1058 Results.MaybeAddResult(CodeCompleteConsumer::Result(M->first, Rank));
1059 Results.ExitScope();
1060}
1061
Douglas Gregor3545ff42009-09-21 16:56:56 +00001062static void HandleCodeCompleteResults(CodeCompleteConsumer *CodeCompleter,
1063 CodeCompleteConsumer::Result *Results,
1064 unsigned NumResults) {
1065 // Sort the results by rank/kind/etc.
1066 std::stable_sort(Results, Results + NumResults, SortCodeCompleteResult());
1067
1068 if (CodeCompleter)
1069 CodeCompleter->ProcessCodeCompleteResults(Results, NumResults);
1070}
1071
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001072void Sema::CodeCompleteOrdinaryName(Scope *S) {
1073 ResultBuilder Results(*this, &ResultBuilder::IsOrdinaryName);
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001074 unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
1075 0, CurContext, Results);
1076 AddMacroResults(PP, NextRank, Results);
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001077 HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
1078}
1079
Douglas Gregor2436e712009-09-17 21:32:03 +00001080void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
1081 SourceLocation OpLoc,
1082 bool IsArrow) {
1083 if (!BaseE || !CodeCompleter)
1084 return;
1085
Douglas Gregor3545ff42009-09-21 16:56:56 +00001086 typedef CodeCompleteConsumer::Result Result;
1087
Douglas Gregor2436e712009-09-17 21:32:03 +00001088 Expr *Base = static_cast<Expr *>(BaseE);
1089 QualType BaseType = Base->getType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00001090
1091 if (IsArrow) {
1092 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
1093 BaseType = Ptr->getPointeeType();
1094 else if (BaseType->isObjCObjectPointerType())
1095 /*Do nothing*/ ;
1096 else
1097 return;
1098 }
1099
Douglas Gregore412a5a2009-09-23 22:26:46 +00001100 ResultBuilder Results(*this, &ResultBuilder::IsMember);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001101 unsigned NextRank = 0;
1102
1103 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor2af2f672009-09-21 20:12:40 +00001104 NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank,
1105 Record->getDecl(), Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001106
1107 if (getLangOptions().CPlusPlus) {
1108 if (!Results.empty()) {
1109 // The "template" keyword can follow "->" or "." in the grammar.
1110 // However, we only want to suggest the template keyword if something
1111 // is dependent.
1112 bool IsDependent = BaseType->isDependentType();
1113 if (!IsDependent) {
1114 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
1115 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
1116 IsDependent = Ctx->isDependentContext();
1117 break;
1118 }
1119 }
1120
1121 if (IsDependent)
1122 Results.MaybeAddResult(Result("template", NextRank++));
1123 }
1124
1125 // We could have the start of a nested-name-specifier. Add those
1126 // results as well.
1127 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
1128 CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank,
Douglas Gregor2af2f672009-09-21 20:12:40 +00001129 CurContext, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001130 }
1131
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001132 // Add macros
1133 AddMacroResults(PP, NextRank, Results);
1134
Douglas Gregor3545ff42009-09-21 16:56:56 +00001135 // Hand off the results found for code completion.
1136 HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
1137
1138 // We're done!
1139 return;
1140 }
Douglas Gregor2436e712009-09-17 21:32:03 +00001141}
1142
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00001143void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
1144 if (!CodeCompleter)
1145 return;
1146
Douglas Gregor3545ff42009-09-21 16:56:56 +00001147 typedef CodeCompleteConsumer::Result Result;
1148 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00001149 switch ((DeclSpec::TST)TagSpec) {
1150 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00001151 Filter = &ResultBuilder::IsEnum;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00001152 break;
1153
1154 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00001155 Filter = &ResultBuilder::IsUnion;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00001156 break;
1157
1158 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00001159 case DeclSpec::TST_class:
Douglas Gregor3545ff42009-09-21 16:56:56 +00001160 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00001161 break;
1162
1163 default:
1164 assert(false && "Unknown type specifier kind in CodeCompleteTag");
1165 return;
1166 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001167
1168 ResultBuilder Results(*this, Filter);
1169 unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
Douglas Gregor2af2f672009-09-21 20:12:40 +00001170 0, CurContext, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001171
1172 if (getLangOptions().CPlusPlus) {
1173 // We could have the start of a nested-name-specifier. Add those
1174 // results as well.
1175 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001176 NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
1177 NextRank, CurContext, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001178 }
1179
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001180 AddMacroResults(PP, NextRank, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001181 HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00001182}
1183
Douglas Gregord328d572009-09-21 18:10:23 +00001184void Sema::CodeCompleteCase(Scope *S) {
1185 if (getSwitchStack().empty() || !CodeCompleter)
1186 return;
1187
1188 SwitchStmt *Switch = getSwitchStack().back();
1189 if (!Switch->getCond()->getType()->isEnumeralType())
1190 return;
1191
1192 // Code-complete the cases of a switch statement over an enumeration type
1193 // by providing the list of
1194 EnumDecl *Enum = Switch->getCond()->getType()->getAs<EnumType>()->getDecl();
1195
1196 // Determine which enumerators we have already seen in the switch statement.
1197 // FIXME: Ideally, we would also be able to look *past* the code-completion
1198 // token, in case we are code-completing in the middle of the switch and not
1199 // at the end. However, we aren't able to do so at the moment.
1200 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorf2510672009-09-21 19:57:38 +00001201 NestedNameSpecifier *Qualifier = 0;
Douglas Gregord328d572009-09-21 18:10:23 +00001202 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
1203 SC = SC->getNextSwitchCase()) {
1204 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
1205 if (!Case)
1206 continue;
1207
1208 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
1209 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
1210 if (EnumConstantDecl *Enumerator
1211 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
1212 // We look into the AST of the case statement to determine which
1213 // enumerator was named. Alternatively, we could compute the value of
1214 // the integral constant expression, then compare it against the
1215 // values of each enumerator. However, value-based approach would not
1216 // work as well with C++ templates where enumerators declared within a
1217 // template are type- and value-dependent.
1218 EnumeratorsSeen.insert(Enumerator);
1219
Douglas Gregorf2510672009-09-21 19:57:38 +00001220 // If this is a qualified-id, keep track of the nested-name-specifier
1221 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00001222 //
1223 // switch (TagD.getKind()) {
1224 // case TagDecl::TK_enum:
1225 // break;
1226 // case XXX
1227 //
Douglas Gregorf2510672009-09-21 19:57:38 +00001228 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00001229 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
1230 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00001231 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00001232 }
1233 }
1234
Douglas Gregorf2510672009-09-21 19:57:38 +00001235 if (getLangOptions().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
1236 // If there are no prior enumerators in C++, check whether we have to
1237 // qualify the names of the enumerators that we suggest, because they
1238 // may not be visible in this scope.
1239 Qualifier = getRequiredQualification(Context, CurContext,
1240 Enum->getDeclContext());
1241
1242 // FIXME: Scoped enums need to start with "EnumDecl" as the context!
1243 }
1244
Douglas Gregord328d572009-09-21 18:10:23 +00001245 // Add any enumerators that have not yet been mentioned.
1246 ResultBuilder Results(*this);
1247 Results.EnterNewScope();
1248 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
1249 EEnd = Enum->enumerator_end();
1250 E != EEnd; ++E) {
1251 if (EnumeratorsSeen.count(*E))
1252 continue;
1253
Douglas Gregorf2510672009-09-21 19:57:38 +00001254 Results.MaybeAddResult(CodeCompleteConsumer::Result(*E, 0, Qualifier));
Douglas Gregord328d572009-09-21 18:10:23 +00001255 }
1256 Results.ExitScope();
1257
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001258 AddMacroResults(PP, 1, Results);
Douglas Gregord328d572009-09-21 18:10:23 +00001259 HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
1260}
1261
Douglas Gregorcabea402009-09-22 15:41:20 +00001262namespace {
1263 struct IsBetterOverloadCandidate {
1264 Sema &S;
1265
1266 public:
1267 explicit IsBetterOverloadCandidate(Sema &S) : S(S) { }
1268
1269 bool
1270 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
1271 return S.isBetterOverloadCandidate(X, Y);
1272 }
1273 };
1274}
1275
1276void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
1277 ExprTy **ArgsIn, unsigned NumArgs) {
1278 if (!CodeCompleter)
1279 return;
1280
1281 Expr *Fn = (Expr *)FnIn;
1282 Expr **Args = (Expr **)ArgsIn;
1283
1284 // Ignore type-dependent call expressions entirely.
1285 if (Fn->isTypeDependent() ||
1286 Expr::hasAnyTypeDependentArguments(Args, NumArgs))
1287 return;
1288
1289 NamedDecl *Function;
1290 DeclarationName UnqualifiedName;
1291 NestedNameSpecifier *Qualifier;
1292 SourceRange QualifierRange;
1293 bool ArgumentDependentLookup;
1294 bool HasExplicitTemplateArgs;
John McCall0ad16662009-10-29 08:12:44 +00001295 const TemplateArgumentLoc *ExplicitTemplateArgs;
Douglas Gregorcabea402009-09-22 15:41:20 +00001296 unsigned NumExplicitTemplateArgs;
1297
1298 DeconstructCallFunction(Fn,
1299 Function, UnqualifiedName, Qualifier, QualifierRange,
1300 ArgumentDependentLookup, HasExplicitTemplateArgs,
1301 ExplicitTemplateArgs, NumExplicitTemplateArgs);
1302
1303
1304 // FIXME: What if we're calling something that isn't a function declaration?
1305 // FIXME: What if we're calling a pseudo-destructor?
1306 // FIXME: What if we're calling a member function?
1307
1308 // Build an overload candidate set based on the functions we find.
1309 OverloadCandidateSet CandidateSet;
1310 AddOverloadedCallCandidates(Function, UnqualifiedName,
1311 ArgumentDependentLookup, HasExplicitTemplateArgs,
1312 ExplicitTemplateArgs, NumExplicitTemplateArgs,
1313 Args, NumArgs,
1314 CandidateSet,
1315 /*PartialOverloading=*/true);
1316
1317 // Sort the overload candidate set by placing the best overloads first.
1318 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
1319 IsBetterOverloadCandidate(*this));
1320
1321 // Add the remaining viable overload candidates as code-completion reslults.
Douglas Gregor05f477c2009-09-23 00:16:58 +00001322 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
1323 llvm::SmallVector<ResultCandidate, 8> Results;
Anders Carlssone7ceb852009-09-22 17:29:51 +00001324
Douglas Gregorcabea402009-09-22 15:41:20 +00001325 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
1326 CandEnd = CandidateSet.end();
1327 Cand != CandEnd; ++Cand) {
1328 if (Cand->Viable)
Douglas Gregor05f477c2009-09-23 00:16:58 +00001329 Results.push_back(ResultCandidate(Cand->Function));
Douglas Gregorcabea402009-09-22 15:41:20 +00001330 }
Douglas Gregor05f477c2009-09-23 00:16:58 +00001331 CodeCompleter->ProcessOverloadCandidates(NumArgs, Results.data(),
1332 Results.size());
Douglas Gregorcabea402009-09-22 15:41:20 +00001333}
1334
Douglas Gregor2436e712009-09-17 21:32:03 +00001335void Sema::CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS,
1336 bool EnteringContext) {
1337 if (!SS.getScopeRep() || !CodeCompleter)
1338 return;
1339
Douglas Gregor3545ff42009-09-21 16:56:56 +00001340 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
1341 if (!Ctx)
1342 return;
1343
1344 ResultBuilder Results(*this);
Douglas Gregor2af2f672009-09-21 20:12:40 +00001345 unsigned NextRank = CollectMemberLookupResults(Ctx, 0, Ctx, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001346
1347 // The "template" keyword can follow "::" in the grammar, but only
1348 // put it into the grammar if the nested-name-specifier is dependent.
1349 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
1350 if (!Results.empty() && NNS->isDependent())
1351 Results.MaybeAddResult(CodeCompleteConsumer::Result("template", NextRank));
1352
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001353 AddMacroResults(PP, NextRank + 1, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001354 HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00001355}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00001356
1357void Sema::CodeCompleteUsing(Scope *S) {
1358 if (!CodeCompleter)
1359 return;
1360
Douglas Gregor3545ff42009-09-21 16:56:56 +00001361 ResultBuilder Results(*this, &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00001362 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00001363
1364 // If we aren't in class scope, we could see the "namespace" keyword.
1365 if (!S->isClassScope())
1366 Results.MaybeAddResult(CodeCompleteConsumer::Result("namespace", 0));
1367
1368 // After "using", we can see anything that would start a
1369 // nested-name-specifier.
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001370 unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
1371 0, CurContext, Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00001372 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00001373
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001374 AddMacroResults(PP, NextRank, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001375 HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00001376}
1377
1378void Sema::CodeCompleteUsingDirective(Scope *S) {
1379 if (!CodeCompleter)
1380 return;
1381
Douglas Gregor3545ff42009-09-21 16:56:56 +00001382 // After "using namespace", we expect to see a namespace name or namespace
1383 // alias.
1384 ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00001385 Results.EnterNewScope();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001386 unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
1387 0, CurContext, Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00001388 Results.ExitScope();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001389 AddMacroResults(PP, NextRank, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001390 HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00001391}
1392
1393void Sema::CodeCompleteNamespaceDecl(Scope *S) {
1394 if (!CodeCompleter)
1395 return;
1396
Douglas Gregor3545ff42009-09-21 16:56:56 +00001397 ResultBuilder Results(*this, &ResultBuilder::IsNamespace);
1398 DeclContext *Ctx = (DeclContext *)S->getEntity();
1399 if (!S->getParent())
1400 Ctx = Context.getTranslationUnitDecl();
1401
1402 if (Ctx && Ctx->isFileContext()) {
1403 // We only want to see those namespaces that have already been defined
1404 // within this scope, because its likely that the user is creating an
1405 // extended namespace declaration. Keep track of the most recent
1406 // definition of each namespace.
1407 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
1408 for (DeclContext::specific_decl_iterator<NamespaceDecl>
1409 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
1410 NS != NSEnd; ++NS)
1411 OrigToLatest[NS->getOriginalNamespace()] = *NS;
1412
1413 // Add the most recent definition (or extended definition) of each
1414 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00001415 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00001416 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
1417 NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
1418 NS != NSEnd; ++NS)
Douglas Gregor2af2f672009-09-21 20:12:40 +00001419 Results.MaybeAddResult(CodeCompleteConsumer::Result(NS->second, 0),
1420 CurContext);
Douglas Gregor64b12b52009-09-22 23:31:26 +00001421 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00001422 }
1423
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001424 AddMacroResults(PP, 1, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001425 HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00001426}
1427
1428void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
1429 if (!CodeCompleter)
1430 return;
1431
Douglas Gregor3545ff42009-09-21 16:56:56 +00001432 // After "namespace", we expect to see a namespace or alias.
1433 ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001434 unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
1435 0, CurContext, Results);
1436 AddMacroResults(PP, NextRank, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001437 HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00001438}
1439
Douglas Gregorc811ede2009-09-18 20:05:18 +00001440void Sema::CodeCompleteOperatorName(Scope *S) {
1441 if (!CodeCompleter)
1442 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001443
1444 typedef CodeCompleteConsumer::Result Result;
1445 ResultBuilder Results(*this, &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00001446 Results.EnterNewScope();
Douglas Gregorc811ede2009-09-18 20:05:18 +00001447
Douglas Gregor3545ff42009-09-21 16:56:56 +00001448 // Add the names of overloadable operators.
1449#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
1450 if (std::strcmp(Spelling, "?")) \
1451 Results.MaybeAddResult(Result(Spelling, 0));
1452#include "clang/Basic/OperatorKinds.def"
1453
1454 // Add any type names visible from the current scope
1455 unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
Douglas Gregor2af2f672009-09-21 20:12:40 +00001456 0, CurContext, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001457
1458 // Add any type specifiers
1459 AddTypeSpecifierResults(getLangOptions(), 0, Results);
1460
1461 // Add any nested-name-specifiers
1462 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001463 NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
1464 NextRank + 1, CurContext, Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00001465 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00001466
Douglas Gregorf329c7c2009-10-30 16:50:04 +00001467 AddMacroResults(PP, NextRank, Results);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001468 HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00001469}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00001470
Steve Naroff936354c2009-10-08 21:55:05 +00001471void Sema::CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) {
1472 if (!CodeCompleter)
1473 return;
1474 unsigned Attributes = ODS.getPropertyAttributes();
1475
1476 typedef CodeCompleteConsumer::Result Result;
1477 ResultBuilder Results(*this);
1478 Results.EnterNewScope();
1479 if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly))
1480 Results.MaybeAddResult(CodeCompleteConsumer::Result("readonly", 0));
1481 if (!(Attributes & ObjCDeclSpec::DQ_PR_assign))
1482 Results.MaybeAddResult(CodeCompleteConsumer::Result("assign", 0));
1483 if (!(Attributes & ObjCDeclSpec::DQ_PR_readwrite))
1484 Results.MaybeAddResult(CodeCompleteConsumer::Result("readwrite", 0));
1485 if (!(Attributes & ObjCDeclSpec::DQ_PR_retain))
1486 Results.MaybeAddResult(CodeCompleteConsumer::Result("retain", 0));
1487 if (!(Attributes & ObjCDeclSpec::DQ_PR_copy))
1488 Results.MaybeAddResult(CodeCompleteConsumer::Result("copy", 0));
1489 if (!(Attributes & ObjCDeclSpec::DQ_PR_nonatomic))
1490 Results.MaybeAddResult(CodeCompleteConsumer::Result("nonatomic", 0));
1491 if (!(Attributes & ObjCDeclSpec::DQ_PR_setter))
1492 Results.MaybeAddResult(CodeCompleteConsumer::Result("setter", 0));
1493 if (!(Attributes & ObjCDeclSpec::DQ_PR_getter))
1494 Results.MaybeAddResult(CodeCompleteConsumer::Result("getter", 0));
1495 Results.ExitScope();
1496 HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
1497}