blob: cdad740851183c3be54dfa33094ed0e2e43c3cb7 [file] [log] [blame]
Douglas Gregor81b747b2009-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//===----------------------------------------------------------------------===//
John McCall2d887082010-08-25 22:03:47 +000013#include "clang/Sema/SemaInternal.h"
Douglas Gregore737f502010-08-12 20:07:10 +000014#include "clang/Sema/Lookup.h"
John McCall120d63c2010-08-24 20:38:10 +000015#include "clang/Sema/Overload.h"
Douglas Gregor81b747b2009-09-17 21:32:03 +000016#include "clang/Sema/CodeCompleteConsumer.h"
Douglas Gregor719770d2010-04-06 17:30:22 +000017#include "clang/Sema/ExternalSemaSource.h"
John McCall5f1e0942010-08-24 08:50:51 +000018#include "clang/Sema/Scope.h"
John McCall781472f2010-08-25 08:40:02 +000019#include "clang/Sema/ScopeInfo.h"
John McCall7cd088e2010-08-24 07:21:54 +000020#include "clang/AST/DeclObjC.h"
Douglas Gregorb9d0ef72009-09-21 19:57:38 +000021#include "clang/AST/ExprCXX.h"
Douglas Gregor24a069f2009-11-17 17:59:40 +000022#include "clang/AST/ExprObjC.h"
Douglas Gregorc5b2e582012-01-29 18:15:03 +000023#include "clang/Lex/HeaderSearch.h"
Douglas Gregor3f7c7f42009-10-30 16:50:04 +000024#include "clang/Lex/MacroInfo.h"
25#include "clang/Lex/Preprocessor.h"
Douglas Gregord36adf52010-09-16 16:06:31 +000026#include "llvm/ADT/DenseSet.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000027#include "llvm/ADT/SmallPtrSet.h"
Douglas Gregor6a684032009-09-28 03:51:44 +000028#include "llvm/ADT/StringExtras.h"
Douglas Gregor22f56992010-04-06 19:22:33 +000029#include "llvm/ADT/StringSwitch.h"
Douglas Gregor458433d2010-08-26 15:07:07 +000030#include "llvm/ADT/Twine.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000031#include <list>
32#include <map>
33#include <vector>
Douglas Gregor81b747b2009-09-17 21:32:03 +000034
35using namespace clang;
John McCall781472f2010-08-25 08:40:02 +000036using namespace sema;
Douglas Gregor81b747b2009-09-17 21:32:03 +000037
Douglas Gregor86d9a522009-09-21 16:56:56 +000038namespace {
39 /// \brief A container of code-completion results.
40 class ResultBuilder {
41 public:
42 /// \brief The type of a name-lookup filter, which can be provided to the
43 /// name-lookup routines to specify which declarations should be included in
44 /// the result set (when it returns true) and which declarations should be
45 /// filtered out (returns false).
46 typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
47
John McCall0a2c5e22010-08-25 06:19:51 +000048 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +000049
50 private:
51 /// \brief The actual results we have found.
52 std::vector<Result> Results;
53
54 /// \brief A record of all of the declarations we have found and placed
55 /// into the result set, used to ensure that no declaration ever gets into
56 /// the result set twice.
57 llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
58
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000059 typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
60
61 /// \brief An entry in the shadow map, which is optimized to store
62 /// a single (declaration, index) mapping (the common case) but
63 /// can also store a list of (declaration, index) mappings.
64 class ShadowMapEntry {
Chris Lattner5f9e2722011-07-23 10:55:15 +000065 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000066
67 /// \brief Contains either the solitary NamedDecl * or a vector
68 /// of (declaration, index) pairs.
69 llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
70
71 /// \brief When the entry contains a single declaration, this is
72 /// the index associated with that entry.
73 unsigned SingleDeclIndex;
74
75 public:
76 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
77
78 void Add(NamedDecl *ND, unsigned Index) {
79 if (DeclOrVector.isNull()) {
80 // 0 - > 1 elements: just set the single element information.
81 DeclOrVector = ND;
82 SingleDeclIndex = Index;
83 return;
84 }
85
86 if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
87 // 1 -> 2 elements: create the vector of results and push in the
88 // existing declaration.
89 DeclIndexPairVector *Vec = new DeclIndexPairVector;
90 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
91 DeclOrVector = Vec;
92 }
93
94 // Add the new element to the end of the vector.
95 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
96 DeclIndexPair(ND, Index));
97 }
98
99 void Destroy() {
100 if (DeclIndexPairVector *Vec
101 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
102 delete Vec;
103 DeclOrVector = ((NamedDecl *)0);
104 }
105 }
106
107 // Iteration.
108 class iterator;
109 iterator begin() const;
110 iterator end() const;
111 };
112
Douglas Gregor86d9a522009-09-21 16:56:56 +0000113 /// \brief A mapping from declaration names to the declarations that have
114 /// this name within a particular scope and their index within the list of
115 /// results.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000116 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000117
118 /// \brief The semantic analysis object for which results are being
119 /// produced.
120 Sema &SemaRef;
Douglas Gregor218937c2011-02-01 19:23:04 +0000121
122 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000123 CodeCompletionAllocator &Allocator;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000124
125 /// \brief If non-NULL, a filter function used to remove any code-completion
126 /// results that are not desirable.
127 LookupFilter Filter;
Douglas Gregor45bcd432010-01-14 03:21:49 +0000128
129 /// \brief Whether we should allow declarations as
130 /// nested-name-specifiers that would otherwise be filtered out.
131 bool AllowNestedNameSpecifiers;
132
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000133 /// \brief If set, the type that we would prefer our resulting value
134 /// declarations to have.
135 ///
136 /// Closely matching the preferred type gives a boost to a result's
137 /// priority.
138 CanQualType PreferredType;
139
Douglas Gregor86d9a522009-09-21 16:56:56 +0000140 /// \brief A list of shadow maps, which is used to model name hiding at
141 /// different levels of, e.g., the inheritance hierarchy.
142 std::list<ShadowMap> ShadowMaps;
143
Douglas Gregor3cdee122010-08-26 16:36:48 +0000144 /// \brief If we're potentially referring to a C++ member function, the set
145 /// of qualifiers applied to the object type.
146 Qualifiers ObjectTypeQualifiers;
147
148 /// \brief Whether the \p ObjectTypeQualifiers field is active.
149 bool HasObjectTypeQualifiers;
150
Douglas Gregor265f7492010-08-27 15:29:55 +0000151 /// \brief The selector that we prefer.
152 Selector PreferredSelector;
153
Douglas Gregorca45da02010-11-02 20:36:02 +0000154 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000155 CodeCompletionContext CompletionContext;
156
Douglas Gregorca45da02010-11-02 20:36:02 +0000157 /// \brief If we are in an instance method definition, the @implementation
158 /// object.
159 ObjCImplementationDecl *ObjCImplementation;
160
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000161 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000162
Douglas Gregor6f942b22010-09-21 16:06:22 +0000163 void MaybeAddConstructorResults(Result R);
164
Douglas Gregor86d9a522009-09-21 16:56:56 +0000165 public:
Douglas Gregordae68752011-02-01 22:57:45 +0000166 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000167 const CodeCompletionContext &CompletionContext,
168 LookupFilter Filter = 0)
Douglas Gregor218937c2011-02-01 19:23:04 +0000169 : SemaRef(SemaRef), Allocator(Allocator), Filter(Filter),
170 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-11-02 20:36:02 +0000171 CompletionContext(CompletionContext),
172 ObjCImplementation(0)
173 {
174 // If this is an Objective-C instance method definition, dig out the
175 // corresponding implementation.
176 switch (CompletionContext.getKind()) {
177 case CodeCompletionContext::CCC_Expression:
178 case CodeCompletionContext::CCC_ObjCMessageReceiver:
179 case CodeCompletionContext::CCC_ParenthesizedExpression:
180 case CodeCompletionContext::CCC_Statement:
181 case CodeCompletionContext::CCC_Recovery:
182 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
183 if (Method->isInstanceMethod())
184 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
185 ObjCImplementation = Interface->getImplementation();
186 break;
187
188 default:
189 break;
190 }
191 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000192
Douglas Gregord8e8a582010-05-25 21:41:55 +0000193 /// \brief Whether we should include code patterns in the completion
194 /// results.
195 bool includeCodePatterns() const {
196 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000197 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000198 }
199
Douglas Gregor86d9a522009-09-21 16:56:56 +0000200 /// \brief Set the filter used for code-completion results.
201 void setFilter(LookupFilter Filter) {
202 this->Filter = Filter;
203 }
204
Douglas Gregor86d9a522009-09-21 16:56:56 +0000205 Result *data() { return Results.empty()? 0 : &Results.front(); }
206 unsigned size() const { return Results.size(); }
207 bool empty() const { return Results.empty(); }
208
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000209 /// \brief Specify the preferred type.
210 void setPreferredType(QualType T) {
211 PreferredType = SemaRef.Context.getCanonicalType(T);
212 }
213
Douglas Gregor3cdee122010-08-26 16:36:48 +0000214 /// \brief Set the cv-qualifiers on the object type, for us in filtering
215 /// calls to member functions.
216 ///
217 /// When there are qualifiers in this set, they will be used to filter
218 /// out member functions that aren't available (because there will be a
219 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
220 /// match.
221 void setObjectTypeQualifiers(Qualifiers Quals) {
222 ObjectTypeQualifiers = Quals;
223 HasObjectTypeQualifiers = true;
224 }
225
Douglas Gregor265f7492010-08-27 15:29:55 +0000226 /// \brief Set the preferred selector.
227 ///
228 /// When an Objective-C method declaration result is added, and that
229 /// method's selector matches this preferred selector, we give that method
230 /// a slight priority boost.
231 void setPreferredSelector(Selector Sel) {
232 PreferredSelector = Sel;
233 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000234
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000235 /// \brief Retrieve the code-completion context for which results are
236 /// being collected.
237 const CodeCompletionContext &getCompletionContext() const {
238 return CompletionContext;
239 }
240
Douglas Gregor45bcd432010-01-14 03:21:49 +0000241 /// \brief Specify whether nested-name-specifiers are allowed.
242 void allowNestedNameSpecifiers(bool Allow = true) {
243 AllowNestedNameSpecifiers = Allow;
244 }
245
Douglas Gregorb9d77572010-09-21 00:03:25 +0000246 /// \brief Return the semantic analysis object for which we are collecting
247 /// code completion results.
248 Sema &getSema() const { return SemaRef; }
249
Douglas Gregor218937c2011-02-01 19:23:04 +0000250 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000251 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Douglas Gregor218937c2011-02-01 19:23:04 +0000252
Douglas Gregore495b7f2010-01-14 00:20:49 +0000253 /// \brief Determine whether the given declaration is at all interesting
254 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000255 ///
256 /// \param ND the declaration that we are inspecting.
257 ///
258 /// \param AsNestedNameSpecifier will be set true if this declaration is
259 /// only interesting when it is a nested-name-specifier.
260 bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000261
262 /// \brief Check whether the result is hidden by the Hiding declaration.
263 ///
264 /// \returns true if the result is hidden and cannot be found, false if
265 /// the hidden result could still be found. When false, \p R may be
266 /// modified to describe how the result can be found (e.g., via extra
267 /// qualification).
268 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
269 NamedDecl *Hiding);
270
Douglas Gregor86d9a522009-09-21 16:56:56 +0000271 /// \brief Add a new result to this result set (if it isn't already in one
272 /// of the shadow maps), or replace an existing result (for, e.g., a
273 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000274 ///
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000275 /// \param CurContext the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000276 ///
277 /// \param R the context in which this result will be named.
278 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000279
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000280 /// \brief Add a new result to this result set, where we already know
281 /// the hiding declation (if any).
282 ///
283 /// \param R the result to add (if it is unique).
284 ///
285 /// \param CurContext the context in which this result will be named.
286 ///
287 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000288 ///
289 /// \param InBaseClass whether the result was found in a base
290 /// class of the searched context.
291 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
292 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000293
Douglas Gregora4477812010-01-14 16:01:26 +0000294 /// \brief Add a new non-declaration result to this result set.
295 void AddResult(Result R);
296
Douglas Gregor86d9a522009-09-21 16:56:56 +0000297 /// \brief Enter into a new scope.
298 void EnterNewScope();
299
300 /// \brief Exit from the current scope.
301 void ExitScope();
302
Douglas Gregor55385fe2009-11-18 04:19:12 +0000303 /// \brief Ignore this declaration, if it is seen again.
304 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
305
Douglas Gregor86d9a522009-09-21 16:56:56 +0000306 /// \name Name lookup predicates
307 ///
308 /// These predicates can be passed to the name lookup functions to filter the
309 /// results of name lookup. All of the predicates have the same type, so that
310 ///
311 //@{
Douglas Gregor791215b2009-09-21 20:51:25 +0000312 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000313 bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
Douglas Gregorf9578432010-07-28 21:50:18 +0000314 bool IsIntegralConstantValue(NamedDecl *ND) const;
Douglas Gregor01dfea02010-01-10 23:08:15 +0000315 bool IsOrdinaryNonValueName(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000316 bool IsNestedNameSpecifier(NamedDecl *ND) const;
317 bool IsEnum(NamedDecl *ND) const;
318 bool IsClassOrStruct(NamedDecl *ND) const;
319 bool IsUnion(NamedDecl *ND) const;
320 bool IsNamespace(NamedDecl *ND) const;
321 bool IsNamespaceOrAlias(NamedDecl *ND) const;
322 bool IsType(NamedDecl *ND) const;
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000323 bool IsMember(NamedDecl *ND) const;
Douglas Gregor80f4f4c2010-01-14 16:08:12 +0000324 bool IsObjCIvar(NamedDecl *ND) const;
Douglas Gregor8e254cf2010-05-27 23:06:34 +0000325 bool IsObjCMessageReceiver(NamedDecl *ND) const;
Douglas Gregorfb629412010-08-23 21:17:50 +0000326 bool IsObjCCollection(NamedDecl *ND) const;
Douglas Gregor52779fb2010-09-23 23:01:17 +0000327 bool IsImpossibleToSatisfy(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000328 //@}
329 };
330}
331
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000332class ResultBuilder::ShadowMapEntry::iterator {
333 llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
334 unsigned SingleDeclIndex;
335
336public:
337 typedef DeclIndexPair value_type;
338 typedef value_type reference;
339 typedef std::ptrdiff_t difference_type;
340 typedef std::input_iterator_tag iterator_category;
341
342 class pointer {
343 DeclIndexPair Value;
344
345 public:
346 pointer(const DeclIndexPair &Value) : Value(Value) { }
347
348 const DeclIndexPair *operator->() const {
349 return &Value;
350 }
351 };
352
353 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
354
355 iterator(NamedDecl *SingleDecl, unsigned Index)
356 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
357
358 iterator(const DeclIndexPair *Iterator)
359 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
360
361 iterator &operator++() {
362 if (DeclOrIterator.is<NamedDecl *>()) {
363 DeclOrIterator = (NamedDecl *)0;
364 SingleDeclIndex = 0;
365 return *this;
366 }
367
368 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
369 ++I;
370 DeclOrIterator = I;
371 return *this;
372 }
373
Chris Lattner66392d42010-09-04 18:12:20 +0000374 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000375 iterator tmp(*this);
376 ++(*this);
377 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000378 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000379
380 reference operator*() const {
381 if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
382 return reference(ND, SingleDeclIndex);
383
Douglas Gregord490f952009-12-06 21:27:58 +0000384 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000385 }
386
387 pointer operator->() const {
388 return pointer(**this);
389 }
390
391 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000392 return X.DeclOrIterator.getOpaqueValue()
393 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000394 X.SingleDeclIndex == Y.SingleDeclIndex;
395 }
396
397 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000398 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000399 }
400};
401
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000402ResultBuilder::ShadowMapEntry::iterator
403ResultBuilder::ShadowMapEntry::begin() const {
404 if (DeclOrVector.isNull())
405 return iterator();
406
407 if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
408 return iterator(ND, SingleDeclIndex);
409
410 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
411}
412
413ResultBuilder::ShadowMapEntry::iterator
414ResultBuilder::ShadowMapEntry::end() const {
415 if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
416 return iterator();
417
418 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
419}
420
Douglas Gregor456c4a12009-09-21 20:12:40 +0000421/// \brief Compute the qualification required to get from the current context
422/// (\p CurContext) to the target context (\p TargetContext).
423///
424/// \param Context the AST context in which the qualification will be used.
425///
426/// \param CurContext the context where an entity is being named, which is
427/// typically based on the current scope.
428///
429/// \param TargetContext the context in which the named entity actually
430/// resides.
431///
432/// \returns a nested name specifier that refers into the target context, or
433/// NULL if no qualification is needed.
434static NestedNameSpecifier *
435getRequiredQualification(ASTContext &Context,
436 DeclContext *CurContext,
437 DeclContext *TargetContext) {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000438 SmallVector<DeclContext *, 4> TargetParents;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000439
440 for (DeclContext *CommonAncestor = TargetContext;
441 CommonAncestor && !CommonAncestor->Encloses(CurContext);
442 CommonAncestor = CommonAncestor->getLookupParent()) {
443 if (CommonAncestor->isTransparentContext() ||
444 CommonAncestor->isFunctionOrMethod())
445 continue;
446
447 TargetParents.push_back(CommonAncestor);
448 }
449
450 NestedNameSpecifier *Result = 0;
451 while (!TargetParents.empty()) {
452 DeclContext *Parent = TargetParents.back();
453 TargetParents.pop_back();
454
Douglas Gregorfb629412010-08-23 21:17:50 +0000455 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
456 if (!Namespace->getIdentifier())
457 continue;
458
Douglas Gregor456c4a12009-09-21 20:12:40 +0000459 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000460 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000461 else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
462 Result = NestedNameSpecifier::Create(Context, Result,
463 false,
464 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000465 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000466 return Result;
467}
468
Douglas Gregor45bcd432010-01-14 03:21:49 +0000469bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
470 bool &AsNestedNameSpecifier) const {
471 AsNestedNameSpecifier = false;
472
Douglas Gregore495b7f2010-01-14 00:20:49 +0000473 ND = ND->getUnderlyingDecl();
474 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000475
476 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000477 if (!ND->getDeclName())
478 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000479
480 // Friend declarations and declarations introduced due to friends are never
481 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000482 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000483 return false;
484
Douglas Gregor76282942009-12-11 17:31:05 +0000485 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000486 if (isa<ClassTemplateSpecializationDecl>(ND) ||
487 isa<ClassTemplatePartialSpecializationDecl>(ND))
488 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000489
Douglas Gregor76282942009-12-11 17:31:05 +0000490 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000491 if (isa<UsingDecl>(ND))
492 return false;
493
494 // Some declarations have reserved names that we don't want to ever show.
495 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000496 // __va_list_tag is a freak of nature. Find it and skip it.
497 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000498 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000499
Douglas Gregorf52cede2009-10-09 22:16:47 +0000500 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000501 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000502 //
503 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000504 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000505 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000506 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000507 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
508 (ND->getLocation().isInvalid() ||
509 SemaRef.SourceMgr.isInSystemHeader(
510 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000511 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000512 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000513 }
Douglas Gregor6f942b22010-09-21 16:06:22 +0000514
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000515 // Skip out-of-line declarations and definitions.
516 // NOTE: Unless it's an Objective-C property, method, or ivar, where
517 // the contexts can be messy.
518 if (!ND->getDeclContext()->Equals(ND->getLexicalDeclContext()) &&
519 !(isa<ObjCPropertyDecl>(ND) || isa<ObjCIvarDecl>(ND) ||
520 isa<ObjCMethodDecl>(ND)))
521 return false;
522
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000523 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
524 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
525 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000526 Filter != &ResultBuilder::IsNamespaceOrAlias &&
527 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000528 AsNestedNameSpecifier = true;
529
Douglas Gregor86d9a522009-09-21 16:56:56 +0000530 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000531 if (Filter && !(this->*Filter)(ND)) {
532 // Check whether it is interesting as a nested-name-specifier.
533 if (AllowNestedNameSpecifiers && SemaRef.getLangOptions().CPlusPlus &&
534 IsNestedNameSpecifier(ND) &&
535 (Filter != &ResultBuilder::IsMember ||
536 (isa<CXXRecordDecl>(ND) &&
537 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
538 AsNestedNameSpecifier = true;
539 return true;
540 }
541
Douglas Gregore495b7f2010-01-14 00:20:49 +0000542 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000543 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000544 // ... then it must be interesting!
545 return true;
546}
547
Douglas Gregor6660d842010-01-14 00:41:07 +0000548bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
549 NamedDecl *Hiding) {
550 // In C, there is no way to refer to a hidden name.
551 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
552 // name if we introduce the tag type.
553 if (!SemaRef.getLangOptions().CPlusPlus)
554 return true;
555
Sebastian Redl7a126a42010-08-31 00:36:30 +0000556 DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000557
558 // There is no way to qualify a name declared in a function or method.
559 if (HiddenCtx->isFunctionOrMethod())
560 return true;
561
Sebastian Redl7a126a42010-08-31 00:36:30 +0000562 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000563 return true;
564
565 // We can refer to the result with the appropriate qualification. Do it.
566 R.Hidden = true;
567 R.QualifierIsInformative = false;
568
569 if (!R.Qualifier)
570 R.Qualifier = getRequiredQualification(SemaRef.Context,
571 CurContext,
572 R.Declaration->getDeclContext());
573 return false;
574}
575
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000576/// \brief A simplified classification of types used to determine whether two
577/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000578SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000579 switch (T->getTypeClass()) {
580 case Type::Builtin:
581 switch (cast<BuiltinType>(T)->getKind()) {
582 case BuiltinType::Void:
583 return STC_Void;
584
585 case BuiltinType::NullPtr:
586 return STC_Pointer;
587
588 case BuiltinType::Overload:
589 case BuiltinType::Dependent:
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000590 return STC_Other;
591
592 case BuiltinType::ObjCId:
593 case BuiltinType::ObjCClass:
594 case BuiltinType::ObjCSel:
595 return STC_ObjectiveC;
596
597 default:
598 return STC_Arithmetic;
599 }
David Blaikie7530c032012-01-17 06:56:22 +0000600
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000601 case Type::Complex:
602 return STC_Arithmetic;
603
604 case Type::Pointer:
605 return STC_Pointer;
606
607 case Type::BlockPointer:
608 return STC_Block;
609
610 case Type::LValueReference:
611 case Type::RValueReference:
612 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
613
614 case Type::ConstantArray:
615 case Type::IncompleteArray:
616 case Type::VariableArray:
617 case Type::DependentSizedArray:
618 return STC_Array;
619
620 case Type::DependentSizedExtVector:
621 case Type::Vector:
622 case Type::ExtVector:
623 return STC_Arithmetic;
624
625 case Type::FunctionProto:
626 case Type::FunctionNoProto:
627 return STC_Function;
628
629 case Type::Record:
630 return STC_Record;
631
632 case Type::Enum:
633 return STC_Arithmetic;
634
635 case Type::ObjCObject:
636 case Type::ObjCInterface:
637 case Type::ObjCObjectPointer:
638 return STC_ObjectiveC;
639
640 default:
641 return STC_Other;
642 }
643}
644
645/// \brief Get the type that a given expression will have if this declaration
646/// is used as an expression in its "typical" code-completion form.
Douglas Gregor1827e102010-08-16 16:18:59 +0000647QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000648 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
649
650 if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
651 return C.getTypeDeclType(Type);
652 if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
653 return C.getObjCInterfaceType(Iface);
654
655 QualType T;
656 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000657 T = Function->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000658 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000659 T = Method->getSendResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000660 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000661 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000662 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
663 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
664 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
665 T = Property->getType();
666 else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
667 T = Value->getType();
668 else
669 return QualType();
Douglas Gregor3e64d562011-04-14 20:33:34 +0000670
671 // Dig through references, function pointers, and block pointers to
672 // get down to the likely type of an expression when the entity is
673 // used.
674 do {
675 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
676 T = Ref->getPointeeType();
677 continue;
678 }
679
680 if (const PointerType *Pointer = T->getAs<PointerType>()) {
681 if (Pointer->getPointeeType()->isFunctionType()) {
682 T = Pointer->getPointeeType();
683 continue;
684 }
685
686 break;
687 }
688
689 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
690 T = Block->getPointeeType();
691 continue;
692 }
693
694 if (const FunctionType *Function = T->getAs<FunctionType>()) {
695 T = Function->getResultType();
696 continue;
697 }
698
699 break;
700 } while (true);
701
702 return T;
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000703}
704
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000705void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
706 // If this is an Objective-C method declaration whose selector matches our
707 // preferred selector, give it a priority boost.
708 if (!PreferredSelector.isNull())
709 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
710 if (PreferredSelector == Method->getSelector())
711 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000712
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000713 // If we have a preferred type, adjust the priority for results with exactly-
714 // matching or nearly-matching types.
715 if (!PreferredType.isNull()) {
716 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
717 if (!T.isNull()) {
718 CanQualType TC = SemaRef.Context.getCanonicalType(T);
719 // Check for exactly-matching types (modulo qualifiers).
720 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
721 R.Priority /= CCF_ExactTypeMatch;
722 // Check for nearly-matching types, based on classification of each.
723 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000724 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000725 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
726 R.Priority /= CCF_SimilarTypeMatch;
727 }
728 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000729}
730
Douglas Gregor6f942b22010-09-21 16:06:22 +0000731void ResultBuilder::MaybeAddConstructorResults(Result R) {
732 if (!SemaRef.getLangOptions().CPlusPlus || !R.Declaration ||
733 !CompletionContext.wantConstructorResults())
734 return;
735
736 ASTContext &Context = SemaRef.Context;
737 NamedDecl *D = R.Declaration;
738 CXXRecordDecl *Record = 0;
739 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
740 Record = ClassTemplate->getTemplatedDecl();
741 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
742 // Skip specializations and partial specializations.
743 if (isa<ClassTemplateSpecializationDecl>(Record))
744 return;
745 } else {
746 // There are no constructors here.
747 return;
748 }
749
750 Record = Record->getDefinition();
751 if (!Record)
752 return;
753
754
755 QualType RecordTy = Context.getTypeDeclType(Record);
756 DeclarationName ConstructorName
757 = Context.DeclarationNames.getCXXConstructorName(
758 Context.getCanonicalType(RecordTy));
759 for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
760 Ctors.first != Ctors.second; ++Ctors.first) {
761 R.Declaration = *Ctors.first;
762 R.CursorKind = getCursorKindForDecl(R.Declaration);
763 Results.push_back(R);
764 }
765}
766
Douglas Gregore495b7f2010-01-14 00:20:49 +0000767void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
768 assert(!ShadowMaps.empty() && "Must enter into a results scope");
769
770 if (R.Kind != Result::RK_Declaration) {
771 // For non-declaration results, just add the result.
772 Results.push_back(R);
773 return;
774 }
775
776 // Look through using declarations.
777 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
778 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
779 return;
780 }
781
782 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
783 unsigned IDNS = CanonDecl->getIdentifierNamespace();
784
Douglas Gregor45bcd432010-01-14 03:21:49 +0000785 bool AsNestedNameSpecifier = false;
786 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000787 return;
788
Douglas Gregor6f942b22010-09-21 16:06:22 +0000789 // C++ constructors are never found by name lookup.
790 if (isa<CXXConstructorDecl>(R.Declaration))
791 return;
792
Douglas Gregor86d9a522009-09-21 16:56:56 +0000793 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000794 ShadowMapEntry::iterator I, IEnd;
795 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
796 if (NamePos != SMap.end()) {
797 I = NamePos->second.begin();
798 IEnd = NamePos->second.end();
799 }
800
801 for (; I != IEnd; ++I) {
802 NamedDecl *ND = I->first;
803 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000804 if (ND->getCanonicalDecl() == CanonDecl) {
805 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000806 Results[Index].Declaration = R.Declaration;
807
Douglas Gregor86d9a522009-09-21 16:56:56 +0000808 // We're done.
809 return;
810 }
811 }
812
813 // This is a new declaration in this scope. However, check whether this
814 // declaration name is hidden by a similarly-named declaration in an outer
815 // scope.
816 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
817 --SMEnd;
818 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000819 ShadowMapEntry::iterator I, IEnd;
820 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
821 if (NamePos != SM->end()) {
822 I = NamePos->second.begin();
823 IEnd = NamePos->second.end();
824 }
825 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000826 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000827 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000828 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
829 Decl::IDNS_ObjCProtocol)))
830 continue;
831
832 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000833 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000834 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000835 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000836 continue;
837
838 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000839 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000840 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000841
842 break;
843 }
844 }
845
846 // Make sure that any given declaration only shows up in the result set once.
847 if (!AllDeclsFound.insert(CanonDecl))
848 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000849
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000850 // If the filter is for nested-name-specifiers, then this result starts a
851 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000852 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000853 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000854 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000855 } else
856 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000857
Douglas Gregor0563c262009-09-22 23:15:58 +0000858 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000859 if (R.QualifierIsInformative && !R.Qualifier &&
860 !R.StartsNestedNameSpecifier) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000861 DeclContext *Ctx = R.Declaration->getDeclContext();
862 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
863 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
864 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
865 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
866 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
867 else
868 R.QualifierIsInformative = false;
869 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000870
Douglas Gregor86d9a522009-09-21 16:56:56 +0000871 // Insert this result into the set of results and into the current shadow
872 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000873 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000874 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000875
876 if (!AsNestedNameSpecifier)
877 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000878}
879
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000880void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000881 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000882 if (R.Kind != Result::RK_Declaration) {
883 // For non-declaration results, just add the result.
884 Results.push_back(R);
885 return;
886 }
887
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000888 // Look through using declarations.
889 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
890 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
891 return;
892 }
893
Douglas Gregor45bcd432010-01-14 03:21:49 +0000894 bool AsNestedNameSpecifier = false;
895 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000896 return;
897
Douglas Gregor6f942b22010-09-21 16:06:22 +0000898 // C++ constructors are never found by name lookup.
899 if (isa<CXXConstructorDecl>(R.Declaration))
900 return;
901
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000902 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
903 return;
904
905 // Make sure that any given declaration only shows up in the result set once.
906 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
907 return;
908
909 // If the filter is for nested-name-specifiers, then this result starts a
910 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000911 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000912 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000913 R.Priority = CCP_NestedNameSpecifier;
914 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000915 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
916 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000917 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000918 R.QualifierIsInformative = true;
919
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000920 // If this result is supposed to have an informative qualifier, add one.
921 if (R.QualifierIsInformative && !R.Qualifier &&
922 !R.StartsNestedNameSpecifier) {
923 DeclContext *Ctx = R.Declaration->getDeclContext();
924 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
925 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
926 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
927 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000928 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000929 else
930 R.QualifierIsInformative = false;
931 }
932
Douglas Gregor12e13132010-05-26 22:00:08 +0000933 // Adjust the priority if this result comes from a base class.
934 if (InBaseClass)
935 R.Priority += CCD_InBaseClass;
936
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000937 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000938
Douglas Gregor3cdee122010-08-26 16:36:48 +0000939 if (HasObjectTypeQualifiers)
940 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
941 if (Method->isInstance()) {
942 Qualifiers MethodQuals
943 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
944 if (ObjectTypeQualifiers == MethodQuals)
945 R.Priority += CCD_ObjectQualifierMatch;
946 else if (ObjectTypeQualifiers - MethodQuals) {
947 // The method cannot be invoked, because doing so would drop
948 // qualifiers.
949 return;
950 }
951 }
952
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000953 // Insert this result into the set of results.
954 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000955
956 if (!AsNestedNameSpecifier)
957 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000958}
959
Douglas Gregora4477812010-01-14 16:01:26 +0000960void ResultBuilder::AddResult(Result R) {
961 assert(R.Kind != Result::RK_Declaration &&
962 "Declaration results need more context");
963 Results.push_back(R);
964}
965
Douglas Gregor86d9a522009-09-21 16:56:56 +0000966/// \brief Enter into a new scope.
967void ResultBuilder::EnterNewScope() {
968 ShadowMaps.push_back(ShadowMap());
969}
970
971/// \brief Exit from the current scope.
972void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000973 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
974 EEnd = ShadowMaps.back().end();
975 E != EEnd;
976 ++E)
977 E->second.Destroy();
978
Douglas Gregor86d9a522009-09-21 16:56:56 +0000979 ShadowMaps.pop_back();
980}
981
Douglas Gregor791215b2009-09-21 20:51:25 +0000982/// \brief Determines whether this given declaration will be found by
983/// ordinary name lookup.
984bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000985 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
986
Douglas Gregor791215b2009-09-21 20:51:25 +0000987 unsigned IDNS = Decl::IDNS_Ordinary;
988 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000989 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Douglas Gregorca45da02010-11-02 20:36:02 +0000990 else if (SemaRef.getLangOptions().ObjC1) {
991 if (isa<ObjCIvarDecl>(ND))
992 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +0000993 }
994
Douglas Gregor791215b2009-09-21 20:51:25 +0000995 return ND->getIdentifierNamespace() & IDNS;
996}
997
Douglas Gregor01dfea02010-01-10 23:08:15 +0000998/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000999/// ordinary name lookup but is not a type name.
1000bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
1001 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1002 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1003 return false;
1004
1005 unsigned IDNS = Decl::IDNS_Ordinary;
1006 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +00001007 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Douglas Gregorca45da02010-11-02 20:36:02 +00001008 else if (SemaRef.getLangOptions().ObjC1) {
1009 if (isa<ObjCIvarDecl>(ND))
1010 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001011 }
1012
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001013 return ND->getIdentifierNamespace() & IDNS;
1014}
1015
Douglas Gregorf9578432010-07-28 21:50:18 +00001016bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
1017 if (!IsOrdinaryNonTypeName(ND))
1018 return 0;
1019
1020 if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
1021 if (VD->getType()->isIntegralOrEnumerationType())
1022 return true;
1023
1024 return false;
1025}
1026
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001027/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001028/// ordinary name lookup.
1029bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001030 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1031
Douglas Gregor01dfea02010-01-10 23:08:15 +00001032 unsigned IDNS = Decl::IDNS_Ordinary;
1033 if (SemaRef.getLangOptions().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001034 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001035
1036 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001037 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1038 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001039}
1040
Douglas Gregor86d9a522009-09-21 16:56:56 +00001041/// \brief Determines whether the given declaration is suitable as the
1042/// start of a C++ nested-name-specifier, e.g., a class or namespace.
1043bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
1044 // Allow us to find class templates, too.
1045 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1046 ND = ClassTemplate->getTemplatedDecl();
1047
1048 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1049}
1050
1051/// \brief Determines whether the given declaration is an enumeration.
1052bool ResultBuilder::IsEnum(NamedDecl *ND) const {
1053 return isa<EnumDecl>(ND);
1054}
1055
1056/// \brief Determines whether the given declaration is a class or struct.
1057bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
1058 // Allow us to find class templates, too.
1059 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1060 ND = ClassTemplate->getTemplatedDecl();
1061
1062 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001063 return RD->getTagKind() == TTK_Class ||
1064 RD->getTagKind() == TTK_Struct;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001065
1066 return false;
1067}
1068
1069/// \brief Determines whether the given declaration is a union.
1070bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1071 // Allow us to find class templates, too.
1072 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1073 ND = ClassTemplate->getTemplatedDecl();
1074
1075 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001076 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001077
1078 return false;
1079}
1080
1081/// \brief Determines whether the given declaration is a namespace.
1082bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1083 return isa<NamespaceDecl>(ND);
1084}
1085
1086/// \brief Determines whether the given declaration is a namespace or
1087/// namespace alias.
1088bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1089 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1090}
1091
Douglas Gregor76282942009-12-11 17:31:05 +00001092/// \brief Determines whether the given declaration is a type.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001093bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregord32b0222010-08-24 01:06:58 +00001094 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1095 ND = Using->getTargetDecl();
1096
1097 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001098}
1099
Douglas Gregor76282942009-12-11 17:31:05 +00001100/// \brief Determines which members of a class should be visible via
1101/// "." or "->". Only value declarations, nested name specifiers, and
1102/// using declarations thereof should show up.
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001103bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor76282942009-12-11 17:31:05 +00001104 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1105 ND = Using->getTargetDecl();
1106
Douglas Gregorce821962009-12-11 18:14:22 +00001107 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1108 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001109}
1110
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001111static bool isObjCReceiverType(ASTContext &C, QualType T) {
1112 T = C.getCanonicalType(T);
1113 switch (T->getTypeClass()) {
1114 case Type::ObjCObject:
1115 case Type::ObjCInterface:
1116 case Type::ObjCObjectPointer:
1117 return true;
1118
1119 case Type::Builtin:
1120 switch (cast<BuiltinType>(T)->getKind()) {
1121 case BuiltinType::ObjCId:
1122 case BuiltinType::ObjCClass:
1123 case BuiltinType::ObjCSel:
1124 return true;
1125
1126 default:
1127 break;
1128 }
1129 return false;
1130
1131 default:
1132 break;
1133 }
1134
1135 if (!C.getLangOptions().CPlusPlus)
1136 return false;
1137
1138 // FIXME: We could perform more analysis here to determine whether a
1139 // particular class type has any conversions to Objective-C types. For now,
1140 // just accept all class types.
1141 return T->isDependentType() || T->isRecordType();
1142}
1143
1144bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1145 QualType T = getDeclUsageType(SemaRef.Context, ND);
1146 if (T.isNull())
1147 return false;
1148
1149 T = SemaRef.Context.getBaseElementType(T);
1150 return isObjCReceiverType(SemaRef.Context, T);
1151}
1152
Douglas Gregorfb629412010-08-23 21:17:50 +00001153bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
1154 if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) ||
1155 (!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
1156 return false;
1157
1158 QualType T = getDeclUsageType(SemaRef.Context, ND);
1159 if (T.isNull())
1160 return false;
1161
1162 T = SemaRef.Context.getBaseElementType(T);
1163 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1164 T->isObjCIdType() ||
1165 (SemaRef.getLangOptions().CPlusPlus && T->isRecordType());
1166}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001167
Douglas Gregor52779fb2010-09-23 23:01:17 +00001168bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1169 return false;
1170}
1171
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001172/// \rief Determines whether the given declaration is an Objective-C
1173/// instance variable.
1174bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1175 return isa<ObjCIvarDecl>(ND);
1176}
1177
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001178namespace {
1179 /// \brief Visible declaration consumer that adds a code-completion result
1180 /// for each visible declaration.
1181 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1182 ResultBuilder &Results;
1183 DeclContext *CurContext;
1184
1185 public:
1186 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1187 : Results(Results), CurContext(CurContext) { }
1188
Erik Verbruggend1205962011-10-06 07:27:49 +00001189 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1190 bool InBaseClass) {
1191 bool Accessible = true;
Douglas Gregor17015ef2011-11-03 16:51:37 +00001192 if (Ctx)
1193 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1194
Erik Verbruggend1205962011-10-06 07:27:49 +00001195 ResultBuilder::Result Result(ND, 0, false, Accessible);
1196 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001197 }
1198 };
1199}
1200
Douglas Gregor86d9a522009-09-21 16:56:56 +00001201/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001202static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001203 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001204 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001205 Results.AddResult(Result("short", CCP_Type));
1206 Results.AddResult(Result("long", CCP_Type));
1207 Results.AddResult(Result("signed", CCP_Type));
1208 Results.AddResult(Result("unsigned", CCP_Type));
1209 Results.AddResult(Result("void", CCP_Type));
1210 Results.AddResult(Result("char", CCP_Type));
1211 Results.AddResult(Result("int", CCP_Type));
1212 Results.AddResult(Result("float", CCP_Type));
1213 Results.AddResult(Result("double", CCP_Type));
1214 Results.AddResult(Result("enum", CCP_Type));
1215 Results.AddResult(Result("struct", CCP_Type));
1216 Results.AddResult(Result("union", CCP_Type));
1217 Results.AddResult(Result("const", CCP_Type));
1218 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001219
Douglas Gregor86d9a522009-09-21 16:56:56 +00001220 if (LangOpts.C99) {
1221 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001222 Results.AddResult(Result("_Complex", CCP_Type));
1223 Results.AddResult(Result("_Imaginary", CCP_Type));
1224 Results.AddResult(Result("_Bool", CCP_Type));
1225 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001226 }
1227
Douglas Gregor218937c2011-02-01 19:23:04 +00001228 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001229 if (LangOpts.CPlusPlus) {
1230 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001231 Results.AddResult(Result("bool", CCP_Type +
1232 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001233 Results.AddResult(Result("class", CCP_Type));
1234 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001235
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001236 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001237 Builder.AddTypedTextChunk("typename");
1238 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1239 Builder.AddPlaceholderChunk("qualifier");
1240 Builder.AddTextChunk("::");
1241 Builder.AddPlaceholderChunk("name");
1242 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001243
Douglas Gregor86d9a522009-09-21 16:56:56 +00001244 if (LangOpts.CPlusPlus0x) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001245 Results.AddResult(Result("auto", CCP_Type));
1246 Results.AddResult(Result("char16_t", CCP_Type));
1247 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001248
Douglas Gregor218937c2011-02-01 19:23:04 +00001249 Builder.AddTypedTextChunk("decltype");
1250 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1251 Builder.AddPlaceholderChunk("expression");
1252 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1253 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001254 }
1255 }
1256
1257 // GNU extensions
1258 if (LangOpts.GNUMode) {
1259 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001260 // Results.AddResult(Result("_Decimal32"));
1261 // Results.AddResult(Result("_Decimal64"));
1262 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001263
Douglas Gregor218937c2011-02-01 19:23:04 +00001264 Builder.AddTypedTextChunk("typeof");
1265 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1266 Builder.AddPlaceholderChunk("expression");
1267 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001268
Douglas Gregor218937c2011-02-01 19:23:04 +00001269 Builder.AddTypedTextChunk("typeof");
1270 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1271 Builder.AddPlaceholderChunk("type");
1272 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1273 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001274 }
1275}
1276
John McCallf312b1e2010-08-26 23:41:50 +00001277static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001278 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001279 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001280 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001281 // Note: we don't suggest either "auto" or "register", because both
1282 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1283 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001284 Results.AddResult(Result("extern"));
1285 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001286}
1287
John McCallf312b1e2010-08-26 23:41:50 +00001288static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001289 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001290 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001291 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001292 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001293 case Sema::PCC_Class:
1294 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001295 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001296 Results.AddResult(Result("explicit"));
1297 Results.AddResult(Result("friend"));
1298 Results.AddResult(Result("mutable"));
1299 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001300 }
1301 // Fall through
1302
John McCallf312b1e2010-08-26 23:41:50 +00001303 case Sema::PCC_ObjCInterface:
1304 case Sema::PCC_ObjCImplementation:
1305 case Sema::PCC_Namespace:
1306 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001307 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001308 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001309 break;
1310
John McCallf312b1e2010-08-26 23:41:50 +00001311 case Sema::PCC_ObjCInstanceVariableList:
1312 case Sema::PCC_Expression:
1313 case Sema::PCC_Statement:
1314 case Sema::PCC_ForInit:
1315 case Sema::PCC_Condition:
1316 case Sema::PCC_RecoveryInFunction:
1317 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001318 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001319 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001320 break;
1321 }
1322}
1323
Douglas Gregorbca403c2010-01-13 23:51:12 +00001324static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1325static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1326static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001327 ResultBuilder &Results,
1328 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001329static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001330 ResultBuilder &Results,
1331 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001332static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001333 ResultBuilder &Results,
1334 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001335static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001336
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001337static void AddTypedefResult(ResultBuilder &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001338 CodeCompletionBuilder Builder(Results.getAllocator());
1339 Builder.AddTypedTextChunk("typedef");
1340 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1341 Builder.AddPlaceholderChunk("type");
1342 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1343 Builder.AddPlaceholderChunk("name");
1344 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001345}
1346
John McCallf312b1e2010-08-26 23:41:50 +00001347static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001348 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001349 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001350 case Sema::PCC_Namespace:
1351 case Sema::PCC_Class:
1352 case Sema::PCC_ObjCInstanceVariableList:
1353 case Sema::PCC_Template:
1354 case Sema::PCC_MemberTemplate:
1355 case Sema::PCC_Statement:
1356 case Sema::PCC_RecoveryInFunction:
1357 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001358 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001359 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001360 return true;
1361
John McCallf312b1e2010-08-26 23:41:50 +00001362 case Sema::PCC_Expression:
1363 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001364 return LangOpts.CPlusPlus;
1365
1366 case Sema::PCC_ObjCInterface:
1367 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001368 return false;
1369
John McCallf312b1e2010-08-26 23:41:50 +00001370 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001371 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001372 }
David Blaikie7530c032012-01-17 06:56:22 +00001373
1374 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001375}
1376
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001377static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1378 const Preprocessor &PP) {
1379 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001380 Policy.AnonymousTagLocations = false;
1381 Policy.SuppressStrongLifetime = true;
Douglas Gregor25270b62011-11-03 00:16:13 +00001382 Policy.SuppressUnwrittenScope = true;
Douglas Gregor8ca72082011-10-18 21:20:17 +00001383 return Policy;
1384}
1385
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001386/// \brief Retrieve a printing policy suitable for code completion.
1387static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1388 return getCompletionPrintingPolicy(S.Context, S.PP);
1389}
1390
Douglas Gregor8ca72082011-10-18 21:20:17 +00001391/// \brief Retrieve the string representation of the given type as a string
1392/// that has the appropriate lifetime for code completion.
1393///
1394/// This routine provides a fast path where we provide constant strings for
1395/// common type names.
1396static const char *GetCompletionTypeString(QualType T,
1397 ASTContext &Context,
1398 const PrintingPolicy &Policy,
1399 CodeCompletionAllocator &Allocator) {
1400 if (!T.getLocalQualifiers()) {
1401 // Built-in type names are constant strings.
1402 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
1403 return BT->getName(Policy);
1404
1405 // Anonymous tag types are constant strings.
1406 if (const TagType *TagT = dyn_cast<TagType>(T))
1407 if (TagDecl *Tag = TagT->getDecl())
1408 if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
1409 switch (Tag->getTagKind()) {
1410 case TTK_Struct: return "struct <anonymous>";
1411 case TTK_Class: return "class <anonymous>";
1412 case TTK_Union: return "union <anonymous>";
1413 case TTK_Enum: return "enum <anonymous>";
1414 }
1415 }
1416 }
1417
1418 // Slow path: format the type as a string.
1419 std::string Result;
1420 T.getAsStringInternal(Result, Policy);
1421 return Allocator.CopyString(Result);
1422}
1423
Douglas Gregor01dfea02010-01-10 23:08:15 +00001424/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001425static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001426 Scope *S,
1427 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001428 ResultBuilder &Results) {
Douglas Gregor8ca72082011-10-18 21:20:17 +00001429 CodeCompletionAllocator &Allocator = Results.getAllocator();
1430 CodeCompletionBuilder Builder(Allocator);
1431 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregor218937c2011-02-01 19:23:04 +00001432
John McCall0a2c5e22010-08-25 06:19:51 +00001433 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001434 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001435 case Sema::PCC_Namespace:
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001436 if (SemaRef.getLangOptions().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001437 if (Results.includeCodePatterns()) {
1438 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001439 Builder.AddTypedTextChunk("namespace");
1440 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1441 Builder.AddPlaceholderChunk("identifier");
1442 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1443 Builder.AddPlaceholderChunk("declarations");
1444 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1445 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1446 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001447 }
1448
Douglas Gregor01dfea02010-01-10 23:08:15 +00001449 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001450 Builder.AddTypedTextChunk("namespace");
1451 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1452 Builder.AddPlaceholderChunk("name");
1453 Builder.AddChunk(CodeCompletionString::CK_Equal);
1454 Builder.AddPlaceholderChunk("namespace");
1455 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001456
1457 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001458 Builder.AddTypedTextChunk("using");
1459 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1460 Builder.AddTextChunk("namespace");
1461 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1462 Builder.AddPlaceholderChunk("identifier");
1463 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001464
1465 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001466 Builder.AddTypedTextChunk("asm");
1467 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1468 Builder.AddPlaceholderChunk("string-literal");
1469 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1470 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001471
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001472 if (Results.includeCodePatterns()) {
1473 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001474 Builder.AddTypedTextChunk("template");
1475 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1476 Builder.AddPlaceholderChunk("declaration");
1477 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001478 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001479 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001480
1481 if (SemaRef.getLangOptions().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001482 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001483
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001484 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001485 // Fall through
1486
John McCallf312b1e2010-08-26 23:41:50 +00001487 case Sema::PCC_Class:
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001488 if (SemaRef.getLangOptions().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001489 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001490 Builder.AddTypedTextChunk("using");
1491 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1492 Builder.AddPlaceholderChunk("qualifier");
1493 Builder.AddTextChunk("::");
1494 Builder.AddPlaceholderChunk("name");
1495 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001496
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001497 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001498 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001499 Builder.AddTypedTextChunk("using");
1500 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1501 Builder.AddTextChunk("typename");
1502 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1503 Builder.AddPlaceholderChunk("qualifier");
1504 Builder.AddTextChunk("::");
1505 Builder.AddPlaceholderChunk("name");
1506 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001507 }
1508
John McCallf312b1e2010-08-26 23:41:50 +00001509 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001510 AddTypedefResult(Results);
1511
Douglas Gregor01dfea02010-01-10 23:08:15 +00001512 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001513 Builder.AddTypedTextChunk("public");
1514 Builder.AddChunk(CodeCompletionString::CK_Colon);
1515 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001516
1517 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001518 Builder.AddTypedTextChunk("protected");
1519 Builder.AddChunk(CodeCompletionString::CK_Colon);
1520 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001521
1522 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001523 Builder.AddTypedTextChunk("private");
1524 Builder.AddChunk(CodeCompletionString::CK_Colon);
1525 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001526 }
1527 }
1528 // Fall through
1529
John McCallf312b1e2010-08-26 23:41:50 +00001530 case Sema::PCC_Template:
1531 case Sema::PCC_MemberTemplate:
Douglas Gregord8e8a582010-05-25 21:41:55 +00001532 if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001533 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001534 Builder.AddTypedTextChunk("template");
1535 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1536 Builder.AddPlaceholderChunk("parameters");
1537 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1538 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001539 }
1540
Douglas Gregorbca403c2010-01-13 23:51:12 +00001541 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1542 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001543 break;
1544
John McCallf312b1e2010-08-26 23:41:50 +00001545 case Sema::PCC_ObjCInterface:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001546 AddObjCInterfaceResults(SemaRef.getLangOptions(), Results, true);
1547 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1548 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001549 break;
1550
John McCallf312b1e2010-08-26 23:41:50 +00001551 case Sema::PCC_ObjCImplementation:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001552 AddObjCImplementationResults(SemaRef.getLangOptions(), Results, true);
1553 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1554 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001555 break;
1556
John McCallf312b1e2010-08-26 23:41:50 +00001557 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001558 AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001559 break;
1560
John McCallf312b1e2010-08-26 23:41:50 +00001561 case Sema::PCC_RecoveryInFunction:
1562 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001563 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001564
Douglas Gregorec3310a2011-04-12 02:47:21 +00001565 if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns() &&
1566 SemaRef.getLangOptions().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001567 Builder.AddTypedTextChunk("try");
1568 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1569 Builder.AddPlaceholderChunk("statements");
1570 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1571 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1572 Builder.AddTextChunk("catch");
1573 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1574 Builder.AddPlaceholderChunk("declaration");
1575 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1576 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1577 Builder.AddPlaceholderChunk("statements");
1578 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1579 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1580 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001581 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001582 if (SemaRef.getLangOptions().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001583 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001584
Douglas Gregord8e8a582010-05-25 21:41:55 +00001585 if (Results.includeCodePatterns()) {
1586 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001587 Builder.AddTypedTextChunk("if");
1588 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001589 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001590 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001591 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001592 Builder.AddPlaceholderChunk("expression");
1593 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1594 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1595 Builder.AddPlaceholderChunk("statements");
1596 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1597 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1598 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001599
Douglas Gregord8e8a582010-05-25 21:41:55 +00001600 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001601 Builder.AddTypedTextChunk("switch");
1602 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001603 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001604 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001605 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001606 Builder.AddPlaceholderChunk("expression");
1607 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1608 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1609 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1610 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1611 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001612 }
1613
Douglas Gregor01dfea02010-01-10 23:08:15 +00001614 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001615 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001616 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001617 Builder.AddTypedTextChunk("case");
1618 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1619 Builder.AddPlaceholderChunk("expression");
1620 Builder.AddChunk(CodeCompletionString::CK_Colon);
1621 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001622
1623 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001624 Builder.AddTypedTextChunk("default");
1625 Builder.AddChunk(CodeCompletionString::CK_Colon);
1626 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001627 }
1628
Douglas Gregord8e8a582010-05-25 21:41:55 +00001629 if (Results.includeCodePatterns()) {
1630 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001631 Builder.AddTypedTextChunk("while");
1632 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001633 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001634 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001635 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001636 Builder.AddPlaceholderChunk("expression");
1637 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1638 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1639 Builder.AddPlaceholderChunk("statements");
1640 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1641 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1642 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001643
1644 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001645 Builder.AddTypedTextChunk("do");
1646 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1647 Builder.AddPlaceholderChunk("statements");
1648 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1649 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1650 Builder.AddTextChunk("while");
1651 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1652 Builder.AddPlaceholderChunk("expression");
1653 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1654 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001655
Douglas Gregord8e8a582010-05-25 21:41:55 +00001656 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001657 Builder.AddTypedTextChunk("for");
1658 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001659 if (SemaRef.getLangOptions().CPlusPlus || SemaRef.getLangOptions().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001660 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001661 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001662 Builder.AddPlaceholderChunk("init-expression");
1663 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1664 Builder.AddPlaceholderChunk("condition");
1665 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1666 Builder.AddPlaceholderChunk("inc-expression");
1667 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1668 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1669 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1670 Builder.AddPlaceholderChunk("statements");
1671 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1672 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1673 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001674 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001675
1676 if (S->getContinueParent()) {
1677 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001678 Builder.AddTypedTextChunk("continue");
1679 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001680 }
1681
1682 if (S->getBreakParent()) {
1683 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001684 Builder.AddTypedTextChunk("break");
1685 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001686 }
1687
1688 // "return expression ;" or "return ;", depending on whether we
1689 // know the function is void or not.
1690 bool isVoid = false;
1691 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1692 isVoid = Function->getResultType()->isVoidType();
1693 else if (ObjCMethodDecl *Method
1694 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1695 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001696 else if (SemaRef.getCurBlock() &&
1697 !SemaRef.getCurBlock()->ReturnType.isNull())
1698 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001699 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001700 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001701 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1702 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001703 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001704 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001705
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001706 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001707 Builder.AddTypedTextChunk("goto");
1708 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1709 Builder.AddPlaceholderChunk("label");
1710 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001711
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001712 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001713 Builder.AddTypedTextChunk("using");
1714 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1715 Builder.AddTextChunk("namespace");
1716 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1717 Builder.AddPlaceholderChunk("identifier");
1718 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001719 }
1720
1721 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001722 case Sema::PCC_ForInit:
1723 case Sema::PCC_Condition:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001724 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001725 // Fall through: conditions and statements can have expressions.
1726
Douglas Gregor02688102010-09-14 23:59:36 +00001727 case Sema::PCC_ParenthesizedExpression:
John McCallf85e1932011-06-15 23:02:42 +00001728 if (SemaRef.getLangOptions().ObjCAutoRefCount &&
1729 CCC == Sema::PCC_ParenthesizedExpression) {
1730 // (__bridge <type>)<expression>
1731 Builder.AddTypedTextChunk("__bridge");
1732 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1733 Builder.AddPlaceholderChunk("type");
1734 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1735 Builder.AddPlaceholderChunk("expression");
1736 Results.AddResult(Result(Builder.TakeString()));
1737
1738 // (__bridge_transfer <Objective-C type>)<expression>
1739 Builder.AddTypedTextChunk("__bridge_transfer");
1740 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1741 Builder.AddPlaceholderChunk("Objective-C type");
1742 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1743 Builder.AddPlaceholderChunk("expression");
1744 Results.AddResult(Result(Builder.TakeString()));
1745
1746 // (__bridge_retained <CF type>)<expression>
1747 Builder.AddTypedTextChunk("__bridge_retained");
1748 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1749 Builder.AddPlaceholderChunk("CF type");
1750 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1751 Builder.AddPlaceholderChunk("expression");
1752 Results.AddResult(Result(Builder.TakeString()));
1753 }
1754 // Fall through
1755
John McCallf312b1e2010-08-26 23:41:50 +00001756 case Sema::PCC_Expression: {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001757 if (SemaRef.getLangOptions().CPlusPlus) {
1758 // 'this', if we're in a non-static member function.
Eli Friedman72899c32012-01-07 04:59:52 +00001759 QualType ThisTy = SemaRef.getCurrentThisType();
Douglas Gregor8ca72082011-10-18 21:20:17 +00001760 if (!ThisTy.isNull()) {
1761 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1762 SemaRef.Context,
1763 Policy,
1764 Allocator));
1765 Builder.AddTypedTextChunk("this");
1766 Results.AddResult(Result(Builder.TakeString()));
1767 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001768
Douglas Gregor8ca72082011-10-18 21:20:17 +00001769 // true
1770 Builder.AddResultTypeChunk("bool");
1771 Builder.AddTypedTextChunk("true");
1772 Results.AddResult(Result(Builder.TakeString()));
1773
1774 // false
1775 Builder.AddResultTypeChunk("bool");
1776 Builder.AddTypedTextChunk("false");
1777 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001778
Douglas Gregorec3310a2011-04-12 02:47:21 +00001779 if (SemaRef.getLangOptions().RTTI) {
1780 // dynamic_cast < type-id > ( expression )
1781 Builder.AddTypedTextChunk("dynamic_cast");
1782 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1783 Builder.AddPlaceholderChunk("type");
1784 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1785 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1786 Builder.AddPlaceholderChunk("expression");
1787 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1788 Results.AddResult(Result(Builder.TakeString()));
1789 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001790
1791 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001792 Builder.AddTypedTextChunk("static_cast");
1793 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1794 Builder.AddPlaceholderChunk("type");
1795 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1796 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1797 Builder.AddPlaceholderChunk("expression");
1798 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1799 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001800
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001801 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001802 Builder.AddTypedTextChunk("reinterpret_cast");
1803 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1804 Builder.AddPlaceholderChunk("type");
1805 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1806 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1807 Builder.AddPlaceholderChunk("expression");
1808 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1809 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001810
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001811 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001812 Builder.AddTypedTextChunk("const_cast");
1813 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1814 Builder.AddPlaceholderChunk("type");
1815 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1816 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1817 Builder.AddPlaceholderChunk("expression");
1818 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1819 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001820
Douglas Gregorec3310a2011-04-12 02:47:21 +00001821 if (SemaRef.getLangOptions().RTTI) {
1822 // typeid ( expression-or-type )
Douglas Gregor8ca72082011-10-18 21:20:17 +00001823 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001824 Builder.AddTypedTextChunk("typeid");
1825 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1826 Builder.AddPlaceholderChunk("expression-or-type");
1827 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1828 Results.AddResult(Result(Builder.TakeString()));
1829 }
1830
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001831 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001832 Builder.AddTypedTextChunk("new");
1833 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1834 Builder.AddPlaceholderChunk("type");
1835 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1836 Builder.AddPlaceholderChunk("expressions");
1837 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1838 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001839
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001840 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001841 Builder.AddTypedTextChunk("new");
1842 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1843 Builder.AddPlaceholderChunk("type");
1844 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1845 Builder.AddPlaceholderChunk("size");
1846 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1847 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1848 Builder.AddPlaceholderChunk("expressions");
1849 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1850 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001851
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001852 // delete expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001853 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001854 Builder.AddTypedTextChunk("delete");
1855 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1856 Builder.AddPlaceholderChunk("expression");
1857 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001858
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001859 // delete [] expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001860 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001861 Builder.AddTypedTextChunk("delete");
1862 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1863 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1864 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1865 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1866 Builder.AddPlaceholderChunk("expression");
1867 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001868
Douglas Gregorec3310a2011-04-12 02:47:21 +00001869 if (SemaRef.getLangOptions().CXXExceptions) {
1870 // throw expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001871 Builder.AddResultTypeChunk("void");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001872 Builder.AddTypedTextChunk("throw");
1873 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1874 Builder.AddPlaceholderChunk("expression");
1875 Results.AddResult(Result(Builder.TakeString()));
1876 }
Douglas Gregora50216c2011-10-18 16:29:03 +00001877
Douglas Gregor12e13132010-05-26 22:00:08 +00001878 // FIXME: Rethrow?
Douglas Gregora50216c2011-10-18 16:29:03 +00001879
1880 if (SemaRef.getLangOptions().CPlusPlus0x) {
1881 // nullptr
Douglas Gregor8ca72082011-10-18 21:20:17 +00001882 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001883 Builder.AddTypedTextChunk("nullptr");
1884 Results.AddResult(Result(Builder.TakeString()));
1885
1886 // alignof
Douglas Gregor8ca72082011-10-18 21:20:17 +00001887 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001888 Builder.AddTypedTextChunk("alignof");
1889 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1890 Builder.AddPlaceholderChunk("type");
1891 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1892 Results.AddResult(Result(Builder.TakeString()));
1893
1894 // noexcept
Douglas Gregor8ca72082011-10-18 21:20:17 +00001895 Builder.AddResultTypeChunk("bool");
Douglas Gregora50216c2011-10-18 16:29:03 +00001896 Builder.AddTypedTextChunk("noexcept");
1897 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1898 Builder.AddPlaceholderChunk("expression");
1899 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1900 Results.AddResult(Result(Builder.TakeString()));
1901
1902 // sizeof... expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001903 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001904 Builder.AddTypedTextChunk("sizeof...");
1905 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1906 Builder.AddPlaceholderChunk("parameter-pack");
1907 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1908 Results.AddResult(Result(Builder.TakeString()));
1909 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001910 }
1911
1912 if (SemaRef.getLangOptions().ObjC1) {
1913 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001914 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1915 // The interface can be NULL.
1916 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregor8ca72082011-10-18 21:20:17 +00001917 if (ID->getSuperClass()) {
1918 std::string SuperType;
1919 SuperType = ID->getSuperClass()->getNameAsString();
1920 if (Method->isInstanceMethod())
1921 SuperType += " *";
1922
1923 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1924 Builder.AddTypedTextChunk("super");
1925 Results.AddResult(Result(Builder.TakeString()));
1926 }
Ted Kremenek681e2562010-05-31 21:43:10 +00001927 }
1928
Douglas Gregorbca403c2010-01-13 23:51:12 +00001929 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001930 }
1931
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001932 // sizeof expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001933 Builder.AddResultTypeChunk("size_t");
Douglas Gregor218937c2011-02-01 19:23:04 +00001934 Builder.AddTypedTextChunk("sizeof");
1935 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1936 Builder.AddPlaceholderChunk("expression-or-type");
1937 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1938 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001939 break;
1940 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001941
John McCallf312b1e2010-08-26 23:41:50 +00001942 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001943 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00001944 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001945 }
1946
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001947 if (WantTypesInContext(CCC, SemaRef.getLangOptions()))
1948 AddTypeSpecifierResults(SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001949
John McCallf312b1e2010-08-26 23:41:50 +00001950 if (SemaRef.getLangOptions().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00001951 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001952}
1953
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001954/// \brief If the given declaration has an associated type, add it as a result
1955/// type chunk.
1956static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00001957 const PrintingPolicy &Policy,
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001958 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00001959 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001960 if (!ND)
1961 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00001962
1963 // Skip constructors and conversion functions, which have their return types
1964 // built into their names.
1965 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
1966 return;
1967
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001968 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00001969 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001970 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
1971 T = Function->getResultType();
1972 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
1973 T = Method->getResultType();
1974 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
1975 T = FunTmpl->getTemplatedDecl()->getResultType();
1976 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
1977 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
1978 else if (isa<UnresolvedUsingValueDecl>(ND)) {
1979 /* Do nothing: ignore unresolved using declarations*/
John McCallf85e1932011-06-15 23:02:42 +00001980 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001981 T = Value->getType();
John McCallf85e1932011-06-15 23:02:42 +00001982 } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001983 T = Property->getType();
1984
1985 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
1986 return;
1987
Douglas Gregor8987b232011-09-27 23:30:47 +00001988 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00001989 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001990}
1991
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001992static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00001993 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001994 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
1995 if (Sentinel->getSentinel() == 0) {
1996 if (Context.getLangOptions().ObjC1 &&
1997 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00001998 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001999 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002000 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002001 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002002 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002003 }
2004}
2005
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002006static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2007 std::string Result;
2008 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002009 Result += "in ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002010 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002011 Result += "inout ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002012 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002013 Result += "out ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002014 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002015 Result += "bycopy ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002016 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002017 Result += "byref ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002018 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002019 Result += "oneway ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002020 return Result;
2021}
2022
Douglas Gregor83482d12010-08-24 16:15:59 +00002023static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002024 const PrintingPolicy &Policy,
Douglas Gregoraba48082010-08-29 19:47:46 +00002025 ParmVarDecl *Param,
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002026 bool SuppressName = false,
2027 bool SuppressBlock = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00002028 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2029 if (Param->getType()->isDependentType() ||
2030 !Param->getType()->isBlockPointerType()) {
2031 // The argument for a dependent or non-block parameter is a placeholder
2032 // containing that parameter's type.
2033 std::string Result;
2034
Douglas Gregoraba48082010-08-29 19:47:46 +00002035 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002036 Result = Param->getIdentifier()->getName();
2037
John McCallf85e1932011-06-15 23:02:42 +00002038 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002039
2040 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002041 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2042 + Result + ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00002043 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002044 Result += Param->getIdentifier()->getName();
2045 }
2046 return Result;
2047 }
2048
2049 // The argument for a block pointer parameter is a block literal with
2050 // the appropriate type.
Douglas Gregor830072c2011-02-15 22:37:09 +00002051 FunctionTypeLoc *Block = 0;
2052 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregor83482d12010-08-24 16:15:59 +00002053 TypeLoc TL;
2054 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2055 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2056 while (true) {
2057 // Look through typedefs.
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002058 if (!SuppressBlock) {
2059 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2060 if (TypeSourceInfo *InnerTSInfo
2061 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2062 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2063 continue;
2064 }
2065 }
2066
2067 // Look through qualified types
2068 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2069 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregor83482d12010-08-24 16:15:59 +00002070 continue;
2071 }
2072 }
2073
Douglas Gregor83482d12010-08-24 16:15:59 +00002074 // Try to get the function prototype behind the block pointer type,
2075 // then we're done.
2076 if (BlockPointerTypeLoc *BlockPtr
2077 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00002078 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor830072c2011-02-15 22:37:09 +00002079 Block = dyn_cast<FunctionTypeLoc>(&TL);
2080 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregor83482d12010-08-24 16:15:59 +00002081 }
2082 break;
2083 }
2084 }
2085
2086 if (!Block) {
2087 // We were unable to find a FunctionProtoTypeLoc with parameter names
2088 // for the block; just use the parameter type as a placeholder.
2089 std::string Result;
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002090 if (!ObjCMethodParam && Param->getIdentifier())
2091 Result = Param->getIdentifier()->getName();
2092
John McCallf85e1932011-06-15 23:02:42 +00002093 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002094
2095 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002096 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2097 + Result + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002098 if (Param->getIdentifier())
2099 Result += Param->getIdentifier()->getName();
2100 }
2101
2102 return Result;
2103 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002104
Douglas Gregor83482d12010-08-24 16:15:59 +00002105 // We have the function prototype behind the block pointer type, as it was
2106 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00002107 std::string Result;
2108 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002109 if (!ResultType->isVoidType() || SuppressBlock)
John McCallf85e1932011-06-15 23:02:42 +00002110 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002111
2112 // Format the parameter list.
2113 std::string Params;
Douglas Gregor830072c2011-02-15 22:37:09 +00002114 if (!BlockProto || Block->getNumArgs() == 0) {
2115 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002116 Params = "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00002117 else
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002118 Params = "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00002119 } else {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002120 Params += "(";
Douglas Gregor38276252010-09-08 22:47:51 +00002121 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2122 if (I)
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002123 Params += ", ";
2124 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2125 /*SuppressName=*/false,
2126 /*SuppressBlock=*/true);
Douglas Gregor38276252010-09-08 22:47:51 +00002127
Douglas Gregor830072c2011-02-15 22:37:09 +00002128 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002129 Params += ", ...";
Douglas Gregor38276252010-09-08 22:47:51 +00002130 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002131 Params += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00002132 }
Douglas Gregor38276252010-09-08 22:47:51 +00002133
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002134 if (SuppressBlock) {
2135 // Format as a parameter.
2136 Result = Result + " (^";
2137 if (Param->getIdentifier())
2138 Result += Param->getIdentifier()->getName();
2139 Result += ")";
2140 Result += Params;
2141 } else {
2142 // Format as a block literal argument.
2143 Result = '^' + Result;
2144 Result += Params;
2145
2146 if (Param->getIdentifier())
2147 Result += Param->getIdentifier()->getName();
2148 }
2149
Douglas Gregor83482d12010-08-24 16:15:59 +00002150 return Result;
2151}
2152
Douglas Gregor86d9a522009-09-21 16:56:56 +00002153/// \brief Add function parameter chunks to the given code completion string.
2154static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002155 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002156 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00002157 CodeCompletionBuilder &Result,
2158 unsigned Start = 0,
2159 bool InOptional = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002160 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00002161 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002162
Douglas Gregor218937c2011-02-01 19:23:04 +00002163 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002164 ParmVarDecl *Param = Function->getParamDecl(P);
2165
Douglas Gregor218937c2011-02-01 19:23:04 +00002166 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002167 // When we see an optional default argument, put that argument and
2168 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002169 CodeCompletionBuilder Opt(Result.getAllocator());
2170 if (!FirstParameter)
2171 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor8987b232011-09-27 23:30:47 +00002172 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregor218937c2011-02-01 19:23:04 +00002173 Result.AddOptionalChunk(Opt.TakeString());
2174 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002175 }
2176
Douglas Gregor218937c2011-02-01 19:23:04 +00002177 if (FirstParameter)
2178 FirstParameter = false;
2179 else
2180 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
2181
2182 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002183
2184 // Format the placeholder string.
Douglas Gregor8987b232011-09-27 23:30:47 +00002185 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2186 Param);
Douglas Gregor83482d12010-08-24 16:15:59 +00002187
Douglas Gregore17794f2010-08-31 05:13:43 +00002188 if (Function->isVariadic() && P == N - 1)
2189 PlaceholderStr += ", ...";
2190
Douglas Gregor86d9a522009-09-21 16:56:56 +00002191 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002192 Result.AddPlaceholderChunk(
2193 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002194 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002195
2196 if (const FunctionProtoType *Proto
2197 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002198 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002199 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002200 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002201
Douglas Gregor218937c2011-02-01 19:23:04 +00002202 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002203 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002204}
2205
2206/// \brief Add template parameter chunks to the given code completion string.
2207static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002208 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002209 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002210 CodeCompletionBuilder &Result,
2211 unsigned MaxParameters = 0,
2212 unsigned Start = 0,
2213 bool InDefaultArg = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002214 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002215 bool FirstParameter = true;
2216
2217 TemplateParameterList *Params = Template->getTemplateParameters();
2218 TemplateParameterList::iterator PEnd = Params->end();
2219 if (MaxParameters)
2220 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002221 for (TemplateParameterList::iterator P = Params->begin() + Start;
2222 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002223 bool HasDefaultArg = false;
2224 std::string PlaceholderStr;
2225 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2226 if (TTP->wasDeclaredWithTypename())
2227 PlaceholderStr = "typename";
2228 else
2229 PlaceholderStr = "class";
2230
2231 if (TTP->getIdentifier()) {
2232 PlaceholderStr += ' ';
2233 PlaceholderStr += TTP->getIdentifier()->getName();
2234 }
2235
2236 HasDefaultArg = TTP->hasDefaultArgument();
2237 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002238 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002239 if (NTTP->getIdentifier())
2240 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCallf85e1932011-06-15 23:02:42 +00002241 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002242 HasDefaultArg = NTTP->hasDefaultArgument();
2243 } else {
2244 assert(isa<TemplateTemplateParmDecl>(*P));
2245 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2246
2247 // Since putting the template argument list into the placeholder would
2248 // be very, very long, we just use an abbreviation.
2249 PlaceholderStr = "template<...> class";
2250 if (TTP->getIdentifier()) {
2251 PlaceholderStr += ' ';
2252 PlaceholderStr += TTP->getIdentifier()->getName();
2253 }
2254
2255 HasDefaultArg = TTP->hasDefaultArgument();
2256 }
2257
Douglas Gregor218937c2011-02-01 19:23:04 +00002258 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002259 // When we see an optional default argument, put that argument and
2260 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002261 CodeCompletionBuilder Opt(Result.getAllocator());
2262 if (!FirstParameter)
2263 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor8987b232011-09-27 23:30:47 +00002264 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregor218937c2011-02-01 19:23:04 +00002265 P - Params->begin(), true);
2266 Result.AddOptionalChunk(Opt.TakeString());
2267 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002268 }
2269
Douglas Gregor218937c2011-02-01 19:23:04 +00002270 InDefaultArg = false;
2271
Douglas Gregor86d9a522009-09-21 16:56:56 +00002272 if (FirstParameter)
2273 FirstParameter = false;
2274 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002275 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002276
2277 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002278 Result.AddPlaceholderChunk(
2279 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002280 }
2281}
2282
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002283/// \brief Add a qualifier to the given code-completion string, if the
2284/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002285static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002286AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002287 NestedNameSpecifier *Qualifier,
2288 bool QualifierIsInformative,
Douglas Gregor8987b232011-09-27 23:30:47 +00002289 ASTContext &Context,
2290 const PrintingPolicy &Policy) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002291 if (!Qualifier)
2292 return;
2293
2294 std::string PrintedNNS;
2295 {
2296 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor8987b232011-09-27 23:30:47 +00002297 Qualifier->print(OS, Policy);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002298 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002299 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002300 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002301 else
Douglas Gregordae68752011-02-01 22:57:45 +00002302 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002303}
2304
Douglas Gregor218937c2011-02-01 19:23:04 +00002305static void
2306AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2307 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002308 const FunctionProtoType *Proto
2309 = Function->getType()->getAs<FunctionProtoType>();
2310 if (!Proto || !Proto->getTypeQuals())
2311 return;
2312
Douglas Gregora63f6de2011-02-01 21:15:40 +00002313 // FIXME: Add ref-qualifier!
2314
2315 // Handle single qualifiers without copying
2316 if (Proto->getTypeQuals() == Qualifiers::Const) {
2317 Result.AddInformativeChunk(" const");
2318 return;
2319 }
2320
2321 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2322 Result.AddInformativeChunk(" volatile");
2323 return;
2324 }
2325
2326 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2327 Result.AddInformativeChunk(" restrict");
2328 return;
2329 }
2330
2331 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002332 std::string QualsStr;
2333 if (Proto->getTypeQuals() & Qualifiers::Const)
2334 QualsStr += " const";
2335 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2336 QualsStr += " volatile";
2337 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2338 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002339 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002340}
2341
Douglas Gregor6f942b22010-09-21 16:06:22 +00002342/// \brief Add the name of the given declaration
Douglas Gregor8987b232011-09-27 23:30:47 +00002343static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
2344 NamedDecl *ND, CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002345 typedef CodeCompletionString::Chunk Chunk;
2346
2347 DeclarationName Name = ND->getDeclName();
2348 if (!Name)
2349 return;
2350
2351 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002352 case DeclarationName::CXXOperatorName: {
2353 const char *OperatorName = 0;
2354 switch (Name.getCXXOverloadedOperator()) {
2355 case OO_None:
2356 case OO_Conditional:
2357 case NUM_OVERLOADED_OPERATORS:
2358 OperatorName = "operator";
2359 break;
2360
2361#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2362 case OO_##Name: OperatorName = "operator" Spelling; break;
2363#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2364#include "clang/Basic/OperatorKinds.def"
2365
2366 case OO_New: OperatorName = "operator new"; break;
2367 case OO_Delete: OperatorName = "operator delete"; break;
2368 case OO_Array_New: OperatorName = "operator new[]"; break;
2369 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2370 case OO_Call: OperatorName = "operator()"; break;
2371 case OO_Subscript: OperatorName = "operator[]"; break;
2372 }
2373 Result.AddTypedTextChunk(OperatorName);
2374 break;
2375 }
2376
Douglas Gregor6f942b22010-09-21 16:06:22 +00002377 case DeclarationName::Identifier:
2378 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002379 case DeclarationName::CXXDestructorName:
2380 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002381 Result.AddTypedTextChunk(
2382 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002383 break;
2384
2385 case DeclarationName::CXXUsingDirective:
2386 case DeclarationName::ObjCZeroArgSelector:
2387 case DeclarationName::ObjCOneArgSelector:
2388 case DeclarationName::ObjCMultiArgSelector:
2389 break;
2390
2391 case DeclarationName::CXXConstructorName: {
2392 CXXRecordDecl *Record = 0;
2393 QualType Ty = Name.getCXXNameType();
2394 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2395 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2396 else if (const InjectedClassNameType *InjectedTy
2397 = Ty->getAs<InjectedClassNameType>())
2398 Record = InjectedTy->getDecl();
2399 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002400 Result.AddTypedTextChunk(
2401 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002402 break;
2403 }
2404
Douglas Gregordae68752011-02-01 22:57:45 +00002405 Result.AddTypedTextChunk(
2406 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002407 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002408 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor8987b232011-09-27 23:30:47 +00002409 AddTemplateParameterChunks(Context, Policy, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002410 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002411 }
2412 break;
2413 }
2414 }
2415}
2416
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002417CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
2418 CodeCompletionAllocator &Allocator) {
2419 return CreateCodeCompletionString(S.Context, S.PP, Allocator);
2420}
2421
Douglas Gregor86d9a522009-09-21 16:56:56 +00002422/// \brief If possible, create a new code completion string for the given
2423/// result.
2424///
2425/// \returns Either a new, heap-allocated code completion string describing
2426/// how to use this result, or NULL to indicate that the string or name of the
2427/// result is all that is needed.
2428CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002429CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2430 Preprocessor &PP,
Douglas Gregordae68752011-02-01 22:57:45 +00002431 CodeCompletionAllocator &Allocator) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002432 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00002433 CodeCompletionBuilder Result(Allocator, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002434
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002435 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002436 if (Kind == RK_Pattern) {
2437 Pattern->Priority = Priority;
2438 Pattern->Availability = Availability;
2439 return Pattern;
2440 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002441
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002442 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002443 Result.AddTypedTextChunk(Keyword);
2444 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002445 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002446
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002447 if (Kind == RK_Macro) {
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002448 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002449 assert(MI && "Not a macro?");
2450
Douglas Gregordae68752011-02-01 22:57:45 +00002451 Result.AddTypedTextChunk(
2452 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002453
2454 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002455 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002456
2457 // Format a function-like macro with placeholders for the arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00002458 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregore4244702011-07-30 08:17:44 +00002459 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002460
2461 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2462 if (MI->isC99Varargs()) {
2463 --AEnd;
2464
2465 if (A == AEnd) {
2466 Result.AddPlaceholderChunk("...");
2467 }
Douglas Gregore4244702011-07-30 08:17:44 +00002468 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002469
Douglas Gregore4244702011-07-30 08:17:44 +00002470 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002471 if (A != MI->arg_begin())
Douglas Gregor218937c2011-02-01 19:23:04 +00002472 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002473
2474 if (MI->isVariadic() && (A+1) == AEnd) {
2475 llvm::SmallString<32> Arg = (*A)->getName();
2476 if (MI->isC99Varargs())
2477 Arg += ", ...";
2478 else
2479 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002480 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002481 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002482 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002483
2484 // Non-variadic macros are simple.
2485 Result.AddPlaceholderChunk(
2486 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002487 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002488 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2489 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002490 }
2491
Douglas Gregord8e8a582010-05-25 21:41:55 +00002492 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002493 NamedDecl *ND = Declaration;
2494
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002495 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002496 Result.AddTypedTextChunk(
2497 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002498 Result.AddTextChunk("::");
2499 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002500 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002501
2502 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2503 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2504 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2505 }
2506 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002507
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002508 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002509
Douglas Gregor86d9a522009-09-21 16:56:56 +00002510 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002511 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002512 Ctx, Policy);
2513 AddTypedNameChunk(Ctx, Policy, ND, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002514 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002515 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002516 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002517 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002518 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002519 }
2520
2521 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002522 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002523 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002524 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002525 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002526
Douglas Gregor86d9a522009-09-21 16:56:56 +00002527 // Figure out which template parameters are deduced (or have default
2528 // arguments).
Chris Lattner5f9e2722011-07-23 10:55:15 +00002529 SmallVector<bool, 16> Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002530 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002531 unsigned LastDeducibleArgument;
2532 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2533 --LastDeducibleArgument) {
2534 if (!Deduced[LastDeducibleArgument - 1]) {
2535 // C++0x: Figure out if the template argument has a default. If so,
2536 // the user doesn't need to type this argument.
2537 // FIXME: We need to abstract template parameters better!
2538 bool HasDefaultArg = false;
2539 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002540 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002541 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2542 HasDefaultArg = TTP->hasDefaultArgument();
2543 else if (NonTypeTemplateParmDecl *NTTP
2544 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2545 HasDefaultArg = NTTP->hasDefaultArgument();
2546 else {
2547 assert(isa<TemplateTemplateParmDecl>(Param));
2548 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002549 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002550 }
2551
2552 if (!HasDefaultArg)
2553 break;
2554 }
2555 }
2556
2557 if (LastDeducibleArgument) {
2558 // Some of the function template arguments cannot be deduced from a
2559 // function call, so we introduce an explicit template argument list
2560 // containing all of the arguments up to the first deducible argument.
Douglas Gregor218937c2011-02-01 19:23:04 +00002561 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002562 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002563 LastDeducibleArgument);
Douglas Gregor218937c2011-02-01 19:23:04 +00002564 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002565 }
2566
2567 // Add the function parameters
Douglas Gregor218937c2011-02-01 19:23:04 +00002568 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002569 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002570 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002571 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002572 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002573 }
2574
2575 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002576 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002577 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002578 Result.AddTypedTextChunk(
2579 Result.getAllocator().CopyString(Template->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002580 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002581 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002582 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
2583 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002584 }
2585
Douglas Gregor9630eb62009-11-17 16:44:22 +00002586 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002587 Selector Sel = Method->getSelector();
2588 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002589 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002590 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002591 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002592 }
2593
Douglas Gregor813d8342011-02-18 22:29:55 +00002594 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002595 SelName += ':';
2596 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002597 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002598 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002599 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002600
2601 // If there is only one parameter, and we're past it, add an empty
2602 // typed-text chunk since there is nothing to type.
2603 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002604 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002605 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002606 unsigned Idx = 0;
2607 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2608 PEnd = Method->param_end();
2609 P != PEnd; (void)++P, ++Idx) {
2610 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002611 std::string Keyword;
2612 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002613 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002614 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002615 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002616 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002617 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002618 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002619 else
Douglas Gregordae68752011-02-01 22:57:45 +00002620 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002621 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002622
2623 // If we're before the starting parameter, skip the placeholder.
2624 if (Idx < StartParameter)
2625 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002626
2627 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002628
2629 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002630 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002631 else {
John McCallf85e1932011-06-15 23:02:42 +00002632 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002633 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2634 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002635 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002636 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002637 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002638 }
2639
Douglas Gregore17794f2010-08-31 05:13:43 +00002640 if (Method->isVariadic() && (P + 1) == PEnd)
2641 Arg += ", ...";
2642
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002643 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002644 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002645 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002646 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002647 else
Douglas Gregordae68752011-02-01 22:57:45 +00002648 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002649 }
2650
Douglas Gregor2a17af02009-12-23 00:21:46 +00002651 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002652 if (Method->param_size() == 0) {
2653 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002654 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002655 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002656 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002657 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002658 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002659 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002660
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002661 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002662 }
2663
Douglas Gregor218937c2011-02-01 19:23:04 +00002664 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002665 }
2666
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002667 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002668 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002669 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002670
Douglas Gregordae68752011-02-01 22:57:45 +00002671 Result.AddTypedTextChunk(
2672 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002673 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002674}
2675
Douglas Gregor86d802e2009-09-23 00:34:09 +00002676CodeCompletionString *
2677CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2678 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002679 Sema &S,
Douglas Gregordae68752011-02-01 22:57:45 +00002680 CodeCompletionAllocator &Allocator) const {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002681 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor8987b232011-09-27 23:30:47 +00002682 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002683
Douglas Gregor218937c2011-02-01 19:23:04 +00002684 // FIXME: Set priority, availability appropriately.
2685 CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002686 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002687 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002688 const FunctionProtoType *Proto
2689 = dyn_cast<FunctionProtoType>(getFunctionType());
2690 if (!FDecl && !Proto) {
2691 // Function without a prototype. Just give the return type and a
2692 // highlighted ellipsis.
2693 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002694 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002695 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002696 Result.getAllocator()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002697 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
2698 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
2699 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2700 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002701 }
2702
2703 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002704 Result.AddTextChunk(
2705 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002706 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002707 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002708 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002709 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002710
Douglas Gregor218937c2011-02-01 19:23:04 +00002711 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002712 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2713 for (unsigned I = 0; I != NumParams; ++I) {
2714 if (I)
Douglas Gregor218937c2011-02-01 19:23:04 +00002715 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002716
2717 std::string ArgString;
2718 QualType ArgType;
2719
2720 if (FDecl) {
2721 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2722 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2723 } else {
2724 ArgType = Proto->getArgType(I);
2725 }
2726
John McCallf85e1932011-06-15 23:02:42 +00002727 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002728
2729 if (I == CurrentArg)
Douglas Gregor218937c2011-02-01 19:23:04 +00002730 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter,
Douglas Gregordae68752011-02-01 22:57:45 +00002731 Result.getAllocator().CopyString(ArgString)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002732 else
Douglas Gregordae68752011-02-01 22:57:45 +00002733 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002734 }
2735
2736 if (Proto && Proto->isVariadic()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002737 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002738 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002739 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002740 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002741 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002742 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002743 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002744
Douglas Gregor218937c2011-02-01 19:23:04 +00002745 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002746}
2747
Chris Lattner5f9e2722011-07-23 10:55:15 +00002748unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002749 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002750 bool PreferredTypeIsPointer) {
2751 unsigned Priority = CCP_Macro;
2752
Douglas Gregorb05496d2010-09-20 21:11:48 +00002753 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2754 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2755 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002756 Priority = CCP_Constant;
2757 if (PreferredTypeIsPointer)
2758 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002759 }
2760 // Treat "YES", "NO", "true", and "false" as constants.
2761 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2762 MacroName.equals("true") || MacroName.equals("false"))
2763 Priority = CCP_Constant;
2764 // Treat "bool" as a type.
2765 else if (MacroName.equals("bool"))
2766 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2767
Douglas Gregor1827e102010-08-16 16:18:59 +00002768
2769 return Priority;
2770}
2771
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002772CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2773 if (!D)
2774 return CXCursor_UnexposedDecl;
2775
2776 switch (D->getKind()) {
2777 case Decl::Enum: return CXCursor_EnumDecl;
2778 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2779 case Decl::Field: return CXCursor_FieldDecl;
2780 case Decl::Function:
2781 return CXCursor_FunctionDecl;
2782 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2783 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002784 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002785
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002786 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002787 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2788 case Decl::ObjCMethod:
2789 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2790 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2791 case Decl::CXXMethod: return CXCursor_CXXMethod;
2792 case Decl::CXXConstructor: return CXCursor_Constructor;
2793 case Decl::CXXDestructor: return CXCursor_Destructor;
2794 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2795 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002796 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002797 case Decl::ParmVar: return CXCursor_ParmDecl;
2798 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002799 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002800 case Decl::Var: return CXCursor_VarDecl;
2801 case Decl::Namespace: return CXCursor_Namespace;
2802 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2803 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2804 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2805 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2806 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2807 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002808 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002809 case Decl::ClassTemplatePartialSpecialization:
2810 return CXCursor_ClassTemplatePartialSpecialization;
2811 case Decl::UsingDirective: return CXCursor_UsingDirective;
2812
2813 case Decl::Using:
2814 case Decl::UnresolvedUsingValue:
2815 case Decl::UnresolvedUsingTypename:
2816 return CXCursor_UsingDeclaration;
2817
Douglas Gregor352697a2011-06-03 23:08:58 +00002818 case Decl::ObjCPropertyImpl:
2819 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2820 case ObjCPropertyImplDecl::Dynamic:
2821 return CXCursor_ObjCDynamicDecl;
2822
2823 case ObjCPropertyImplDecl::Synthesize:
2824 return CXCursor_ObjCSynthesizeDecl;
2825 }
Douglas Gregor352697a2011-06-03 23:08:58 +00002826
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002827 default:
2828 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2829 switch (TD->getTagKind()) {
2830 case TTK_Struct: return CXCursor_StructDecl;
2831 case TTK_Class: return CXCursor_ClassDecl;
2832 case TTK_Union: return CXCursor_UnionDecl;
2833 case TTK_Enum: return CXCursor_EnumDecl;
2834 }
2835 }
2836 }
2837
2838 return CXCursor_UnexposedDecl;
2839}
2840
Douglas Gregor590c7d52010-07-08 20:55:51 +00002841static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2842 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002843 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002844
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002845 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002846
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002847 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2848 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002849 M != MEnd; ++M) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002850 Results.AddResult(Result(M->first,
2851 getMacroUsagePriority(M->first->getName(),
Douglas Gregorb05496d2010-09-20 21:11:48 +00002852 PP.getLangOptions(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002853 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002854 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002855
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002856 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002857
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002858}
2859
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002860static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2861 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002862 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002863
2864 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002865
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002866 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2867 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2868 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2869 Results.AddResult(Result("__func__", CCP_Constant));
2870 Results.ExitScope();
2871}
2872
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002873static void HandleCodeCompleteResults(Sema *S,
2874 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002875 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002876 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002877 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002878 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002879 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002880}
2881
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002882static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2883 Sema::ParserCompletionContext PCC) {
2884 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002885 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002886 return CodeCompletionContext::CCC_TopLevel;
2887
John McCallf312b1e2010-08-26 23:41:50 +00002888 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002889 return CodeCompletionContext::CCC_ClassStructUnion;
2890
John McCallf312b1e2010-08-26 23:41:50 +00002891 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002892 return CodeCompletionContext::CCC_ObjCInterface;
2893
John McCallf312b1e2010-08-26 23:41:50 +00002894 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002895 return CodeCompletionContext::CCC_ObjCImplementation;
2896
John McCallf312b1e2010-08-26 23:41:50 +00002897 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002898 return CodeCompletionContext::CCC_ObjCIvarList;
2899
John McCallf312b1e2010-08-26 23:41:50 +00002900 case Sema::PCC_Template:
2901 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002902 if (S.CurContext->isFileContext())
2903 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002904 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002905 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002906 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002907
John McCallf312b1e2010-08-26 23:41:50 +00002908 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002909 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002910
John McCallf312b1e2010-08-26 23:41:50 +00002911 case Sema::PCC_ForInit:
Douglas Gregora5450a02010-10-18 22:01:46 +00002912 if (S.getLangOptions().CPlusPlus || S.getLangOptions().C99 ||
2913 S.getLangOptions().ObjC1)
2914 return CodeCompletionContext::CCC_ParenthesizedExpression;
2915 else
2916 return CodeCompletionContext::CCC_Expression;
2917
2918 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002919 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002920 return CodeCompletionContext::CCC_Expression;
2921
John McCallf312b1e2010-08-26 23:41:50 +00002922 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002923 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002924
John McCallf312b1e2010-08-26 23:41:50 +00002925 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002926 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002927
2928 case Sema::PCC_ParenthesizedExpression:
2929 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002930
2931 case Sema::PCC_LocalDeclarationSpecifiers:
2932 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002933 }
David Blaikie7530c032012-01-17 06:56:22 +00002934
2935 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002936}
2937
Douglas Gregorf6961522010-08-27 21:18:54 +00002938/// \brief If we're in a C++ virtual member function, add completion results
2939/// that invoke the functions we override, since it's common to invoke the
2940/// overridden function as well as adding new functionality.
2941///
2942/// \param S The semantic analysis object for which we are generating results.
2943///
2944/// \param InContext This context in which the nested-name-specifier preceding
2945/// the code-completion point
2946static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2947 ResultBuilder &Results) {
2948 // Look through blocks.
2949 DeclContext *CurContext = S.CurContext;
2950 while (isa<BlockDecl>(CurContext))
2951 CurContext = CurContext->getParent();
2952
2953
2954 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2955 if (!Method || !Method->isVirtual())
2956 return;
2957
2958 // We need to have names for all of the parameters, if we're going to
2959 // generate a forwarding call.
2960 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2961 PEnd = Method->param_end();
2962 P != PEnd;
2963 ++P) {
2964 if (!(*P)->getDeclName())
2965 return;
2966 }
2967
Douglas Gregor8987b232011-09-27 23:30:47 +00002968 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00002969 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
2970 MEnd = Method->end_overridden_methods();
2971 M != MEnd; ++M) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002972 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf6961522010-08-27 21:18:54 +00002973 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
2974 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
2975 continue;
2976
2977 // If we need a nested-name-specifier, add one now.
2978 if (!InContext) {
2979 NestedNameSpecifier *NNS
2980 = getRequiredQualification(S.Context, CurContext,
2981 Overridden->getDeclContext());
2982 if (NNS) {
2983 std::string Str;
2984 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00002985 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002986 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00002987 }
2988 } else if (!InContext->Equals(Overridden->getDeclContext()))
2989 continue;
2990
Douglas Gregordae68752011-02-01 22:57:45 +00002991 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00002992 Overridden->getNameAsString()));
2993 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00002994 bool FirstParam = true;
2995 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2996 PEnd = Method->param_end();
2997 P != PEnd; ++P) {
2998 if (FirstParam)
2999 FirstParam = false;
3000 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003001 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003002
Douglas Gregordae68752011-02-01 22:57:45 +00003003 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003004 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003005 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003006 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3007 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003008 CCP_SuperCompletion,
3009 CXCursor_CXXMethod));
3010 Results.Ignore(Overridden);
3011 }
3012}
3013
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003014void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3015 ModuleIdPath Path) {
3016 typedef CodeCompletionResult Result;
3017 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3018 CodeCompletionContext::CCC_Other);
3019 Results.EnterNewScope();
3020
3021 CodeCompletionAllocator &Allocator = Results.getAllocator();
3022 CodeCompletionBuilder Builder(Allocator);
3023 typedef CodeCompletionResult Result;
3024 if (Path.empty()) {
3025 // Enumerate all top-level modules.
3026 llvm::SmallVector<Module *, 8> Modules;
3027 PP.getHeaderSearchInfo().collectAllModules(Modules);
3028 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3029 Builder.AddTypedTextChunk(
3030 Builder.getAllocator().CopyString(Modules[I]->Name));
3031 Results.AddResult(Result(Builder.TakeString(),
3032 CCP_Declaration,
3033 CXCursor_NotImplemented,
3034 Modules[I]->isAvailable()
3035 ? CXAvailability_Available
3036 : CXAvailability_NotAvailable));
3037 }
3038 } else {
3039 // Load the named module.
3040 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3041 Module::AllVisible,
3042 /*IsInclusionDirective=*/false);
3043 // Enumerate submodules.
3044 if (Mod) {
3045 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3046 SubEnd = Mod->submodule_end();
3047 Sub != SubEnd; ++Sub) {
3048
3049 Builder.AddTypedTextChunk(
3050 Builder.getAllocator().CopyString((*Sub)->Name));
3051 Results.AddResult(Result(Builder.TakeString(),
3052 CCP_Declaration,
3053 CXCursor_NotImplemented,
3054 (*Sub)->isAvailable()
3055 ? CXAvailability_Available
3056 : CXAvailability_NotAvailable));
3057 }
3058 }
3059 }
3060 Results.ExitScope();
3061 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3062 Results.data(),Results.size());
3063}
3064
Douglas Gregor01dfea02010-01-10 23:08:15 +00003065void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003066 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00003067 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003068 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003069 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003070 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003071
Douglas Gregor01dfea02010-01-10 23:08:15 +00003072 // Determine how to filter results, e.g., so that the names of
3073 // values (functions, enumerators, function templates, etc.) are
3074 // only allowed where we can have an expression.
3075 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003076 case PCC_Namespace:
3077 case PCC_Class:
3078 case PCC_ObjCInterface:
3079 case PCC_ObjCImplementation:
3080 case PCC_ObjCInstanceVariableList:
3081 case PCC_Template:
3082 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003083 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003084 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003085 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3086 break;
3087
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003088 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003089 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003090 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003091 case PCC_ForInit:
3092 case PCC_Condition:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003093 if (WantTypesInContext(CompletionContext, getLangOptions()))
3094 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3095 else
3096 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003097
3098 if (getLangOptions().CPlusPlus)
3099 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003100 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003101
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003102 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003103 // Unfiltered
3104 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003105 }
3106
Douglas Gregor3cdee122010-08-26 16:36:48 +00003107 // If we are in a C++ non-static member function, check the qualifiers on
3108 // the member function to filter/prioritize the results list.
3109 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3110 if (CurMethod->isInstance())
3111 Results.setObjectTypeQualifiers(
3112 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3113
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003114 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003115 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3116 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003117
Douglas Gregorbca403c2010-01-13 23:51:12 +00003118 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003119 Results.ExitScope();
3120
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003121 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003122 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003123 case PCC_Expression:
3124 case PCC_Statement:
3125 case PCC_RecoveryInFunction:
3126 if (S->getFnParent())
3127 AddPrettyFunctionResults(PP.getLangOptions(), Results);
3128 break;
3129
3130 case PCC_Namespace:
3131 case PCC_Class:
3132 case PCC_ObjCInterface:
3133 case PCC_ObjCImplementation:
3134 case PCC_ObjCInstanceVariableList:
3135 case PCC_Template:
3136 case PCC_MemberTemplate:
3137 case PCC_ForInit:
3138 case PCC_Condition:
3139 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003140 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003141 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003142 }
3143
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003144 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003145 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003146
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003147 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003148 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003149}
3150
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003151static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3152 ParsedType Receiver,
3153 IdentifierInfo **SelIdents,
3154 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003155 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003156 bool IsSuper,
3157 ResultBuilder &Results);
3158
3159void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3160 bool AllowNonIdentifiers,
3161 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003162 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003163 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003164 AllowNestedNameSpecifiers
3165 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3166 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003167 Results.EnterNewScope();
3168
3169 // Type qualifiers can come after names.
3170 Results.AddResult(Result("const"));
3171 Results.AddResult(Result("volatile"));
3172 if (getLangOptions().C99)
3173 Results.AddResult(Result("restrict"));
3174
3175 if (getLangOptions().CPlusPlus) {
3176 if (AllowNonIdentifiers) {
3177 Results.AddResult(Result("operator"));
3178 }
3179
3180 // Add nested-name-specifiers.
3181 if (AllowNestedNameSpecifiers) {
3182 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003183 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003184 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3185 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3186 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003187 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003188 }
3189 }
3190 Results.ExitScope();
3191
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003192 // If we're in a context where we might have an expression (rather than a
3193 // declaration), and what we've seen so far is an Objective-C type that could
3194 // be a receiver of a class message, this may be a class message send with
3195 // the initial opening bracket '[' missing. Add appropriate completions.
3196 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3197 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3198 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3199 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3200 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3201 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3202 DS.getTypeQualifiers() == 0 &&
3203 S &&
3204 (S->getFlags() & Scope::DeclScope) != 0 &&
3205 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3206 Scope::FunctionPrototypeScope |
3207 Scope::AtCatchScope)) == 0) {
3208 ParsedType T = DS.getRepAsType();
3209 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003210 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003211 }
3212
Douglas Gregor4497dd42010-08-24 04:59:56 +00003213 // Note that we intentionally suppress macro results here, since we do not
3214 // encourage using macros to produce the names of entities.
3215
Douglas Gregor52779fb2010-09-23 23:01:17 +00003216 HandleCodeCompleteResults(this, CodeCompleter,
3217 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003218 Results.data(), Results.size());
3219}
3220
Douglas Gregorfb629412010-08-23 21:17:50 +00003221struct Sema::CodeCompleteExpressionData {
3222 CodeCompleteExpressionData(QualType PreferredType = QualType())
3223 : PreferredType(PreferredType), IntegralConstantExpression(false),
3224 ObjCCollection(false) { }
3225
3226 QualType PreferredType;
3227 bool IntegralConstantExpression;
3228 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003229 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003230};
3231
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003232/// \brief Perform code-completion in an expression context when we know what
3233/// type we're looking for.
Douglas Gregorf9578432010-07-28 21:50:18 +00003234///
3235/// \param IntegralConstantExpression Only permit integral constant
3236/// expressions.
Douglas Gregorfb629412010-08-23 21:17:50 +00003237void Sema::CodeCompleteExpression(Scope *S,
3238 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00003239 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003240 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3241 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003242 if (Data.ObjCCollection)
3243 Results.setFilter(&ResultBuilder::IsObjCCollection);
3244 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003245 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003246 else if (WantTypesInContext(PCC_Expression, getLangOptions()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003247 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3248 else
3249 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003250
3251 if (!Data.PreferredType.isNull())
3252 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3253
3254 // Ignore any declarations that we were told that we don't care about.
3255 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3256 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003257
3258 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003259 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3260 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003261
3262 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003263 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003264 Results.ExitScope();
3265
Douglas Gregor590c7d52010-07-08 20:55:51 +00003266 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003267 if (!Data.PreferredType.isNull())
3268 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3269 || Data.PreferredType->isMemberPointerType()
3270 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003271
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003272 if (S->getFnParent() &&
3273 !Data.ObjCCollection &&
3274 !Data.IntegralConstantExpression)
3275 AddPrettyFunctionResults(PP.getLangOptions(), Results);
3276
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003277 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003278 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003279 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003280 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3281 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003282 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003283}
3284
Douglas Gregorac5fd842010-09-18 01:28:11 +00003285void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3286 if (E.isInvalid())
3287 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
3288 else if (getLangOptions().ObjC1)
3289 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003290}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003291
Douglas Gregor73449212010-12-09 23:01:55 +00003292/// \brief The set of properties that have already been added, referenced by
3293/// property name.
3294typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3295
Douglas Gregor95ac6552009-11-18 01:29:26 +00003296static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003297 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003298 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003299 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003300 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003301 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003302 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003303
3304 // Add properties in this container.
3305 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3306 PEnd = Container->prop_end();
3307 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003308 ++P) {
3309 if (AddedProperties.insert(P->getIdentifier()))
3310 Results.MaybeAddResult(Result(*P, 0), CurContext);
3311 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003312
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003313 // Add nullary methods
3314 if (AllowNullaryMethods) {
3315 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003316 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003317 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3318 MEnd = Container->meth_end();
3319 M != MEnd; ++M) {
3320 if (M->getSelector().isUnarySelector())
3321 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3322 if (AddedProperties.insert(Name)) {
3323 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor8987b232011-09-27 23:30:47 +00003324 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003325 Builder.AddTypedTextChunk(
3326 Results.getAllocator().CopyString(Name->getName()));
3327
3328 CXAvailabilityKind Availability = CXAvailability_Available;
3329 switch (M->getAvailability()) {
3330 case AR_Available:
3331 case AR_NotYetIntroduced:
3332 Availability = CXAvailability_Available;
3333 break;
3334
3335 case AR_Deprecated:
3336 Availability = CXAvailability_Deprecated;
3337 break;
3338
3339 case AR_Unavailable:
3340 Availability = CXAvailability_NotAvailable;
3341 break;
3342 }
3343
3344 Results.MaybeAddResult(Result(Builder.TakeString(),
3345 CCP_MemberDeclaration + CCD_MethodAsProperty,
3346 M->isInstanceMethod()
3347 ? CXCursor_ObjCInstanceMethodDecl
3348 : CXCursor_ObjCClassMethodDecl,
3349 Availability),
3350 CurContext);
3351 }
3352 }
3353 }
3354
3355
Douglas Gregor95ac6552009-11-18 01:29:26 +00003356 // Add properties in referenced protocols.
3357 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3358 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3359 PEnd = Protocol->protocol_end();
3360 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003361 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3362 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003363 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003364 if (AllowCategories) {
3365 // Look through categories.
3366 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3367 Category; Category = Category->getNextClassCategory())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003368 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3369 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003370 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003371
3372 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003373 for (ObjCInterfaceDecl::all_protocol_iterator
3374 I = IFace->all_referenced_protocol_begin(),
3375 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003376 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3377 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003378
3379 // Look in the superclass.
3380 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003381 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3382 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003383 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003384 } else if (const ObjCCategoryDecl *Category
3385 = dyn_cast<ObjCCategoryDecl>(Container)) {
3386 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003387 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3388 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003389 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003390 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3391 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003392 }
3393}
3394
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003395void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003396 SourceLocation OpLoc,
3397 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003398 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003399 return;
3400
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003401 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3402 if (ConvertedBase.isInvalid())
3403 return;
3404 Base = ConvertedBase.get();
3405
John McCall0a2c5e22010-08-25 06:19:51 +00003406 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003407
Douglas Gregor81b747b2009-09-17 21:32:03 +00003408 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003409
3410 if (IsArrow) {
3411 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3412 BaseType = Ptr->getPointeeType();
3413 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003414 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003415 else
3416 return;
3417 }
3418
Douglas Gregor3da626b2011-07-07 16:03:39 +00003419 enum CodeCompletionContext::Kind contextKind;
3420
3421 if (IsArrow) {
3422 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3423 }
3424 else {
3425 if (BaseType->isObjCObjectPointerType() ||
3426 BaseType->isObjCObjectOrInterfaceType()) {
3427 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3428 }
3429 else {
3430 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3431 }
3432 }
3433
Douglas Gregor218937c2011-02-01 19:23:04 +00003434 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003435 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003436 BaseType),
3437 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003438 Results.EnterNewScope();
3439 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003440 // Indicate that we are performing a member access, and the cv-qualifiers
3441 // for the base object type.
3442 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3443
Douglas Gregor95ac6552009-11-18 01:29:26 +00003444 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003445 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003446 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003447 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3448 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003449
Douglas Gregor95ac6552009-11-18 01:29:26 +00003450 if (getLangOptions().CPlusPlus) {
3451 if (!Results.empty()) {
3452 // The "template" keyword can follow "->" or "." in the grammar.
3453 // However, we only want to suggest the template keyword if something
3454 // is dependent.
3455 bool IsDependent = BaseType->isDependentType();
3456 if (!IsDependent) {
3457 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3458 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3459 IsDependent = Ctx->isDependentContext();
3460 break;
3461 }
3462 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003463
Douglas Gregor95ac6552009-11-18 01:29:26 +00003464 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003465 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003466 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003467 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003468 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3469 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003470 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003471
3472 // Add property results based on our interface.
3473 const ObjCObjectPointerType *ObjCPtr
3474 = BaseType->getAsObjCInterfacePointerType();
3475 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003476 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3477 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003478 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003479
3480 // Add properties from the protocols in a qualified interface.
3481 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3482 E = ObjCPtr->qual_end();
3483 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003484 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3485 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003486 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003487 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003488 // Objective-C instance variable access.
3489 ObjCInterfaceDecl *Class = 0;
3490 if (const ObjCObjectPointerType *ObjCPtr
3491 = BaseType->getAs<ObjCObjectPointerType>())
3492 Class = ObjCPtr->getInterfaceDecl();
3493 else
John McCallc12c5bb2010-05-15 11:32:37 +00003494 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003495
3496 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003497 if (Class) {
3498 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3499 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003500 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3501 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003502 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003503 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003504
3505 // FIXME: How do we cope with isa?
3506
3507 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003508
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003509 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003510 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003511 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003512 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003513}
3514
Douglas Gregor374929f2009-09-18 15:37:17 +00003515void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3516 if (!CodeCompleter)
3517 return;
3518
John McCall0a2c5e22010-08-25 06:19:51 +00003519 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003520 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003521 enum CodeCompletionContext::Kind ContextKind
3522 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003523 switch ((DeclSpec::TST)TagSpec) {
3524 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003525 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003526 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003527 break;
3528
3529 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003530 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003531 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003532 break;
3533
3534 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003535 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003536 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003537 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003538 break;
3539
3540 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003541 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003542 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003543
Douglas Gregor218937c2011-02-01 19:23:04 +00003544 ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003545 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003546
3547 // First pass: look for tags.
3548 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003549 LookupVisibleDecls(S, LookupTagName, Consumer,
3550 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003551
Douglas Gregor8071e422010-08-15 06:18:01 +00003552 if (CodeCompleter->includeGlobals()) {
3553 // Second pass: look for nested name specifiers.
3554 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3555 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3556 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003557
Douglas Gregor52779fb2010-09-23 23:01:17 +00003558 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003559 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003560}
3561
Douglas Gregor1a480c42010-08-27 17:35:51 +00003562void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003563 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3564 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003565 Results.EnterNewScope();
3566 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3567 Results.AddResult("const");
3568 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3569 Results.AddResult("volatile");
3570 if (getLangOptions().C99 &&
3571 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3572 Results.AddResult("restrict");
3573 Results.ExitScope();
3574 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003575 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003576 Results.data(), Results.size());
3577}
3578
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003579void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003580 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003581 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003582
John McCall781472f2010-08-25 08:40:02 +00003583 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003584 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3585 if (!type->isEnumeralType()) {
3586 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003587 Data.IntegralConstantExpression = true;
3588 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003589 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003590 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003591
3592 // Code-complete the cases of a switch statement over an enumeration type
3593 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003594 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003595
3596 // Determine which enumerators we have already seen in the switch statement.
3597 // FIXME: Ideally, we would also be able to look *past* the code-completion
3598 // token, in case we are code-completing in the middle of the switch and not
3599 // at the end. However, we aren't able to do so at the moment.
3600 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003601 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003602 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3603 SC = SC->getNextSwitchCase()) {
3604 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3605 if (!Case)
3606 continue;
3607
3608 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3609 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3610 if (EnumConstantDecl *Enumerator
3611 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3612 // We look into the AST of the case statement to determine which
3613 // enumerator was named. Alternatively, we could compute the value of
3614 // the integral constant expression, then compare it against the
3615 // values of each enumerator. However, value-based approach would not
3616 // work as well with C++ templates where enumerators declared within a
3617 // template are type- and value-dependent.
3618 EnumeratorsSeen.insert(Enumerator);
3619
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003620 // If this is a qualified-id, keep track of the nested-name-specifier
3621 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003622 //
3623 // switch (TagD.getKind()) {
3624 // case TagDecl::TK_enum:
3625 // break;
3626 // case XXX
3627 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003628 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003629 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3630 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003631 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003632 }
3633 }
3634
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003635 if (getLangOptions().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
3636 // If there are no prior enumerators in C++, check whether we have to
3637 // qualify the names of the enumerators that we suggest, because they
3638 // may not be visible in this scope.
3639 Qualifier = getRequiredQualification(Context, CurContext,
3640 Enum->getDeclContext());
3641
3642 // FIXME: Scoped enums need to start with "EnumDecl" as the context!
3643 }
3644
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003645 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003646 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3647 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003648 Results.EnterNewScope();
3649 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3650 EEnd = Enum->enumerator_end();
3651 E != EEnd; ++E) {
3652 if (EnumeratorsSeen.count(*E))
3653 continue;
3654
Douglas Gregor5c722c702011-02-18 23:30:37 +00003655 CodeCompletionResult R(*E, Qualifier);
3656 R.Priority = CCP_EnumInCase;
3657 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003658 }
3659 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003660
Douglas Gregor3da626b2011-07-07 16:03:39 +00003661 //We need to make sure we're setting the right context,
3662 //so only say we include macros if the code completer says we do
3663 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3664 if (CodeCompleter->includeMacros()) {
Douglas Gregorbca403c2010-01-13 23:51:12 +00003665 AddMacroResults(PP, Results);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003666 kind = CodeCompletionContext::CCC_OtherWithMacros;
3667 }
3668
3669
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003670 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003671 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003672 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003673}
3674
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003675namespace {
3676 struct IsBetterOverloadCandidate {
3677 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003678 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003679
3680 public:
John McCall5769d612010-02-08 23:07:23 +00003681 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3682 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003683
3684 bool
3685 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003686 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003687 }
3688 };
3689}
3690
Douglas Gregord28dcd72010-05-30 06:10:08 +00003691static bool anyNullArguments(Expr **Args, unsigned NumArgs) {
3692 if (NumArgs && !Args)
3693 return true;
3694
3695 for (unsigned I = 0; I != NumArgs; ++I)
3696 if (!Args[I])
3697 return true;
3698
3699 return false;
3700}
3701
Richard Trieuf81e5a92011-09-09 02:00:50 +00003702void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
3703 Expr **ArgsIn, unsigned NumArgs) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003704 if (!CodeCompleter)
3705 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003706
3707 // When we're code-completing for a call, we fall back to ordinary
3708 // name code-completion whenever we can't produce specific
3709 // results. We may want to revisit this strategy in the future,
3710 // e.g., by merging the two kinds of results.
3711
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003712 Expr *Fn = (Expr *)FnIn;
3713 Expr **Args = (Expr **)ArgsIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003714
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003715 // Ignore type-dependent call expressions entirely.
Douglas Gregord28dcd72010-05-30 06:10:08 +00003716 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) ||
Douglas Gregoref96eac2009-12-11 19:06:04 +00003717 Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003718 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003719 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003720 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003721
John McCall3b4294e2009-12-16 12:17:52 +00003722 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003723 SourceLocation Loc = Fn->getExprLoc();
3724 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003725
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003726 // FIXME: What if we're calling something that isn't a function declaration?
3727 // FIXME: What if we're calling a pseudo-destructor?
3728 // FIXME: What if we're calling a member function?
3729
Douglas Gregorc0265402010-01-21 15:46:19 +00003730 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003731 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003732
John McCall3b4294e2009-12-16 12:17:52 +00003733 Expr *NakedFn = Fn->IgnoreParenCasts();
3734 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
3735 AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet,
3736 /*PartialOverloading=*/ true);
3737 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3738 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003739 if (FDecl) {
Douglas Gregord28dcd72010-05-30 06:10:08 +00003740 if (!getLangOptions().CPlusPlus ||
3741 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003742 Results.push_back(ResultCandidate(FDecl));
3743 else
John McCall86820f52010-01-26 01:37:31 +00003744 // FIXME: access?
John McCall9aa472c2010-03-19 07:35:19 +00003745 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none),
3746 Args, NumArgs, CandidateSet,
Douglas Gregorc27d6c52010-04-16 17:41:49 +00003747 false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003748 }
John McCall3b4294e2009-12-16 12:17:52 +00003749 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003750
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003751 QualType ParamType;
3752
Douglas Gregorc0265402010-01-21 15:46:19 +00003753 if (!CandidateSet.empty()) {
3754 // Sort the overload candidate set by placing the best overloads first.
3755 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003756 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003757
Douglas Gregorc0265402010-01-21 15:46:19 +00003758 // Add the remaining viable overload candidates as code-completion reslults.
3759 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3760 CandEnd = CandidateSet.end();
3761 Cand != CandEnd; ++Cand) {
3762 if (Cand->Viable)
3763 Results.push_back(ResultCandidate(Cand->Function));
3764 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003765
3766 // From the viable candidates, try to determine the type of this parameter.
3767 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3768 if (const FunctionType *FType = Results[I].getFunctionType())
3769 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
3770 if (NumArgs < Proto->getNumArgs()) {
3771 if (ParamType.isNull())
3772 ParamType = Proto->getArgType(NumArgs);
3773 else if (!Context.hasSameUnqualifiedType(
3774 ParamType.getNonReferenceType(),
3775 Proto->getArgType(NumArgs).getNonReferenceType())) {
3776 ParamType = QualType();
3777 break;
3778 }
3779 }
3780 }
3781 } else {
3782 // Try to determine the parameter type from the type of the expression
3783 // being called.
3784 QualType FunctionType = Fn->getType();
3785 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3786 FunctionType = Ptr->getPointeeType();
3787 else if (const BlockPointerType *BlockPtr
3788 = FunctionType->getAs<BlockPointerType>())
3789 FunctionType = BlockPtr->getPointeeType();
3790 else if (const MemberPointerType *MemPtr
3791 = FunctionType->getAs<MemberPointerType>())
3792 FunctionType = MemPtr->getPointeeType();
3793
3794 if (const FunctionProtoType *Proto
3795 = FunctionType->getAs<FunctionProtoType>()) {
3796 if (NumArgs < Proto->getNumArgs())
3797 ParamType = Proto->getArgType(NumArgs);
3798 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003799 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003800
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003801 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003802 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003803 else
3804 CodeCompleteExpression(S, ParamType);
3805
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003806 if (!Results.empty())
Douglas Gregoref96eac2009-12-11 19:06:04 +00003807 CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(),
3808 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003809}
3810
John McCalld226f652010-08-21 09:40:31 +00003811void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3812 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003813 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003814 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003815 return;
3816 }
3817
3818 CodeCompleteExpression(S, VD->getType());
3819}
3820
3821void Sema::CodeCompleteReturn(Scope *S) {
3822 QualType ResultType;
3823 if (isa<BlockDecl>(CurContext)) {
3824 if (BlockScopeInfo *BSI = getCurBlock())
3825 ResultType = BSI->ReturnType;
3826 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3827 ResultType = Function->getResultType();
3828 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3829 ResultType = Method->getResultType();
3830
3831 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003832 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003833 else
3834 CodeCompleteExpression(S, ResultType);
3835}
3836
Douglas Gregord2d8be62011-07-30 08:36:53 +00003837void Sema::CodeCompleteAfterIf(Scope *S) {
3838 typedef CodeCompletionResult Result;
3839 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3840 mapCodeCompletionContext(*this, PCC_Statement));
3841 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3842 Results.EnterNewScope();
3843
3844 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3845 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3846 CodeCompleter->includeGlobals());
3847
3848 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3849
3850 // "else" block
3851 CodeCompletionBuilder Builder(Results.getAllocator());
3852 Builder.AddTypedTextChunk("else");
3853 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3854 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3855 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3856 Builder.AddPlaceholderChunk("statements");
3857 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3858 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3859 Results.AddResult(Builder.TakeString());
3860
3861 // "else if" block
3862 Builder.AddTypedTextChunk("else");
3863 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3864 Builder.AddTextChunk("if");
3865 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3866 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3867 if (getLangOptions().CPlusPlus)
3868 Builder.AddPlaceholderChunk("condition");
3869 else
3870 Builder.AddPlaceholderChunk("expression");
3871 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3872 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3873 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3874 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3875 Builder.AddPlaceholderChunk("statements");
3876 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3877 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3878 Results.AddResult(Builder.TakeString());
3879
3880 Results.ExitScope();
3881
3882 if (S->getFnParent())
3883 AddPrettyFunctionResults(PP.getLangOptions(), Results);
3884
3885 if (CodeCompleter->includeMacros())
3886 AddMacroResults(PP, Results);
3887
3888 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3889 Results.data(),Results.size());
3890}
3891
Richard Trieuf81e5a92011-09-09 02:00:50 +00003892void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003893 if (LHS)
3894 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3895 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003896 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003897}
3898
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003899void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003900 bool EnteringContext) {
3901 if (!SS.getScopeRep() || !CodeCompleter)
3902 return;
3903
Douglas Gregor86d9a522009-09-21 16:56:56 +00003904 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3905 if (!Ctx)
3906 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003907
3908 // Try to instantiate any non-dependent declaration contexts before
3909 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003910 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003911 return;
3912
Douglas Gregor218937c2011-02-01 19:23:04 +00003913 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3914 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003915 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003916
Douglas Gregor86d9a522009-09-21 16:56:56 +00003917 // The "template" keyword can follow "::" in the grammar, but only
3918 // put it into the grammar if the nested-name-specifier is dependent.
3919 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3920 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003921 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003922
3923 // Add calls to overridden virtual functions, if there are any.
3924 //
3925 // FIXME: This isn't wonderful, because we don't know whether we're actually
3926 // in a context that permits expressions. This is a general issue with
3927 // qualified-id completions.
3928 if (!EnteringContext)
3929 MaybeAddOverrideCalls(*this, Ctx, Results);
3930 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003931
Douglas Gregorf6961522010-08-27 21:18:54 +00003932 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3933 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3934
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003935 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00003936 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003937 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003938}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003939
3940void Sema::CodeCompleteUsing(Scope *S) {
3941 if (!CodeCompleter)
3942 return;
3943
Douglas Gregor218937c2011-02-01 19:23:04 +00003944 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003945 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3946 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003947 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003948
3949 // If we aren't in class scope, we could see the "namespace" keyword.
3950 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00003951 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003952
3953 // After "using", we can see anything that would start a
3954 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003955 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003956 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3957 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003958 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003959
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003960 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003961 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003962 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003963}
3964
3965void Sema::CodeCompleteUsingDirective(Scope *S) {
3966 if (!CodeCompleter)
3967 return;
3968
Douglas Gregor86d9a522009-09-21 16:56:56 +00003969 // After "using namespace", we expect to see a namespace name or namespace
3970 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003971 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3972 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003973 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003974 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003975 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003976 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3977 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003978 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003979 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003980 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003981 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003982}
3983
3984void Sema::CodeCompleteNamespaceDecl(Scope *S) {
3985 if (!CodeCompleter)
3986 return;
3987
Douglas Gregor86d9a522009-09-21 16:56:56 +00003988 DeclContext *Ctx = (DeclContext *)S->getEntity();
3989 if (!S->getParent())
3990 Ctx = Context.getTranslationUnitDecl();
3991
Douglas Gregor52779fb2010-09-23 23:01:17 +00003992 bool SuppressedGlobalResults
3993 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
3994
Douglas Gregor218937c2011-02-01 19:23:04 +00003995 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003996 SuppressedGlobalResults
3997 ? CodeCompletionContext::CCC_Namespace
3998 : CodeCompletionContext::CCC_Other,
3999 &ResultBuilder::IsNamespace);
4000
4001 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004002 // We only want to see those namespaces that have already been defined
4003 // within this scope, because its likely that the user is creating an
4004 // extended namespace declaration. Keep track of the most recent
4005 // definition of each namespace.
4006 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4007 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4008 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4009 NS != NSEnd; ++NS)
4010 OrigToLatest[NS->getOriginalNamespace()] = *NS;
4011
4012 // Add the most recent definition (or extended definition) of each
4013 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004014 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004015 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
4016 NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
4017 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004018 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004019 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004020 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004021 }
4022
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004023 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004024 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004025 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004026}
4027
4028void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4029 if (!CodeCompleter)
4030 return;
4031
Douglas Gregor86d9a522009-09-21 16:56:56 +00004032 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004033 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4034 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004035 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004036 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004037 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4038 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004039 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004040 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004041 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004042}
4043
Douglas Gregored8d3222009-09-18 20:05:18 +00004044void Sema::CodeCompleteOperatorName(Scope *S) {
4045 if (!CodeCompleter)
4046 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004047
John McCall0a2c5e22010-08-25 06:19:51 +00004048 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004049 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4050 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004051 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004052 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004053
Douglas Gregor86d9a522009-09-21 16:56:56 +00004054 // Add the names of overloadable operators.
4055#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4056 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004057 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004058#include "clang/Basic/OperatorKinds.def"
4059
4060 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004061 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004062 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004063 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4064 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004065
4066 // Add any type specifiers
Douglas Gregorbca403c2010-01-13 23:51:12 +00004067 AddTypeSpecifierResults(getLangOptions(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004068 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004069
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004070 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004071 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004072 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004073}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004074
Douglas Gregor0133f522010-08-28 00:00:50 +00004075void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004076 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004077 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004078 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004079 CXXConstructorDecl *Constructor
4080 = static_cast<CXXConstructorDecl *>(ConstructorD);
4081 if (!Constructor)
4082 return;
4083
Douglas Gregor218937c2011-02-01 19:23:04 +00004084 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004085 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004086 Results.EnterNewScope();
4087
4088 // Fill in any already-initialized fields or base classes.
4089 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4090 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4091 for (unsigned I = 0; I != NumInitializers; ++I) {
4092 if (Initializers[I]->isBaseInitializer())
4093 InitializedBases.insert(
4094 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4095 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004096 InitializedFields.insert(cast<FieldDecl>(
4097 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004098 }
4099
4100 // Add completions for base classes.
Douglas Gregor218937c2011-02-01 19:23:04 +00004101 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004102 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004103 CXXRecordDecl *ClassDecl = Constructor->getParent();
4104 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4105 BaseEnd = ClassDecl->bases_end();
4106 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004107 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4108 SawLastInitializer
4109 = NumInitializers > 0 &&
4110 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4111 Context.hasSameUnqualifiedType(Base->getType(),
4112 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004113 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004114 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004115
Douglas Gregor218937c2011-02-01 19:23:04 +00004116 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004117 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004118 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004119 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4120 Builder.AddPlaceholderChunk("args");
4121 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4122 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004123 SawLastInitializer? CCP_NextInitializer
4124 : CCP_MemberDeclaration));
4125 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004126 }
4127
4128 // Add completions for virtual base classes.
4129 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4130 BaseEnd = ClassDecl->vbases_end();
4131 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004132 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4133 SawLastInitializer
4134 = NumInitializers > 0 &&
4135 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4136 Context.hasSameUnqualifiedType(Base->getType(),
4137 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004138 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004139 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004140
Douglas Gregor218937c2011-02-01 19:23:04 +00004141 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004142 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004143 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004144 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4145 Builder.AddPlaceholderChunk("args");
4146 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4147 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004148 SawLastInitializer? CCP_NextInitializer
4149 : CCP_MemberDeclaration));
4150 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004151 }
4152
4153 // Add completions for members.
4154 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4155 FieldEnd = ClassDecl->field_end();
4156 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004157 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4158 SawLastInitializer
4159 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004160 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
4161 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004162 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004163 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004164
4165 if (!Field->getDeclName())
4166 continue;
4167
Douglas Gregordae68752011-02-01 22:57:45 +00004168 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004169 Field->getIdentifier()->getName()));
4170 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4171 Builder.AddPlaceholderChunk("args");
4172 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4173 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004174 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004175 : CCP_MemberDeclaration,
4176 CXCursor_MemberRef));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004177 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004178 }
4179 Results.ExitScope();
4180
Douglas Gregor52779fb2010-09-23 23:01:17 +00004181 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004182 Results.data(), Results.size());
4183}
4184
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004185// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
4186// true or false.
4187#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorbca403c2010-01-13 23:51:12 +00004188static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004189 ResultBuilder &Results,
4190 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004191 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004192 // Since we have an implementation, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004193 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004194
Douglas Gregor218937c2011-02-01 19:23:04 +00004195 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004196 if (LangOpts.ObjC2) {
4197 // @dynamic
Douglas Gregor218937c2011-02-01 19:23:04 +00004198 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
4199 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4200 Builder.AddPlaceholderChunk("property");
4201 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004202
4203 // @synthesize
Douglas Gregor218937c2011-02-01 19:23:04 +00004204 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
4205 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4206 Builder.AddPlaceholderChunk("property");
4207 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004208 }
4209}
4210
Douglas Gregorbca403c2010-01-13 23:51:12 +00004211static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004212 ResultBuilder &Results,
4213 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004214 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004215
4216 // Since we have an interface or protocol, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004217 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004218
4219 if (LangOpts.ObjC2) {
4220 // @property
Douglas Gregora4477812010-01-14 16:01:26 +00004221 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004222
4223 // @required
Douglas Gregora4477812010-01-14 16:01:26 +00004224 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004225
4226 // @optional
Douglas Gregora4477812010-01-14 16:01:26 +00004227 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004228 }
4229}
4230
Douglas Gregorbca403c2010-01-13 23:51:12 +00004231static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004232 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004233 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004234
4235 // @class name ;
Douglas Gregor218937c2011-02-01 19:23:04 +00004236 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
4237 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4238 Builder.AddPlaceholderChunk("name");
4239 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004240
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004241 if (Results.includeCodePatterns()) {
4242 // @interface name
4243 // FIXME: Could introduce the whole pattern, including superclasses and
4244 // such.
Douglas Gregor218937c2011-02-01 19:23:04 +00004245 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
4246 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4247 Builder.AddPlaceholderChunk("class");
4248 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004249
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004250 // @protocol name
Douglas Gregor218937c2011-02-01 19:23:04 +00004251 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4252 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4253 Builder.AddPlaceholderChunk("protocol");
4254 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004255
4256 // @implementation name
Douglas Gregor218937c2011-02-01 19:23:04 +00004257 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
4258 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4259 Builder.AddPlaceholderChunk("class");
4260 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004261 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004262
4263 // @compatibility_alias name
Douglas Gregor218937c2011-02-01 19:23:04 +00004264 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
4265 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4266 Builder.AddPlaceholderChunk("alias");
4267 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4268 Builder.AddPlaceholderChunk("class");
4269 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004270}
4271
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004272void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004273 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004274 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4275 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004276 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004277 if (isa<ObjCImplDecl>(CurContext))
Douglas Gregorbca403c2010-01-13 23:51:12 +00004278 AddObjCImplementationResults(getLangOptions(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004279 else if (CurContext->isObjCContainer())
Douglas Gregorbca403c2010-01-13 23:51:12 +00004280 AddObjCInterfaceResults(getLangOptions(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004281 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004282 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004283 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004284 HandleCodeCompleteResults(this, CodeCompleter,
4285 CodeCompletionContext::CCC_Other,
4286 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004287}
4288
Douglas Gregorbca403c2010-01-13 23:51:12 +00004289static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004290 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004291 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004292
4293 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004294 const char *EncodeType = "char[]";
4295 if (Results.getSema().getLangOptions().CPlusPlus ||
4296 Results.getSema().getLangOptions().ConstStrings)
4297 EncodeType = " const char[]";
4298 Builder.AddResultTypeChunk(EncodeType);
Douglas Gregor218937c2011-02-01 19:23:04 +00004299 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
4300 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4301 Builder.AddPlaceholderChunk("type-name");
4302 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4303 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004304
4305 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004306 Builder.AddResultTypeChunk("Protocol *");
Douglas Gregor218937c2011-02-01 19:23:04 +00004307 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4308 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4309 Builder.AddPlaceholderChunk("protocol-name");
4310 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4311 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004312
4313 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004314 Builder.AddResultTypeChunk("SEL");
Douglas Gregor218937c2011-02-01 19:23:04 +00004315 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
4316 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4317 Builder.AddPlaceholderChunk("selector");
4318 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4319 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004320}
4321
Douglas Gregorbca403c2010-01-13 23:51:12 +00004322static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004323 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004324 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004325
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004326 if (Results.includeCodePatterns()) {
4327 // @try { statements } @catch ( declaration ) { statements } @finally
4328 // { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004329 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
4330 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4331 Builder.AddPlaceholderChunk("statements");
4332 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4333 Builder.AddTextChunk("@catch");
4334 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4335 Builder.AddPlaceholderChunk("parameter");
4336 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4337 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4338 Builder.AddPlaceholderChunk("statements");
4339 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4340 Builder.AddTextChunk("@finally");
4341 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4342 Builder.AddPlaceholderChunk("statements");
4343 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4344 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004345 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004346
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004347 // @throw
Douglas Gregor218937c2011-02-01 19:23:04 +00004348 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
4349 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4350 Builder.AddPlaceholderChunk("expression");
4351 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004352
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004353 if (Results.includeCodePatterns()) {
4354 // @synchronized ( expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004355 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
4356 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4357 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4358 Builder.AddPlaceholderChunk("expression");
4359 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4360 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4361 Builder.AddPlaceholderChunk("statements");
4362 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4363 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004364 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004365}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004366
Douglas Gregorbca403c2010-01-13 23:51:12 +00004367static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004368 ResultBuilder &Results,
4369 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004370 typedef CodeCompletionResult Result;
Douglas Gregora4477812010-01-14 16:01:26 +00004371 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
4372 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
4373 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004374 if (LangOpts.ObjC2)
Douglas Gregora4477812010-01-14 16:01:26 +00004375 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004376}
4377
4378void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004379 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4380 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004381 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004382 AddObjCVisibilityResults(getLangOptions(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004383 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004384 HandleCodeCompleteResults(this, CodeCompleter,
4385 CodeCompletionContext::CCC_Other,
4386 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004387}
4388
4389void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004390 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4391 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004392 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004393 AddObjCStatementResults(Results, false);
4394 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004395 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004396 HandleCodeCompleteResults(this, CodeCompleter,
4397 CodeCompletionContext::CCC_Other,
4398 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004399}
4400
4401void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004402 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4403 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004404 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004405 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004406 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004407 HandleCodeCompleteResults(this, CodeCompleter,
4408 CodeCompletionContext::CCC_Other,
4409 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004410}
4411
Douglas Gregor988358f2009-11-19 00:14:45 +00004412/// \brief Determine whether the addition of the given flag to an Objective-C
4413/// property's attributes will cause a conflict.
4414static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4415 // Check if we've already added this flag.
4416 if (Attributes & NewFlag)
4417 return true;
4418
4419 Attributes |= NewFlag;
4420
4421 // Check for collisions with "readonly".
4422 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4423 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4424 ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004425 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004426 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004427 ObjCDeclSpec::DQ_PR_retain |
4428 ObjCDeclSpec::DQ_PR_strong)))
Douglas Gregor988358f2009-11-19 00:14:45 +00004429 return true;
4430
John McCallf85e1932011-06-15 23:02:42 +00004431 // Check for more than one of { assign, copy, retain, strong }.
Douglas Gregor988358f2009-11-19 00:14:45 +00004432 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004433 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004434 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004435 ObjCDeclSpec::DQ_PR_retain|
4436 ObjCDeclSpec::DQ_PR_strong);
Douglas Gregor988358f2009-11-19 00:14:45 +00004437 if (AssignCopyRetMask &&
4438 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004439 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004440 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004441 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
4442 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
Douglas Gregor988358f2009-11-19 00:14:45 +00004443 return true;
4444
4445 return false;
4446}
4447
Douglas Gregora93b1082009-11-18 23:08:07 +00004448void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004449 if (!CodeCompleter)
4450 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004451
Steve Naroffece8e712009-10-08 21:55:05 +00004452 unsigned Attributes = ODS.getPropertyAttributes();
4453
John McCall0a2c5e22010-08-25 06:19:51 +00004454 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004455 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4456 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004457 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004458 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004459 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004460 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004461 Results.AddResult(CodeCompletionResult("assign"));
John McCallf85e1932011-06-15 23:02:42 +00004462 if (!ObjCPropertyFlagConflicts(Attributes,
4463 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4464 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004465 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004466 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004467 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004468 Results.AddResult(CodeCompletionResult("retain"));
John McCallf85e1932011-06-15 23:02:42 +00004469 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4470 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004471 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004472 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004473 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004474 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004475 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4476 Results.AddResult(CodeCompletionResult("atomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004477 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004478 CodeCompletionBuilder Setter(Results.getAllocator());
4479 Setter.AddTypedTextChunk("setter");
4480 Setter.AddTextChunk(" = ");
4481 Setter.AddPlaceholderChunk("method");
4482 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004483 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004484 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004485 CodeCompletionBuilder Getter(Results.getAllocator());
4486 Getter.AddTypedTextChunk("getter");
4487 Getter.AddTextChunk(" = ");
4488 Getter.AddPlaceholderChunk("method");
4489 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004490 }
Steve Naroffece8e712009-10-08 21:55:05 +00004491 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004492 HandleCodeCompleteResults(this, CodeCompleter,
4493 CodeCompletionContext::CCC_Other,
4494 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004495}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004496
Douglas Gregor4ad96852009-11-19 07:41:15 +00004497/// \brief Descripts the kind of Objective-C method that we want to find
4498/// via code completion.
4499enum ObjCMethodKind {
4500 MK_Any, //< Any kind of method, provided it means other specified criteria.
4501 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4502 MK_OneArgSelector //< One-argument selector.
4503};
4504
Douglas Gregor458433d2010-08-26 15:07:07 +00004505static bool isAcceptableObjCSelector(Selector Sel,
4506 ObjCMethodKind WantKind,
4507 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004508 unsigned NumSelIdents,
4509 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004510 if (NumSelIdents > Sel.getNumArgs())
4511 return false;
4512
4513 switch (WantKind) {
4514 case MK_Any: break;
4515 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4516 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4517 }
4518
Douglas Gregorcf544262010-11-17 21:36:08 +00004519 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4520 return false;
4521
Douglas Gregor458433d2010-08-26 15:07:07 +00004522 for (unsigned I = 0; I != NumSelIdents; ++I)
4523 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4524 return false;
4525
4526 return true;
4527}
4528
Douglas Gregor4ad96852009-11-19 07:41:15 +00004529static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4530 ObjCMethodKind WantKind,
4531 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004532 unsigned NumSelIdents,
4533 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004534 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004535 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004536}
Douglas Gregord36adf52010-09-16 16:06:31 +00004537
4538namespace {
4539 /// \brief A set of selectors, which is used to avoid introducing multiple
4540 /// completions with the same selector into the result set.
4541 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4542}
4543
Douglas Gregor36ecb042009-11-17 23:22:23 +00004544/// \brief Add all of the Objective-C methods in the given Objective-C
4545/// container to the set of results.
4546///
4547/// The container will be a class, protocol, category, or implementation of
4548/// any of the above. This mether will recurse to include methods from
4549/// the superclasses of classes along with their categories, protocols, and
4550/// implementations.
4551///
4552/// \param Container the container in which we'll look to find methods.
4553///
4554/// \param WantInstance whether to add instance methods (only); if false, this
4555/// routine will add factory methods (only).
4556///
4557/// \param CurContext the context in which we're performing the lookup that
4558/// finds methods.
4559///
Douglas Gregorcf544262010-11-17 21:36:08 +00004560/// \param AllowSameLength Whether we allow a method to be added to the list
4561/// when it has the same number of parameters as we have selector identifiers.
4562///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004563/// \param Results the structure into which we'll add results.
4564static void AddObjCMethods(ObjCContainerDecl *Container,
4565 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004566 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004567 IdentifierInfo **SelIdents,
4568 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004569 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004570 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004571 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004572 ResultBuilder &Results,
4573 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004574 typedef CodeCompletionResult Result;
Douglas Gregor36ecb042009-11-17 23:22:23 +00004575 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4576 MEnd = Container->meth_end();
4577 M != MEnd; ++M) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004578 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4579 // Check whether the selector identifiers we've been given are a
4580 // subset of the identifiers for this particular method.
Douglas Gregorcf544262010-11-17 21:36:08 +00004581 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4582 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004583 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004584
Douglas Gregord36adf52010-09-16 16:06:31 +00004585 if (!Selectors.insert((*M)->getSelector()))
4586 continue;
4587
Douglas Gregord3c68542009-11-19 01:08:35 +00004588 Result R = Result(*M, 0);
4589 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004590 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004591 if (!InOriginalClass)
4592 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004593 Results.MaybeAddResult(R, CurContext);
4594 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004595 }
4596
Douglas Gregore396c7b2010-09-16 15:34:59 +00004597 // Visit the protocols of protocols.
4598 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004599 if (Protocol->hasDefinition()) {
4600 const ObjCList<ObjCProtocolDecl> &Protocols
4601 = Protocol->getReferencedProtocols();
4602 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4603 E = Protocols.end();
4604 I != E; ++I)
4605 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4606 NumSelIdents, CurContext, Selectors, AllowSameLength,
4607 Results, false);
4608 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004609 }
4610
Douglas Gregor36ecb042009-11-17 23:22:23 +00004611 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004612 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004613 return;
4614
4615 // Add methods in protocols.
4616 const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols();
4617 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4618 E = Protocols.end();
4619 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004620 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004621 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004622
4623 // Add methods in categories.
4624 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4625 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004626 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004627 NumSelIdents, CurContext, Selectors, AllowSameLength,
4628 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004629
4630 // Add a categories protocol methods.
4631 const ObjCList<ObjCProtocolDecl> &Protocols
4632 = CatDecl->getReferencedProtocols();
4633 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4634 E = Protocols.end();
4635 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004636 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004637 NumSelIdents, CurContext, Selectors, AllowSameLength,
4638 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004639
4640 // Add methods in category implementations.
4641 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004642 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004643 NumSelIdents, CurContext, Selectors, AllowSameLength,
4644 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004645 }
4646
4647 // Add methods in superclass.
4648 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004649 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004650 SelIdents, NumSelIdents, CurContext, Selectors,
4651 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004652
4653 // Add methods in our implementation, if any.
4654 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004655 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004656 NumSelIdents, CurContext, Selectors, AllowSameLength,
4657 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004658}
4659
4660
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004661void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004662 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004663
4664 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004665 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004666 if (!Class) {
4667 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004668 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004669 Class = Category->getClassInterface();
4670
4671 if (!Class)
4672 return;
4673 }
4674
4675 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004676 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4677 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004678 Results.EnterNewScope();
4679
Douglas Gregord36adf52010-09-16 16:06:31 +00004680 VisitedSelectorSet Selectors;
4681 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004682 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004683 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004684 HandleCodeCompleteResults(this, CodeCompleter,
4685 CodeCompletionContext::CCC_Other,
4686 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004687}
4688
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004689void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004690 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004691
4692 // Try to find the interface where setters might live.
4693 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004694 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004695 if (!Class) {
4696 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004697 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004698 Class = Category->getClassInterface();
4699
4700 if (!Class)
4701 return;
4702 }
4703
4704 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004705 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4706 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004707 Results.EnterNewScope();
4708
Douglas Gregord36adf52010-09-16 16:06:31 +00004709 VisitedSelectorSet Selectors;
4710 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004711 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004712
4713 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004714 HandleCodeCompleteResults(this, CodeCompleter,
4715 CodeCompletionContext::CCC_Other,
4716 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004717}
4718
Douglas Gregorafc45782011-02-15 22:19:42 +00004719void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4720 bool IsParameter) {
John McCall0a2c5e22010-08-25 06:19:51 +00004721 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004722 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4723 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004724 Results.EnterNewScope();
4725
4726 // Add context-sensitive, Objective-C parameter-passing keywords.
4727 bool AddedInOut = false;
4728 if ((DS.getObjCDeclQualifier() &
4729 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4730 Results.AddResult("in");
4731 Results.AddResult("inout");
4732 AddedInOut = true;
4733 }
4734 if ((DS.getObjCDeclQualifier() &
4735 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4736 Results.AddResult("out");
4737 if (!AddedInOut)
4738 Results.AddResult("inout");
4739 }
4740 if ((DS.getObjCDeclQualifier() &
4741 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4742 ObjCDeclSpec::DQ_Oneway)) == 0) {
4743 Results.AddResult("bycopy");
4744 Results.AddResult("byref");
4745 Results.AddResult("oneway");
4746 }
4747
Douglas Gregorafc45782011-02-15 22:19:42 +00004748 // If we're completing the return type of an Objective-C method and the
4749 // identifier IBAction refers to a macro, provide a completion item for
4750 // an action, e.g.,
4751 // IBAction)<#selector#>:(id)sender
4752 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4753 Context.Idents.get("IBAction").hasMacroDefinition()) {
4754 typedef CodeCompletionString::Chunk Chunk;
4755 CodeCompletionBuilder Builder(Results.getAllocator(), CCP_CodePattern,
4756 CXAvailability_Available);
4757 Builder.AddTypedTextChunk("IBAction");
4758 Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
4759 Builder.AddPlaceholderChunk("selector");
4760 Builder.AddChunk(Chunk(CodeCompletionString::CK_Colon));
4761 Builder.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
4762 Builder.AddTextChunk("id");
4763 Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
4764 Builder.AddTextChunk("sender");
4765 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4766 }
4767
Douglas Gregord32b0222010-08-24 01:06:58 +00004768 // Add various builtin type names and specifiers.
4769 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4770 Results.ExitScope();
4771
4772 // Add the various type names
4773 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4774 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4775 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4776 CodeCompleter->includeGlobals());
4777
4778 if (CodeCompleter->includeMacros())
4779 AddMacroResults(PP, Results);
4780
4781 HandleCodeCompleteResults(this, CodeCompleter,
4782 CodeCompletionContext::CCC_Type,
4783 Results.data(), Results.size());
4784}
4785
Douglas Gregor22f56992010-04-06 19:22:33 +00004786/// \brief When we have an expression with type "id", we may assume
4787/// that it has some more-specific class type based on knowledge of
4788/// common uses of Objective-C. This routine returns that class type,
4789/// or NULL if no better result could be determined.
4790static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004791 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004792 if (!Msg)
4793 return 0;
4794
4795 Selector Sel = Msg->getSelector();
4796 if (Sel.isNull())
4797 return 0;
4798
4799 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4800 if (!Id)
4801 return 0;
4802
4803 ObjCMethodDecl *Method = Msg->getMethodDecl();
4804 if (!Method)
4805 return 0;
4806
4807 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004808 ObjCInterfaceDecl *IFace = 0;
4809 switch (Msg->getReceiverKind()) {
4810 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004811 if (const ObjCObjectType *ObjType
4812 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4813 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004814 break;
4815
4816 case ObjCMessageExpr::Instance: {
4817 QualType T = Msg->getInstanceReceiver()->getType();
4818 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4819 IFace = Ptr->getInterfaceDecl();
4820 break;
4821 }
4822
4823 case ObjCMessageExpr::SuperInstance:
4824 case ObjCMessageExpr::SuperClass:
4825 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00004826 }
4827
4828 if (!IFace)
4829 return 0;
4830
4831 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4832 if (Method->isInstanceMethod())
4833 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4834 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00004835 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00004836 .Case("autorelease", IFace)
4837 .Case("copy", IFace)
4838 .Case("copyWithZone", IFace)
4839 .Case("mutableCopy", IFace)
4840 .Case("mutableCopyWithZone", IFace)
4841 .Case("awakeFromCoder", IFace)
4842 .Case("replacementObjectFromCoder", IFace)
4843 .Case("class", IFace)
4844 .Case("classForCoder", IFace)
4845 .Case("superclass", Super)
4846 .Default(0);
4847
4848 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4849 .Case("new", IFace)
4850 .Case("alloc", IFace)
4851 .Case("allocWithZone", IFace)
4852 .Case("class", IFace)
4853 .Case("superclass", Super)
4854 .Default(0);
4855}
4856
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004857// Add a special completion for a message send to "super", which fills in the
4858// most likely case of forwarding all of our arguments to the superclass
4859// function.
4860///
4861/// \param S The semantic analysis object.
4862///
4863/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4864/// the "super" keyword. Otherwise, we just need to provide the arguments.
4865///
4866/// \param SelIdents The identifiers in the selector that have already been
4867/// provided as arguments for a send to "super".
4868///
4869/// \param NumSelIdents The number of identifiers in \p SelIdents.
4870///
4871/// \param Results The set of results to augment.
4872///
4873/// \returns the Objective-C method declaration that would be invoked by
4874/// this "super" completion. If NULL, no completion was added.
4875static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4876 IdentifierInfo **SelIdents,
4877 unsigned NumSelIdents,
4878 ResultBuilder &Results) {
4879 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
4880 if (!CurMethod)
4881 return 0;
4882
4883 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
4884 if (!Class)
4885 return 0;
4886
4887 // Try to find a superclass method with the same selector.
4888 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00004889 while ((Class = Class->getSuperClass()) && !SuperMethod) {
4890 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004891 SuperMethod = Class->getMethod(CurMethod->getSelector(),
4892 CurMethod->isInstanceMethod());
4893
Douglas Gregor78bcd912011-02-16 00:51:18 +00004894 // Check in categories or class extensions.
4895 if (!SuperMethod) {
4896 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
4897 Category = Category->getNextClassCategory())
4898 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
4899 CurMethod->isInstanceMethod())))
4900 break;
4901 }
4902 }
4903
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004904 if (!SuperMethod)
4905 return 0;
4906
4907 // Check whether the superclass method has the same signature.
4908 if (CurMethod->param_size() != SuperMethod->param_size() ||
4909 CurMethod->isVariadic() != SuperMethod->isVariadic())
4910 return 0;
4911
4912 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
4913 CurPEnd = CurMethod->param_end(),
4914 SuperP = SuperMethod->param_begin();
4915 CurP != CurPEnd; ++CurP, ++SuperP) {
4916 // Make sure the parameter types are compatible.
4917 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
4918 (*SuperP)->getType()))
4919 return 0;
4920
4921 // Make sure we have a parameter name to forward!
4922 if (!(*CurP)->getIdentifier())
4923 return 0;
4924 }
4925
4926 // We have a superclass method. Now, form the send-to-super completion.
Douglas Gregor218937c2011-02-01 19:23:04 +00004927 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004928
4929 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00004930 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
4931 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004932
4933 // If we need the "super" keyword, add it (plus some spacing).
4934 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004935 Builder.AddTypedTextChunk("super");
4936 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004937 }
4938
4939 Selector Sel = CurMethod->getSelector();
4940 if (Sel.isUnarySelector()) {
4941 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00004942 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004943 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004944 else
Douglas Gregordae68752011-02-01 22:57:45 +00004945 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004946 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004947 } else {
4948 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
4949 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
4950 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004951 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004952
4953 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004954 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004955 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004956 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004957 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004958 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004959 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004960 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00004961 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004962 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004963 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00004964 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004965 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004966 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00004967 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004968 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004969 }
4970 }
4971 }
4972
Douglas Gregor218937c2011-02-01 19:23:04 +00004973 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004974 SuperMethod->isInstanceMethod()
4975 ? CXCursor_ObjCInstanceMethodDecl
4976 : CXCursor_ObjCClassMethodDecl));
4977 return SuperMethod;
4978}
4979
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004980void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004981 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004982 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4983 CodeCompletionContext::CCC_ObjCMessageReceiver,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004984 &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004985
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004986 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4987 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00004988 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4989 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004990
4991 // If we are in an Objective-C method inside a class that has a superclass,
4992 // add "super" as an option.
4993 if (ObjCMethodDecl *Method = getCurMethodDecl())
4994 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004995 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004996 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004997
4998 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
4999 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005000
5001 Results.ExitScope();
5002
5003 if (CodeCompleter->includeMacros())
5004 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005005 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005006 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005007
5008}
5009
Douglas Gregor2725ca82010-04-21 19:57:20 +00005010void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5011 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005012 unsigned NumSelIdents,
5013 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005014 ObjCInterfaceDecl *CDecl = 0;
5015 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5016 // Figure out which interface we're in.
5017 CDecl = CurMethod->getClassInterface();
5018 if (!CDecl)
5019 return;
5020
5021 // Find the superclass of this class.
5022 CDecl = CDecl->getSuperClass();
5023 if (!CDecl)
5024 return;
5025
5026 if (CurMethod->isInstanceMethod()) {
5027 // We are inside an instance method, which means that the message
5028 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005029 // current object.
5030 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005031 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005032 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005033 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005034 }
5035
5036 // Fall through to send to the superclass in CDecl.
5037 } else {
5038 // "super" may be the name of a type or variable. Figure out which
5039 // it is.
5040 IdentifierInfo *Super = &Context.Idents.get("super");
5041 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5042 LookupOrdinaryName);
5043 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5044 // "super" names an interface. Use it.
5045 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005046 if (const ObjCObjectType *Iface
5047 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5048 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005049 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5050 // "super" names an unresolved type; we can't be more specific.
5051 } else {
5052 // Assume that "super" names some kind of value and parse that way.
5053 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005054 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005055 UnqualifiedId id;
5056 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005057 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5058 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005059 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005060 SelIdents, NumSelIdents,
5061 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005062 }
5063
5064 // Fall through
5065 }
5066
John McCallb3d87482010-08-24 05:47:05 +00005067 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005068 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005069 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005070 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005071 NumSelIdents, AtArgumentExpression,
5072 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005073}
5074
Douglas Gregorb9d77572010-09-21 00:03:25 +00005075/// \brief Given a set of code-completion results for the argument of a message
5076/// send, determine the preferred type (if any) for that argument expression.
5077static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5078 unsigned NumSelIdents) {
5079 typedef CodeCompletionResult Result;
5080 ASTContext &Context = Results.getSema().Context;
5081
5082 QualType PreferredType;
5083 unsigned BestPriority = CCP_Unlikely * 2;
5084 Result *ResultsData = Results.data();
5085 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5086 Result &R = ResultsData[I];
5087 if (R.Kind == Result::RK_Declaration &&
5088 isa<ObjCMethodDecl>(R.Declaration)) {
5089 if (R.Priority <= BestPriority) {
5090 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5091 if (NumSelIdents <= Method->param_size()) {
5092 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5093 ->getType();
5094 if (R.Priority < BestPriority || PreferredType.isNull()) {
5095 BestPriority = R.Priority;
5096 PreferredType = MyPreferredType;
5097 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5098 MyPreferredType)) {
5099 PreferredType = QualType();
5100 }
5101 }
5102 }
5103 }
5104 }
5105
5106 return PreferredType;
5107}
5108
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005109static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5110 ParsedType Receiver,
5111 IdentifierInfo **SelIdents,
5112 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005113 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005114 bool IsSuper,
5115 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005116 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005117 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005118
Douglas Gregor24a069f2009-11-17 17:59:40 +00005119 // If the given name refers to an interface type, retrieve the
5120 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005121 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005122 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005123 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005124 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5125 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005126 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005127
Douglas Gregor36ecb042009-11-17 23:22:23 +00005128 // Add all of the factory methods in this Objective-C class, its protocols,
5129 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005130 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005131
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005132 // If this is a send-to-super, try to add the special "super" send
5133 // completion.
5134 if (IsSuper) {
5135 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005136 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5137 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005138 Results.Ignore(SuperMethod);
5139 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005140
Douglas Gregor265f7492010-08-27 15:29:55 +00005141 // If we're inside an Objective-C method definition, prefer its selector to
5142 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005143 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005144 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005145
Douglas Gregord36adf52010-09-16 16:06:31 +00005146 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005147 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005148 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005149 SemaRef.CurContext, Selectors, AtArgumentExpression,
5150 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005151 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005152 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005153
Douglas Gregor719770d2010-04-06 17:30:22 +00005154 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005155 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005156 if (SemaRef.ExternalSource) {
5157 for (uint32_t I = 0,
5158 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005159 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005160 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5161 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005162 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005163
5164 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005165 }
5166 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005167
5168 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5169 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005170 M != MEnd; ++M) {
5171 for (ObjCMethodList *MethList = &M->second.second;
5172 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005173 MethList = MethList->Next) {
5174 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5175 NumSelIdents))
5176 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005177
Douglas Gregor13438f92010-04-06 16:40:00 +00005178 Result R(MethList->Method, 0);
5179 R.StartParameter = NumSelIdents;
5180 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005181 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005182 }
5183 }
5184 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005185
5186 Results.ExitScope();
5187}
Douglas Gregor13438f92010-04-06 16:40:00 +00005188
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005189void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5190 IdentifierInfo **SelIdents,
5191 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005192 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005193 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005194
5195 QualType T = this->GetTypeFromParser(Receiver);
5196
Douglas Gregor218937c2011-02-01 19:23:04 +00005197 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005198 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005199 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005200
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005201 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5202 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005203
5204 // If we're actually at the argument expression (rather than prior to the
5205 // selector), we're actually performing code completion for an expression.
5206 // Determine whether we have a single, best method. If so, we can
5207 // code-complete the expression using the corresponding parameter type as
5208 // our preferred type, improving completion results.
5209 if (AtArgumentExpression) {
5210 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005211 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005212 if (PreferredType.isNull())
5213 CodeCompleteOrdinaryName(S, PCC_Expression);
5214 else
5215 CodeCompleteExpression(S, PreferredType);
5216 return;
5217 }
5218
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005219 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005220 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005221 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005222}
5223
Richard Trieuf81e5a92011-09-09 02:00:50 +00005224void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005225 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005226 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005227 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005228 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005229 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005230
5231 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005232
Douglas Gregor36ecb042009-11-17 23:22:23 +00005233 // If necessary, apply function/array conversion to the receiver.
5234 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005235 if (RecExpr) {
5236 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5237 if (Conv.isInvalid()) // conversion failed. bail.
5238 return;
5239 RecExpr = Conv.take();
5240 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005241 QualType ReceiverType = RecExpr? RecExpr->getType()
5242 : Super? Context.getObjCObjectPointerType(
5243 Context.getObjCInterfaceType(Super))
5244 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005245
Douglas Gregorda892642010-11-08 21:12:30 +00005246 // If we're messaging an expression with type "id" or "Class", check
5247 // whether we know something special about the receiver that allows
5248 // us to assume a more-specific receiver type.
5249 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5250 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5251 if (ReceiverType->isObjCClassType())
5252 return CodeCompleteObjCClassMessage(S,
5253 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5254 SelIdents, NumSelIdents,
5255 AtArgumentExpression, Super);
5256
5257 ReceiverType = Context.getObjCObjectPointerType(
5258 Context.getObjCInterfaceType(IFace));
5259 }
5260
Douglas Gregor36ecb042009-11-17 23:22:23 +00005261 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005262 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005263 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005264 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005265
Douglas Gregor36ecb042009-11-17 23:22:23 +00005266 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005267
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005268 // If this is a send-to-super, try to add the special "super" send
5269 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005270 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005271 if (ObjCMethodDecl *SuperMethod
5272 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5273 Results))
5274 Results.Ignore(SuperMethod);
5275 }
5276
Douglas Gregor265f7492010-08-27 15:29:55 +00005277 // If we're inside an Objective-C method definition, prefer its selector to
5278 // others.
5279 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5280 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005281
Douglas Gregord36adf52010-09-16 16:06:31 +00005282 // Keep track of the selectors we've already added.
5283 VisitedSelectorSet Selectors;
5284
Douglas Gregorf74a4192009-11-18 00:06:18 +00005285 // Handle messages to Class. This really isn't a message to an instance
5286 // method, so we treat it the same way we would treat a message send to a
5287 // class method.
5288 if (ReceiverType->isObjCClassType() ||
5289 ReceiverType->isObjCQualifiedClassType()) {
5290 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5291 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005292 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005293 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005294 }
5295 }
5296 // Handle messages to a qualified ID ("id<foo>").
5297 else if (const ObjCObjectPointerType *QualID
5298 = ReceiverType->getAsObjCQualifiedIdType()) {
5299 // Search protocols for instance methods.
5300 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5301 E = QualID->qual_end();
5302 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005303 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005304 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005305 }
5306 // Handle messages to a pointer to interface type.
5307 else if (const ObjCObjectPointerType *IFacePtr
5308 = ReceiverType->getAsObjCInterfacePointerType()) {
5309 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005310 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005311 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5312 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005313
5314 // Search protocols for instance methods.
5315 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5316 E = IFacePtr->qual_end();
5317 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005318 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005319 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005320 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005321 // Handle messages to "id".
5322 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005323 // We're messaging "id", so provide all instance methods we know
5324 // about as code-completion results.
5325
5326 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005327 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005328 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005329 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5330 I != N; ++I) {
5331 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005332 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005333 continue;
5334
Sebastian Redldb9d2142010-08-02 23:18:59 +00005335 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005336 }
5337 }
5338
Sebastian Redldb9d2142010-08-02 23:18:59 +00005339 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5340 MEnd = MethodPool.end();
5341 M != MEnd; ++M) {
5342 for (ObjCMethodList *MethList = &M->second.first;
5343 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005344 MethList = MethList->Next) {
5345 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5346 NumSelIdents))
5347 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005348
5349 if (!Selectors.insert(MethList->Method->getSelector()))
5350 continue;
5351
Douglas Gregor13438f92010-04-06 16:40:00 +00005352 Result R(MethList->Method, 0);
5353 R.StartParameter = NumSelIdents;
5354 R.AllParametersAreInformative = false;
5355 Results.MaybeAddResult(R, CurContext);
5356 }
5357 }
5358 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005359 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005360
5361
5362 // If we're actually at the argument expression (rather than prior to the
5363 // selector), we're actually performing code completion for an expression.
5364 // Determine whether we have a single, best method. If so, we can
5365 // code-complete the expression using the corresponding parameter type as
5366 // our preferred type, improving completion results.
5367 if (AtArgumentExpression) {
5368 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5369 NumSelIdents);
5370 if (PreferredType.isNull())
5371 CodeCompleteOrdinaryName(S, PCC_Expression);
5372 else
5373 CodeCompleteExpression(S, PreferredType);
5374 return;
5375 }
5376
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005377 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005378 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005379 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005380}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005381
Douglas Gregorfb629412010-08-23 21:17:50 +00005382void Sema::CodeCompleteObjCForCollection(Scope *S,
5383 DeclGroupPtrTy IterationVar) {
5384 CodeCompleteExpressionData Data;
5385 Data.ObjCCollection = true;
5386
5387 if (IterationVar.getAsOpaquePtr()) {
5388 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5389 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5390 if (*I)
5391 Data.IgnoreDecls.push_back(*I);
5392 }
5393 }
5394
5395 CodeCompleteExpression(S, Data);
5396}
5397
Douglas Gregor458433d2010-08-26 15:07:07 +00005398void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5399 unsigned NumSelIdents) {
5400 // If we have an external source, load the entire class method
5401 // pool from the AST file.
5402 if (ExternalSource) {
5403 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5404 I != N; ++I) {
5405 Selector Sel = ExternalSource->GetExternalSelector(I);
5406 if (Sel.isNull() || MethodPool.count(Sel))
5407 continue;
5408
5409 ReadMethodPool(Sel);
5410 }
5411 }
5412
Douglas Gregor218937c2011-02-01 19:23:04 +00005413 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5414 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005415 Results.EnterNewScope();
5416 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5417 MEnd = MethodPool.end();
5418 M != MEnd; ++M) {
5419
5420 Selector Sel = M->first;
5421 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5422 continue;
5423
Douglas Gregor218937c2011-02-01 19:23:04 +00005424 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor458433d2010-08-26 15:07:07 +00005425 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005426 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005427 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005428 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005429 continue;
5430 }
5431
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005432 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005433 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005434 if (I == NumSelIdents) {
5435 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005436 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005437 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005438 Accumulator.clear();
5439 }
5440 }
5441
Benjamin Kramera0651c52011-07-26 16:59:25 +00005442 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005443 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005444 }
Douglas Gregordae68752011-02-01 22:57:45 +00005445 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005446 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005447 }
5448 Results.ExitScope();
5449
5450 HandleCodeCompleteResults(this, CodeCompleter,
5451 CodeCompletionContext::CCC_SelectorName,
5452 Results.data(), Results.size());
5453}
5454
Douglas Gregor55385fe2009-11-18 04:19:12 +00005455/// \brief Add all of the protocol declarations that we find in the given
5456/// (translation unit) context.
5457static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005458 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005459 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005460 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005461
5462 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5463 DEnd = Ctx->decls_end();
5464 D != DEnd; ++D) {
5465 // Record any protocols we find.
5466 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005467 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005468 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005469 }
5470}
5471
5472void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5473 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005474 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5475 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005476
Douglas Gregor70c23352010-12-09 21:44:02 +00005477 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5478 Results.EnterNewScope();
5479
5480 // Tell the result set to ignore all of the protocols we have
5481 // already seen.
5482 // FIXME: This doesn't work when caching code-completion results.
5483 for (unsigned I = 0; I != NumProtocols; ++I)
5484 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5485 Protocols[I].second))
5486 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005487
Douglas Gregor70c23352010-12-09 21:44:02 +00005488 // Add all protocols.
5489 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5490 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005491
Douglas Gregor70c23352010-12-09 21:44:02 +00005492 Results.ExitScope();
5493 }
5494
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005495 HandleCodeCompleteResults(this, CodeCompleter,
5496 CodeCompletionContext::CCC_ObjCProtocolName,
5497 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005498}
5499
5500void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005501 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5502 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005503
Douglas Gregor70c23352010-12-09 21:44:02 +00005504 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5505 Results.EnterNewScope();
5506
5507 // Add all protocols.
5508 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5509 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005510
Douglas Gregor70c23352010-12-09 21:44:02 +00005511 Results.ExitScope();
5512 }
5513
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005514 HandleCodeCompleteResults(this, CodeCompleter,
5515 CodeCompletionContext::CCC_ObjCProtocolName,
5516 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005517}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005518
5519/// \brief Add all of the Objective-C interface declarations that we find in
5520/// the given (translation unit) context.
5521static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5522 bool OnlyForwardDeclarations,
5523 bool OnlyUnimplemented,
5524 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005525 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005526
5527 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5528 DEnd = Ctx->decls_end();
5529 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005530 // Record any interfaces we find.
5531 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005532 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005533 (!OnlyUnimplemented || !Class->getImplementation()))
5534 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005535 }
5536}
5537
5538void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005539 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5540 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005541 Results.EnterNewScope();
5542
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005543 if (CodeCompleter->includeGlobals()) {
5544 // Add all classes.
5545 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5546 false, Results);
5547 }
5548
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005549 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005550
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005551 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005552 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005553 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005554}
5555
Douglas Gregorc83c6872010-04-15 22:33:43 +00005556void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5557 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005558 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005559 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005560 Results.EnterNewScope();
5561
5562 // Make sure that we ignore the class we're currently defining.
5563 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005564 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005565 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005566 Results.Ignore(CurClass);
5567
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005568 if (CodeCompleter->includeGlobals()) {
5569 // Add all classes.
5570 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5571 false, Results);
5572 }
5573
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005574 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005575
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005576 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005577 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005578 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005579}
5580
5581void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005582 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5583 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005584 Results.EnterNewScope();
5585
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005586 if (CodeCompleter->includeGlobals()) {
5587 // Add all unimplemented classes.
5588 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5589 true, Results);
5590 }
5591
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005592 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005593
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005594 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005595 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005596 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005597}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005598
5599void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005600 IdentifierInfo *ClassName,
5601 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005602 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005603
Douglas Gregor218937c2011-02-01 19:23:04 +00005604 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005605 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005606
5607 // Ignore any categories we find that have already been implemented by this
5608 // interface.
5609 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5610 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005611 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005612 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5613 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5614 Category = Category->getNextClassCategory())
5615 CategoryNames.insert(Category->getIdentifier());
5616
5617 // Add all of the categories we know about.
5618 Results.EnterNewScope();
5619 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5620 for (DeclContext::decl_iterator D = TU->decls_begin(),
5621 DEnd = TU->decls_end();
5622 D != DEnd; ++D)
5623 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5624 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005625 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005626 Results.ExitScope();
5627
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005628 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005629 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005630 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005631}
5632
5633void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005634 IdentifierInfo *ClassName,
5635 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005636 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005637
5638 // Find the corresponding interface. If we couldn't find the interface, the
5639 // program itself is ill-formed. However, we'll try to be helpful still by
5640 // providing the list of all of the categories we know about.
5641 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005642 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005643 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5644 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005645 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005646
Douglas Gregor218937c2011-02-01 19:23:04 +00005647 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005648 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005649
5650 // Add all of the categories that have have corresponding interface
5651 // declarations in this class and any of its superclasses, except for
5652 // already-implemented categories in the class itself.
5653 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5654 Results.EnterNewScope();
5655 bool IgnoreImplemented = true;
5656 while (Class) {
5657 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5658 Category = Category->getNextClassCategory())
5659 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5660 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005661 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005662
5663 Class = Class->getSuperClass();
5664 IgnoreImplemented = false;
5665 }
5666 Results.ExitScope();
5667
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005668 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005669 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005670 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005671}
Douglas Gregor322328b2009-11-18 22:32:06 +00005672
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005673void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005674 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005675 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5676 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005677
5678 // Figure out where this @synthesize lives.
5679 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005680 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005681 if (!Container ||
5682 (!isa<ObjCImplementationDecl>(Container) &&
5683 !isa<ObjCCategoryImplDecl>(Container)))
5684 return;
5685
5686 // Ignore any properties that have already been implemented.
5687 for (DeclContext::decl_iterator D = Container->decls_begin(),
5688 DEnd = Container->decls_end();
5689 D != DEnd; ++D)
5690 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5691 Results.Ignore(PropertyImpl->getPropertyDecl());
5692
5693 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005694 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005695 Results.EnterNewScope();
5696 if (ObjCImplementationDecl *ClassImpl
5697 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005698 AddObjCProperties(ClassImpl->getClassInterface(), false,
5699 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005700 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005701 else
5702 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005703 false, /*AllowNullaryMethods=*/false, CurContext,
5704 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005705 Results.ExitScope();
5706
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005707 HandleCodeCompleteResults(this, CodeCompleter,
5708 CodeCompletionContext::CCC_Other,
5709 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005710}
5711
5712void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005713 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005714 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005715 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5716 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005717
5718 // Figure out where this @synthesize lives.
5719 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005720 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005721 if (!Container ||
5722 (!isa<ObjCImplementationDecl>(Container) &&
5723 !isa<ObjCCategoryImplDecl>(Container)))
5724 return;
5725
5726 // Figure out which interface we're looking into.
5727 ObjCInterfaceDecl *Class = 0;
5728 if (ObjCImplementationDecl *ClassImpl
5729 = dyn_cast<ObjCImplementationDecl>(Container))
5730 Class = ClassImpl->getClassInterface();
5731 else
5732 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5733 ->getClassInterface();
5734
Douglas Gregore8426052011-04-18 14:40:46 +00005735 // Determine the type of the property we're synthesizing.
5736 QualType PropertyType = Context.getObjCIdType();
5737 if (Class) {
5738 if (ObjCPropertyDecl *Property
5739 = Class->FindPropertyDeclaration(PropertyName)) {
5740 PropertyType
5741 = Property->getType().getNonReferenceType().getUnqualifiedType();
5742
5743 // Give preference to ivars
5744 Results.setPreferredType(PropertyType);
5745 }
5746 }
5747
Douglas Gregor322328b2009-11-18 22:32:06 +00005748 // Add all of the instance variables in this class and its superclasses.
5749 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005750 bool SawSimilarlyNamedIvar = false;
5751 std::string NameWithPrefix;
5752 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005753 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005754 std::string NameWithSuffix = PropertyName->getName().str();
5755 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005756 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005757 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5758 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005759 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5760
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005761 // Determine whether we've seen an ivar with a name similar to the
5762 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005763 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005764 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005765 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005766 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005767
5768 // Reduce the priority of this result by one, to give it a slight
5769 // advantage over other results whose names don't match so closely.
5770 if (Results.size() &&
5771 Results.data()[Results.size() - 1].Kind
5772 == CodeCompletionResult::RK_Declaration &&
5773 Results.data()[Results.size() - 1].Declaration == Ivar)
5774 Results.data()[Results.size() - 1].Priority--;
5775 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005776 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005777 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005778
5779 if (!SawSimilarlyNamedIvar) {
5780 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005781 // an ivar of the appropriate type.
5782 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005783 typedef CodeCompletionResult Result;
5784 CodeCompletionAllocator &Allocator = Results.getAllocator();
5785 CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available);
5786
Douglas Gregor8987b232011-09-27 23:30:47 +00005787 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00005788 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005789 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005790 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5791 Results.AddResult(Result(Builder.TakeString(), Priority,
5792 CXCursor_ObjCIvarDecl));
5793 }
5794
Douglas Gregor322328b2009-11-18 22:32:06 +00005795 Results.ExitScope();
5796
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005797 HandleCodeCompleteResults(this, CodeCompleter,
5798 CodeCompletionContext::CCC_Other,
5799 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005800}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005801
Douglas Gregor408be5a2010-08-25 01:08:01 +00005802// Mapping from selectors to the methods that implement that selector, along
5803// with the "in original class" flag.
5804typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5805 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005806
5807/// \brief Find all of the methods that reside in the given container
5808/// (and its superclasses, protocols, etc.) that meet the given
5809/// criteria. Insert those methods into the map of known methods,
5810/// indexed by selector so they can be easily found.
5811static void FindImplementableMethods(ASTContext &Context,
5812 ObjCContainerDecl *Container,
5813 bool WantInstanceMethods,
5814 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00005815 KnownMethodsMap &KnownMethods,
5816 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005817 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5818 // Recurse into protocols.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00005819 if (!IFace->hasDefinition())
5820 return;
5821
Douglas Gregore8f5a172010-04-07 00:21:17 +00005822 const ObjCList<ObjCProtocolDecl> &Protocols
5823 = IFace->getReferencedProtocols();
5824 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005825 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005826 I != E; ++I)
5827 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005828 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005829
Douglas Gregorea766182010-10-18 18:21:28 +00005830 // Add methods from any class extensions and categories.
5831 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5832 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00005833 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5834 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005835 KnownMethods, false);
5836
5837 // Visit the superclass.
5838 if (IFace->getSuperClass())
5839 FindImplementableMethods(Context, IFace->getSuperClass(),
5840 WantInstanceMethods, ReturnType,
5841 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005842 }
5843
5844 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5845 // Recurse into protocols.
5846 const ObjCList<ObjCProtocolDecl> &Protocols
5847 = Category->getReferencedProtocols();
5848 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005849 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005850 I != E; ++I)
5851 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005852 KnownMethods, InOriginalClass);
5853
5854 // If this category is the original class, jump to the interface.
5855 if (InOriginalClass && Category->getClassInterface())
5856 FindImplementableMethods(Context, Category->getClassInterface(),
5857 WantInstanceMethods, ReturnType, KnownMethods,
5858 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005859 }
5860
5861 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005862 if (Protocol->hasDefinition()) {
5863 // Recurse into protocols.
5864 const ObjCList<ObjCProtocolDecl> &Protocols
5865 = Protocol->getReferencedProtocols();
5866 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5867 E = Protocols.end();
5868 I != E; ++I)
5869 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
5870 KnownMethods, false);
5871 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00005872 }
5873
5874 // Add methods in this container. This operation occurs last because
5875 // we want the methods from this container to override any methods
5876 // we've previously seen with the same selector.
5877 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
5878 MEnd = Container->meth_end();
5879 M != MEnd; ++M) {
5880 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
5881 if (!ReturnType.isNull() &&
5882 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
5883 continue;
5884
Douglas Gregor408be5a2010-08-25 01:08:01 +00005885 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005886 }
5887 }
5888}
5889
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005890/// \brief Add the parenthesized return or parameter type chunk to a code
5891/// completion string.
5892static void AddObjCPassingTypeChunk(QualType Type,
5893 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005894 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005895 CodeCompletionBuilder &Builder) {
5896 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor8987b232011-09-27 23:30:47 +00005897 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005898 Builder.getAllocator()));
5899 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5900}
5901
5902/// \brief Determine whether the given class is or inherits from a class by
5903/// the given name.
5904static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00005905 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005906 if (!Class)
5907 return false;
5908
5909 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
5910 return true;
5911
5912 return InheritsFromClassNamed(Class->getSuperClass(), Name);
5913}
5914
5915/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
5916/// Key-Value Observing (KVO).
5917static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
5918 bool IsInstanceMethod,
5919 QualType ReturnType,
5920 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00005921 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005922 ResultBuilder &Results) {
5923 IdentifierInfo *PropName = Property->getIdentifier();
5924 if (!PropName || PropName->getLength() == 0)
5925 return;
5926
Douglas Gregor8987b232011-09-27 23:30:47 +00005927 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
5928
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005929 // Builder that will create each code completion.
5930 typedef CodeCompletionResult Result;
5931 CodeCompletionAllocator &Allocator = Results.getAllocator();
5932 CodeCompletionBuilder Builder(Allocator);
5933
5934 // The selector table.
5935 SelectorTable &Selectors = Context.Selectors;
5936
5937 // The property name, copied into the code completion allocation region
5938 // on demand.
5939 struct KeyHolder {
5940 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00005941 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005942 const char *CopiedKey;
5943
Chris Lattner5f9e2722011-07-23 10:55:15 +00005944 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005945 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
5946
5947 operator const char *() {
5948 if (CopiedKey)
5949 return CopiedKey;
5950
5951 return CopiedKey = Allocator.CopyString(Key);
5952 }
5953 } Key(Allocator, PropName->getName());
5954
5955 // The uppercased name of the property name.
5956 std::string UpperKey = PropName->getName();
5957 if (!UpperKey.empty())
5958 UpperKey[0] = toupper(UpperKey[0]);
5959
5960 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
5961 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
5962 Property->getType());
5963 bool ReturnTypeMatchesVoid
5964 = ReturnType.isNull() || ReturnType->isVoidType();
5965
5966 // Add the normal accessor -(type)key.
5967 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00005968 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005969 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
5970 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00005971 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005972
5973 Builder.AddTypedTextChunk(Key);
5974 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
5975 CXCursor_ObjCInstanceMethodDecl));
5976 }
5977
5978 // If we have an integral or boolean property (or the user has provided
5979 // an integral or boolean return type), add the accessor -(type)isKey.
5980 if (IsInstanceMethod &&
5981 ((!ReturnType.isNull() &&
5982 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
5983 (ReturnType.isNull() &&
5984 (Property->getType()->isIntegerType() ||
5985 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00005986 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00005987 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00005988 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005989 if (ReturnType.isNull()) {
5990 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5991 Builder.AddTextChunk("BOOL");
5992 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5993 }
5994
5995 Builder.AddTypedTextChunk(
5996 Allocator.CopyString(SelectorId->getName()));
5997 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
5998 CXCursor_ObjCInstanceMethodDecl));
5999 }
6000 }
6001
6002 // Add the normal mutator.
6003 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6004 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006005 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006006 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006007 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006008 if (ReturnType.isNull()) {
6009 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6010 Builder.AddTextChunk("void");
6011 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6012 }
6013
6014 Builder.AddTypedTextChunk(
6015 Allocator.CopyString(SelectorId->getName()));
6016 Builder.AddTypedTextChunk(":");
Douglas Gregor8987b232011-09-27 23:30:47 +00006017 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006018 Builder.AddTextChunk(Key);
6019 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6020 CXCursor_ObjCInstanceMethodDecl));
6021 }
6022 }
6023
6024 // Indexed and unordered accessors
6025 unsigned IndexedGetterPriority = CCP_CodePattern;
6026 unsigned IndexedSetterPriority = CCP_CodePattern;
6027 unsigned UnorderedGetterPriority = CCP_CodePattern;
6028 unsigned UnorderedSetterPriority = CCP_CodePattern;
6029 if (const ObjCObjectPointerType *ObjCPointer
6030 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6031 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6032 // If this interface type is not provably derived from a known
6033 // collection, penalize the corresponding completions.
6034 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6035 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6036 if (!InheritsFromClassNamed(IFace, "NSArray"))
6037 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6038 }
6039
6040 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6041 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6042 if (!InheritsFromClassNamed(IFace, "NSSet"))
6043 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6044 }
6045 }
6046 } else {
6047 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6048 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6049 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6050 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6051 }
6052
6053 // Add -(NSUInteger)countOf<key>
6054 if (IsInstanceMethod &&
6055 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006056 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006057 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006058 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006059 if (ReturnType.isNull()) {
6060 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6061 Builder.AddTextChunk("NSUInteger");
6062 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6063 }
6064
6065 Builder.AddTypedTextChunk(
6066 Allocator.CopyString(SelectorId->getName()));
6067 Results.AddResult(Result(Builder.TakeString(),
6068 std::min(IndexedGetterPriority,
6069 UnorderedGetterPriority),
6070 CXCursor_ObjCInstanceMethodDecl));
6071 }
6072 }
6073
6074 // Indexed getters
6075 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6076 if (IsInstanceMethod &&
6077 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006078 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006079 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006080 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006081 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006082 if (ReturnType.isNull()) {
6083 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6084 Builder.AddTextChunk("id");
6085 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6086 }
6087
6088 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6089 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6090 Builder.AddTextChunk("NSUInteger");
6091 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6092 Builder.AddTextChunk("index");
6093 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6094 CXCursor_ObjCInstanceMethodDecl));
6095 }
6096 }
6097
6098 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6099 if (IsInstanceMethod &&
6100 (ReturnType.isNull() ||
6101 (ReturnType->isObjCObjectPointerType() &&
6102 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6103 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6104 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006105 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006106 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006107 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006108 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006109 if (ReturnType.isNull()) {
6110 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6111 Builder.AddTextChunk("NSArray *");
6112 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6113 }
6114
6115 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6116 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6117 Builder.AddTextChunk("NSIndexSet *");
6118 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6119 Builder.AddTextChunk("indexes");
6120 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6121 CXCursor_ObjCInstanceMethodDecl));
6122 }
6123 }
6124
6125 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6126 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006127 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006128 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006129 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006130 &Context.Idents.get("range")
6131 };
6132
Douglas Gregore74c25c2011-05-04 23:50:46 +00006133 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006134 if (ReturnType.isNull()) {
6135 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6136 Builder.AddTextChunk("void");
6137 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6138 }
6139
6140 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6141 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6142 Builder.AddPlaceholderChunk("object-type");
6143 Builder.AddTextChunk(" **");
6144 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6145 Builder.AddTextChunk("buffer");
6146 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6147 Builder.AddTypedTextChunk("range:");
6148 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6149 Builder.AddTextChunk("NSRange");
6150 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6151 Builder.AddTextChunk("inRange");
6152 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6153 CXCursor_ObjCInstanceMethodDecl));
6154 }
6155 }
6156
6157 // Mutable indexed accessors
6158
6159 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6160 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006161 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006162 IdentifierInfo *SelectorIds[2] = {
6163 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006164 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006165 };
6166
Douglas Gregore74c25c2011-05-04 23:50:46 +00006167 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006168 if (ReturnType.isNull()) {
6169 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6170 Builder.AddTextChunk("void");
6171 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6172 }
6173
6174 Builder.AddTypedTextChunk("insertObject:");
6175 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6176 Builder.AddPlaceholderChunk("object-type");
6177 Builder.AddTextChunk(" *");
6178 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6179 Builder.AddTextChunk("object");
6180 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6181 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6182 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6183 Builder.AddPlaceholderChunk("NSUInteger");
6184 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6185 Builder.AddTextChunk("index");
6186 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6187 CXCursor_ObjCInstanceMethodDecl));
6188 }
6189 }
6190
6191 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6192 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006193 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006194 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006195 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006196 &Context.Idents.get("atIndexes")
6197 };
6198
Douglas Gregore74c25c2011-05-04 23:50:46 +00006199 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006200 if (ReturnType.isNull()) {
6201 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6202 Builder.AddTextChunk("void");
6203 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6204 }
6205
6206 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6207 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6208 Builder.AddTextChunk("NSArray *");
6209 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6210 Builder.AddTextChunk("array");
6211 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6212 Builder.AddTypedTextChunk("atIndexes:");
6213 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6214 Builder.AddPlaceholderChunk("NSIndexSet *");
6215 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6216 Builder.AddTextChunk("indexes");
6217 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6218 CXCursor_ObjCInstanceMethodDecl));
6219 }
6220 }
6221
6222 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6223 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006224 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006225 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006226 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006227 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006228 if (ReturnType.isNull()) {
6229 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6230 Builder.AddTextChunk("void");
6231 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6232 }
6233
6234 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6235 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6236 Builder.AddTextChunk("NSUInteger");
6237 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6238 Builder.AddTextChunk("index");
6239 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6240 CXCursor_ObjCInstanceMethodDecl));
6241 }
6242 }
6243
6244 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6245 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006246 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006247 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006248 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006249 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006250 if (ReturnType.isNull()) {
6251 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6252 Builder.AddTextChunk("void");
6253 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6254 }
6255
6256 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6257 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6258 Builder.AddTextChunk("NSIndexSet *");
6259 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6260 Builder.AddTextChunk("indexes");
6261 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6262 CXCursor_ObjCInstanceMethodDecl));
6263 }
6264 }
6265
6266 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6267 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006268 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006269 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006270 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006271 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006272 &Context.Idents.get("withObject")
6273 };
6274
Douglas Gregore74c25c2011-05-04 23:50:46 +00006275 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006276 if (ReturnType.isNull()) {
6277 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6278 Builder.AddTextChunk("void");
6279 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6280 }
6281
6282 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6283 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6284 Builder.AddPlaceholderChunk("NSUInteger");
6285 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6286 Builder.AddTextChunk("index");
6287 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6288 Builder.AddTypedTextChunk("withObject:");
6289 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6290 Builder.AddTextChunk("id");
6291 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6292 Builder.AddTextChunk("object");
6293 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6294 CXCursor_ObjCInstanceMethodDecl));
6295 }
6296 }
6297
6298 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6299 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006300 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006301 = (Twine("replace") + UpperKey + "AtIndexes").str();
6302 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006303 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006304 &Context.Idents.get(SelectorName1),
6305 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006306 };
6307
Douglas Gregore74c25c2011-05-04 23:50:46 +00006308 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006309 if (ReturnType.isNull()) {
6310 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6311 Builder.AddTextChunk("void");
6312 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6313 }
6314
6315 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6316 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6317 Builder.AddPlaceholderChunk("NSIndexSet *");
6318 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6319 Builder.AddTextChunk("indexes");
6320 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6321 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6322 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6323 Builder.AddTextChunk("NSArray *");
6324 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6325 Builder.AddTextChunk("array");
6326 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6327 CXCursor_ObjCInstanceMethodDecl));
6328 }
6329 }
6330
6331 // Unordered getters
6332 // - (NSEnumerator *)enumeratorOfKey
6333 if (IsInstanceMethod &&
6334 (ReturnType.isNull() ||
6335 (ReturnType->isObjCObjectPointerType() &&
6336 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6337 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6338 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006339 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006340 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006341 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006342 if (ReturnType.isNull()) {
6343 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6344 Builder.AddTextChunk("NSEnumerator *");
6345 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6346 }
6347
6348 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6349 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6350 CXCursor_ObjCInstanceMethodDecl));
6351 }
6352 }
6353
6354 // - (type *)memberOfKey:(type *)object
6355 if (IsInstanceMethod &&
6356 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006357 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006358 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006359 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006360 if (ReturnType.isNull()) {
6361 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6362 Builder.AddPlaceholderChunk("object-type");
6363 Builder.AddTextChunk(" *");
6364 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6365 }
6366
6367 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6368 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6369 if (ReturnType.isNull()) {
6370 Builder.AddPlaceholderChunk("object-type");
6371 Builder.AddTextChunk(" *");
6372 } else {
6373 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006374 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006375 Builder.getAllocator()));
6376 }
6377 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6378 Builder.AddTextChunk("object");
6379 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6380 CXCursor_ObjCInstanceMethodDecl));
6381 }
6382 }
6383
6384 // Mutable unordered accessors
6385 // - (void)addKeyObject:(type *)object
6386 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006387 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006388 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006389 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006390 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006391 if (ReturnType.isNull()) {
6392 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6393 Builder.AddTextChunk("void");
6394 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6395 }
6396
6397 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6398 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6399 Builder.AddPlaceholderChunk("object-type");
6400 Builder.AddTextChunk(" *");
6401 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6402 Builder.AddTextChunk("object");
6403 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6404 CXCursor_ObjCInstanceMethodDecl));
6405 }
6406 }
6407
6408 // - (void)addKey:(NSSet *)objects
6409 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006410 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006411 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006412 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006413 if (ReturnType.isNull()) {
6414 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6415 Builder.AddTextChunk("void");
6416 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6417 }
6418
6419 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6420 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6421 Builder.AddTextChunk("NSSet *");
6422 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6423 Builder.AddTextChunk("objects");
6424 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6425 CXCursor_ObjCInstanceMethodDecl));
6426 }
6427 }
6428
6429 // - (void)removeKeyObject:(type *)object
6430 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006431 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006432 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006433 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006434 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006435 if (ReturnType.isNull()) {
6436 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6437 Builder.AddTextChunk("void");
6438 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6439 }
6440
6441 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6442 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6443 Builder.AddPlaceholderChunk("object-type");
6444 Builder.AddTextChunk(" *");
6445 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6446 Builder.AddTextChunk("object");
6447 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6448 CXCursor_ObjCInstanceMethodDecl));
6449 }
6450 }
6451
6452 // - (void)removeKey:(NSSet *)objects
6453 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006454 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006455 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006456 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006457 if (ReturnType.isNull()) {
6458 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6459 Builder.AddTextChunk("void");
6460 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6461 }
6462
6463 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6464 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6465 Builder.AddTextChunk("NSSet *");
6466 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6467 Builder.AddTextChunk("objects");
6468 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6469 CXCursor_ObjCInstanceMethodDecl));
6470 }
6471 }
6472
6473 // - (void)intersectKey:(NSSet *)objects
6474 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006475 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006476 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006477 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006478 if (ReturnType.isNull()) {
6479 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6480 Builder.AddTextChunk("void");
6481 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6482 }
6483
6484 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6485 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6486 Builder.AddTextChunk("NSSet *");
6487 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6488 Builder.AddTextChunk("objects");
6489 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6490 CXCursor_ObjCInstanceMethodDecl));
6491 }
6492 }
6493
6494 // Key-Value Observing
6495 // + (NSSet *)keyPathsForValuesAffectingKey
6496 if (!IsInstanceMethod &&
6497 (ReturnType.isNull() ||
6498 (ReturnType->isObjCObjectPointerType() &&
6499 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6500 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6501 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006502 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006503 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006504 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006505 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006506 if (ReturnType.isNull()) {
6507 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6508 Builder.AddTextChunk("NSSet *");
6509 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6510 }
6511
6512 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6513 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006514 CXCursor_ObjCClassMethodDecl));
6515 }
6516 }
6517
6518 // + (BOOL)automaticallyNotifiesObserversForKey
6519 if (!IsInstanceMethod &&
6520 (ReturnType.isNull() ||
6521 ReturnType->isIntegerType() ||
6522 ReturnType->isBooleanType())) {
6523 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006524 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006525 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6526 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6527 if (ReturnType.isNull()) {
6528 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6529 Builder.AddTextChunk("BOOL");
6530 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6531 }
6532
6533 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6534 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6535 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006536 }
6537 }
6538}
6539
Douglas Gregore8f5a172010-04-07 00:21:17 +00006540void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6541 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006542 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006543 // Determine the return type of the method we're declaring, if
6544 // provided.
6545 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006546 Decl *IDecl = 0;
6547 if (CurContext->isObjCContainer()) {
6548 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6549 IDecl = cast<Decl>(OCD);
6550 }
Douglas Gregorea766182010-10-18 18:21:28 +00006551 // Determine where we should start searching for methods.
6552 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006553 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006554 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006555 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6556 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006557 IsInImplementation = true;
6558 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006559 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006560 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006561 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006562 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006563 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006564 }
6565
6566 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006567 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006568 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006569 }
6570
Douglas Gregorea766182010-10-18 18:21:28 +00006571 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006572 HandleCodeCompleteResults(this, CodeCompleter,
6573 CodeCompletionContext::CCC_Other,
6574 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006575 return;
6576 }
6577
6578 // Find all of the methods that we could declare/implement here.
6579 KnownMethodsMap KnownMethods;
6580 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006581 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006582
Douglas Gregore8f5a172010-04-07 00:21:17 +00006583 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006584 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006585 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6586 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006587 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006588 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006589 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6590 MEnd = KnownMethods.end();
6591 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006592 ObjCMethodDecl *Method = M->second.first;
Douglas Gregor218937c2011-02-01 19:23:04 +00006593 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006594
6595 // If the result type was not already provided, add it to the
6596 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006597 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00006598 AddObjCPassingTypeChunk(Method->getResultType(), Context, Policy,
6599 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006600
6601 Selector Sel = Method->getSelector();
6602
6603 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006604 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006605 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006606
6607 // Add parameters to the pattern.
6608 unsigned I = 0;
6609 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6610 PEnd = Method->param_end();
6611 P != PEnd; (void)++P, ++I) {
6612 // Add the part of the selector name.
6613 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006614 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006615 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006616 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6617 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006618 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006619 } else
6620 break;
6621
6622 // Add the parameter type.
Douglas Gregor8987b232011-09-27 23:30:47 +00006623 AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Policy,
6624 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006625
6626 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006627 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006628 }
6629
6630 if (Method->isVariadic()) {
6631 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006632 Builder.AddChunk(CodeCompletionString::CK_Comma);
6633 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006634 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006635
Douglas Gregor447107d2010-05-28 00:57:46 +00006636 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006637 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006638 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6639 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6640 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006641 if (!Method->getResultType()->isVoidType()) {
6642 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006643 Builder.AddTextChunk("return");
6644 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6645 Builder.AddPlaceholderChunk("expression");
6646 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006647 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006648 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006649
Douglas Gregor218937c2011-02-01 19:23:04 +00006650 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6651 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006652 }
6653
Douglas Gregor408be5a2010-08-25 01:08:01 +00006654 unsigned Priority = CCP_CodePattern;
6655 if (!M->second.second)
6656 Priority += CCD_InBaseClass;
6657
Douglas Gregor218937c2011-02-01 19:23:04 +00006658 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor16ed9ad2010-08-17 16:06:07 +00006659 Method->isInstanceMethod()
6660 ? CXCursor_ObjCInstanceMethodDecl
6661 : CXCursor_ObjCClassMethodDecl));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006662 }
6663
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006664 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6665 // the properties in this class and its categories.
6666 if (Context.getLangOptions().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006667 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006668 Containers.push_back(SearchDecl);
6669
Douglas Gregore74c25c2011-05-04 23:50:46 +00006670 VisitedSelectorSet KnownSelectors;
6671 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6672 MEnd = KnownMethods.end();
6673 M != MEnd; ++M)
6674 KnownSelectors.insert(M->first);
6675
6676
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006677 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6678 if (!IFace)
6679 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6680 IFace = Category->getClassInterface();
6681
6682 if (IFace) {
6683 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6684 Category = Category->getNextClassCategory())
6685 Containers.push_back(Category);
6686 }
6687
6688 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6689 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6690 PEnd = Containers[I]->prop_end();
6691 P != PEnd; ++P) {
6692 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006693 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006694 }
6695 }
6696 }
6697
Douglas Gregore8f5a172010-04-07 00:21:17 +00006698 Results.ExitScope();
6699
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006700 HandleCodeCompleteResults(this, CodeCompleter,
6701 CodeCompletionContext::CCC_Other,
6702 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006703}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006704
6705void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6706 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006707 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006708 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006709 IdentifierInfo **SelIdents,
6710 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006711 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006712 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006713 if (ExternalSource) {
6714 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6715 I != N; ++I) {
6716 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006717 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006718 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006719
6720 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006721 }
6722 }
6723
6724 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006725 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006726 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6727 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006728
6729 if (ReturnTy)
6730 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006731
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006732 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006733 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6734 MEnd = MethodPool.end();
6735 M != MEnd; ++M) {
6736 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6737 &M->second.second;
6738 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006739 MethList = MethList->Next) {
6740 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6741 NumSelIdents))
6742 continue;
6743
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006744 if (AtParameterName) {
6745 // Suggest parameter names we've seen before.
6746 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6747 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6748 if (Param->getIdentifier()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006749 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregordae68752011-02-01 22:57:45 +00006750 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006751 Param->getIdentifier()->getName()));
6752 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006753 }
6754 }
6755
6756 continue;
6757 }
6758
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006759 Result R(MethList->Method, 0);
6760 R.StartParameter = NumSelIdents;
6761 R.AllParametersAreInformative = false;
6762 R.DeclaringEntity = true;
6763 Results.MaybeAddResult(R, CurContext);
6764 }
6765 }
6766
6767 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006768 HandleCodeCompleteResults(this, CodeCompleter,
6769 CodeCompletionContext::CCC_Other,
6770 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006771}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006772
Douglas Gregorf29c5232010-08-24 22:20:20 +00006773void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006774 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006775 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006776 Results.EnterNewScope();
6777
6778 // #if <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006779 CodeCompletionBuilder Builder(Results.getAllocator());
6780 Builder.AddTypedTextChunk("if");
6781 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6782 Builder.AddPlaceholderChunk("condition");
6783 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006784
6785 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006786 Builder.AddTypedTextChunk("ifdef");
6787 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6788 Builder.AddPlaceholderChunk("macro");
6789 Results.AddResult(Builder.TakeString());
6790
Douglas Gregorf44e8542010-08-24 19:08:16 +00006791 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006792 Builder.AddTypedTextChunk("ifndef");
6793 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6794 Builder.AddPlaceholderChunk("macro");
6795 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006796
6797 if (InConditional) {
6798 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006799 Builder.AddTypedTextChunk("elif");
6800 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6801 Builder.AddPlaceholderChunk("condition");
6802 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006803
6804 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00006805 Builder.AddTypedTextChunk("else");
6806 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006807
6808 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00006809 Builder.AddTypedTextChunk("endif");
6810 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006811 }
6812
6813 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006814 Builder.AddTypedTextChunk("include");
6815 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6816 Builder.AddTextChunk("\"");
6817 Builder.AddPlaceholderChunk("header");
6818 Builder.AddTextChunk("\"");
6819 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006820
6821 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006822 Builder.AddTypedTextChunk("include");
6823 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6824 Builder.AddTextChunk("<");
6825 Builder.AddPlaceholderChunk("header");
6826 Builder.AddTextChunk(">");
6827 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006828
6829 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006830 Builder.AddTypedTextChunk("define");
6831 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6832 Builder.AddPlaceholderChunk("macro");
6833 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006834
6835 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00006836 Builder.AddTypedTextChunk("define");
6837 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6838 Builder.AddPlaceholderChunk("macro");
6839 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6840 Builder.AddPlaceholderChunk("args");
6841 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6842 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006843
6844 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006845 Builder.AddTypedTextChunk("undef");
6846 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6847 Builder.AddPlaceholderChunk("macro");
6848 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006849
6850 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00006851 Builder.AddTypedTextChunk("line");
6852 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6853 Builder.AddPlaceholderChunk("number");
6854 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006855
6856 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00006857 Builder.AddTypedTextChunk("line");
6858 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6859 Builder.AddPlaceholderChunk("number");
6860 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6861 Builder.AddTextChunk("\"");
6862 Builder.AddPlaceholderChunk("filename");
6863 Builder.AddTextChunk("\"");
6864 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006865
6866 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006867 Builder.AddTypedTextChunk("error");
6868 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6869 Builder.AddPlaceholderChunk("message");
6870 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006871
6872 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00006873 Builder.AddTypedTextChunk("pragma");
6874 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6875 Builder.AddPlaceholderChunk("arguments");
6876 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006877
6878 if (getLangOptions().ObjC1) {
6879 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006880 Builder.AddTypedTextChunk("import");
6881 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6882 Builder.AddTextChunk("\"");
6883 Builder.AddPlaceholderChunk("header");
6884 Builder.AddTextChunk("\"");
6885 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006886
6887 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006888 Builder.AddTypedTextChunk("import");
6889 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6890 Builder.AddTextChunk("<");
6891 Builder.AddPlaceholderChunk("header");
6892 Builder.AddTextChunk(">");
6893 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006894 }
6895
6896 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006897 Builder.AddTypedTextChunk("include_next");
6898 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6899 Builder.AddTextChunk("\"");
6900 Builder.AddPlaceholderChunk("header");
6901 Builder.AddTextChunk("\"");
6902 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006903
6904 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006905 Builder.AddTypedTextChunk("include_next");
6906 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6907 Builder.AddTextChunk("<");
6908 Builder.AddPlaceholderChunk("header");
6909 Builder.AddTextChunk(">");
6910 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006911
6912 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006913 Builder.AddTypedTextChunk("warning");
6914 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6915 Builder.AddPlaceholderChunk("message");
6916 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006917
6918 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
6919 // completions for them. And __include_macros is a Clang-internal extension
6920 // that we don't want to encourage anyone to use.
6921
6922 // FIXME: we don't support #assert or #unassert, so don't suggest them.
6923 Results.ExitScope();
6924
Douglas Gregorf44e8542010-08-24 19:08:16 +00006925 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00006926 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00006927 Results.data(), Results.size());
6928}
6929
6930void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00006931 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00006932 S->getFnParent()? Sema::PCC_RecoveryInFunction
6933 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006934}
6935
Douglas Gregorf29c5232010-08-24 22:20:20 +00006936void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006937 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006938 IsDefinition? CodeCompletionContext::CCC_MacroName
6939 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006940 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
6941 // Add just the names of macros, not their arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00006942 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006943 Results.EnterNewScope();
6944 for (Preprocessor::macro_iterator M = PP.macro_begin(),
6945 MEnd = PP.macro_end();
6946 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00006947 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006948 M->first->getName()));
6949 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006950 }
6951 Results.ExitScope();
6952 } else if (IsDefinition) {
6953 // FIXME: Can we detect when the user just wrote an include guard above?
6954 }
6955
Douglas Gregor52779fb2010-09-23 23:01:17 +00006956 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006957 Results.data(), Results.size());
6958}
6959
Douglas Gregorf29c5232010-08-24 22:20:20 +00006960void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00006961 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006962 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00006963
6964 if (!CodeCompleter || CodeCompleter->includeMacros())
6965 AddMacroResults(PP, Results);
6966
6967 // defined (<macro>)
6968 Results.EnterNewScope();
Douglas Gregor218937c2011-02-01 19:23:04 +00006969 CodeCompletionBuilder Builder(Results.getAllocator());
6970 Builder.AddTypedTextChunk("defined");
6971 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6972 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6973 Builder.AddPlaceholderChunk("macro");
6974 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6975 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00006976 Results.ExitScope();
6977
6978 HandleCodeCompleteResults(this, CodeCompleter,
6979 CodeCompletionContext::CCC_PreprocessorExpression,
6980 Results.data(), Results.size());
6981}
6982
6983void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
6984 IdentifierInfo *Macro,
6985 MacroInfo *MacroInfo,
6986 unsigned Argument) {
6987 // FIXME: In the future, we could provide "overload" results, much like we
6988 // do for function calls.
6989
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00006990 // Now just ignore this. There will be another code-completion callback
6991 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00006992}
6993
Douglas Gregor55817af2010-08-25 17:04:25 +00006994void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00006995 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00006996 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00006997 0, 0);
6998}
6999
Douglas Gregordae68752011-02-01 22:57:45 +00007000void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007001 SmallVectorImpl<CodeCompletionResult> &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007002 ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007003 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7004 CodeCompletionDeclConsumer Consumer(Builder,
7005 Context.getTranslationUnitDecl());
7006 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7007 Consumer);
7008 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007009
7010 if (!CodeCompleter || CodeCompleter->includeMacros())
7011 AddMacroResults(PP, Builder);
7012
7013 Results.clear();
7014 Results.insert(Results.end(),
7015 Builder.data(), Builder.data() + Builder.size());
7016}