blob: 75253b5b3082170e256663d0e1babea633a14cd0 [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 Gregor3f7c7f42009-10-30 16:50:04 +000023#include "clang/Lex/MacroInfo.h"
24#include "clang/Lex/Preprocessor.h"
Douglas Gregord36adf52010-09-16 16:06:31 +000025#include "llvm/ADT/DenseSet.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000026#include "llvm/ADT/SmallPtrSet.h"
Douglas Gregor6a684032009-09-28 03:51:44 +000027#include "llvm/ADT/StringExtras.h"
Douglas Gregor22f56992010-04-06 19:22:33 +000028#include "llvm/ADT/StringSwitch.h"
Douglas Gregor458433d2010-08-26 15:07:07 +000029#include "llvm/ADT/Twine.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000030#include <list>
31#include <map>
32#include <vector>
Douglas Gregor81b747b2009-09-17 21:32:03 +000033
34using namespace clang;
John McCall781472f2010-08-25 08:40:02 +000035using namespace sema;
Douglas Gregor81b747b2009-09-17 21:32:03 +000036
Douglas Gregor86d9a522009-09-21 16:56:56 +000037namespace {
38 /// \brief A container of code-completion results.
39 class ResultBuilder {
40 public:
41 /// \brief The type of a name-lookup filter, which can be provided to the
42 /// name-lookup routines to specify which declarations should be included in
43 /// the result set (when it returns true) and which declarations should be
44 /// filtered out (returns false).
45 typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
46
John McCall0a2c5e22010-08-25 06:19:51 +000047 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +000048
49 private:
50 /// \brief The actual results we have found.
51 std::vector<Result> Results;
52
53 /// \brief A record of all of the declarations we have found and placed
54 /// into the result set, used to ensure that no declaration ever gets into
55 /// the result set twice.
56 llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
57
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000058 typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
59
60 /// \brief An entry in the shadow map, which is optimized to store
61 /// a single (declaration, index) mapping (the common case) but
62 /// can also store a list of (declaration, index) mappings.
63 class ShadowMapEntry {
64 typedef llvm::SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
65
66 /// \brief Contains either the solitary NamedDecl * or a vector
67 /// of (declaration, index) pairs.
68 llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
69
70 /// \brief When the entry contains a single declaration, this is
71 /// the index associated with that entry.
72 unsigned SingleDeclIndex;
73
74 public:
75 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
76
77 void Add(NamedDecl *ND, unsigned Index) {
78 if (DeclOrVector.isNull()) {
79 // 0 - > 1 elements: just set the single element information.
80 DeclOrVector = ND;
81 SingleDeclIndex = Index;
82 return;
83 }
84
85 if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
86 // 1 -> 2 elements: create the vector of results and push in the
87 // existing declaration.
88 DeclIndexPairVector *Vec = new DeclIndexPairVector;
89 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
90 DeclOrVector = Vec;
91 }
92
93 // Add the new element to the end of the vector.
94 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
95 DeclIndexPair(ND, Index));
96 }
97
98 void Destroy() {
99 if (DeclIndexPairVector *Vec
100 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
101 delete Vec;
102 DeclOrVector = ((NamedDecl *)0);
103 }
104 }
105
106 // Iteration.
107 class iterator;
108 iterator begin() const;
109 iterator end() const;
110 };
111
Douglas Gregor86d9a522009-09-21 16:56:56 +0000112 /// \brief A mapping from declaration names to the declarations that have
113 /// this name within a particular scope and their index within the list of
114 /// results.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000115 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000116
117 /// \brief The semantic analysis object for which results are being
118 /// produced.
119 Sema &SemaRef;
Douglas Gregor218937c2011-02-01 19:23:04 +0000120
121 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000122 CodeCompletionAllocator &Allocator;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000123
124 /// \brief If non-NULL, a filter function used to remove any code-completion
125 /// results that are not desirable.
126 LookupFilter Filter;
Douglas Gregor45bcd432010-01-14 03:21:49 +0000127
128 /// \brief Whether we should allow declarations as
129 /// nested-name-specifiers that would otherwise be filtered out.
130 bool AllowNestedNameSpecifiers;
131
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000132 /// \brief If set, the type that we would prefer our resulting value
133 /// declarations to have.
134 ///
135 /// Closely matching the preferred type gives a boost to a result's
136 /// priority.
137 CanQualType PreferredType;
138
Douglas Gregor86d9a522009-09-21 16:56:56 +0000139 /// \brief A list of shadow maps, which is used to model name hiding at
140 /// different levels of, e.g., the inheritance hierarchy.
141 std::list<ShadowMap> ShadowMaps;
142
Douglas Gregor3cdee122010-08-26 16:36:48 +0000143 /// \brief If we're potentially referring to a C++ member function, the set
144 /// of qualifiers applied to the object type.
145 Qualifiers ObjectTypeQualifiers;
146
147 /// \brief Whether the \p ObjectTypeQualifiers field is active.
148 bool HasObjectTypeQualifiers;
149
Douglas Gregor265f7492010-08-27 15:29:55 +0000150 /// \brief The selector that we prefer.
151 Selector PreferredSelector;
152
Douglas Gregorca45da02010-11-02 20:36:02 +0000153 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000154 CodeCompletionContext CompletionContext;
155
Douglas Gregorca45da02010-11-02 20:36:02 +0000156 /// \brief If we are in an instance method definition, the @implementation
157 /// object.
158 ObjCImplementationDecl *ObjCImplementation;
159
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000160 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000161
Douglas Gregor6f942b22010-09-21 16:06:22 +0000162 void MaybeAddConstructorResults(Result R);
163
Douglas Gregor86d9a522009-09-21 16:56:56 +0000164 public:
Douglas Gregordae68752011-02-01 22:57:45 +0000165 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000166 const CodeCompletionContext &CompletionContext,
167 LookupFilter Filter = 0)
Douglas Gregor218937c2011-02-01 19:23:04 +0000168 : SemaRef(SemaRef), Allocator(Allocator), Filter(Filter),
169 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-11-02 20:36:02 +0000170 CompletionContext(CompletionContext),
171 ObjCImplementation(0)
172 {
173 // If this is an Objective-C instance method definition, dig out the
174 // corresponding implementation.
175 switch (CompletionContext.getKind()) {
176 case CodeCompletionContext::CCC_Expression:
177 case CodeCompletionContext::CCC_ObjCMessageReceiver:
178 case CodeCompletionContext::CCC_ParenthesizedExpression:
179 case CodeCompletionContext::CCC_Statement:
180 case CodeCompletionContext::CCC_Recovery:
181 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
182 if (Method->isInstanceMethod())
183 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
184 ObjCImplementation = Interface->getImplementation();
185 break;
186
187 default:
188 break;
189 }
190 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000191
Douglas Gregord8e8a582010-05-25 21:41:55 +0000192 /// \brief Whether we should include code patterns in the completion
193 /// results.
194 bool includeCodePatterns() const {
195 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000196 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000197 }
198
Douglas Gregor86d9a522009-09-21 16:56:56 +0000199 /// \brief Set the filter used for code-completion results.
200 void setFilter(LookupFilter Filter) {
201 this->Filter = Filter;
202 }
203
Douglas Gregor86d9a522009-09-21 16:56:56 +0000204 Result *data() { return Results.empty()? 0 : &Results.front(); }
205 unsigned size() const { return Results.size(); }
206 bool empty() const { return Results.empty(); }
207
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000208 /// \brief Specify the preferred type.
209 void setPreferredType(QualType T) {
210 PreferredType = SemaRef.Context.getCanonicalType(T);
211 }
212
Douglas Gregor3cdee122010-08-26 16:36:48 +0000213 /// \brief Set the cv-qualifiers on the object type, for us in filtering
214 /// calls to member functions.
215 ///
216 /// When there are qualifiers in this set, they will be used to filter
217 /// out member functions that aren't available (because there will be a
218 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
219 /// match.
220 void setObjectTypeQualifiers(Qualifiers Quals) {
221 ObjectTypeQualifiers = Quals;
222 HasObjectTypeQualifiers = true;
223 }
224
Douglas Gregor265f7492010-08-27 15:29:55 +0000225 /// \brief Set the preferred selector.
226 ///
227 /// When an Objective-C method declaration result is added, and that
228 /// method's selector matches this preferred selector, we give that method
229 /// a slight priority boost.
230 void setPreferredSelector(Selector Sel) {
231 PreferredSelector = Sel;
232 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000233
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000234 /// \brief Retrieve the code-completion context for which results are
235 /// being collected.
236 const CodeCompletionContext &getCompletionContext() const {
237 return CompletionContext;
238 }
239
Douglas Gregor45bcd432010-01-14 03:21:49 +0000240 /// \brief Specify whether nested-name-specifiers are allowed.
241 void allowNestedNameSpecifiers(bool Allow = true) {
242 AllowNestedNameSpecifiers = Allow;
243 }
244
Douglas Gregorb9d77572010-09-21 00:03:25 +0000245 /// \brief Return the semantic analysis object for which we are collecting
246 /// code completion results.
247 Sema &getSema() const { return SemaRef; }
248
Douglas Gregor218937c2011-02-01 19:23:04 +0000249 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000250 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Douglas Gregor218937c2011-02-01 19:23:04 +0000251
Douglas Gregore495b7f2010-01-14 00:20:49 +0000252 /// \brief Determine whether the given declaration is at all interesting
253 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000254 ///
255 /// \param ND the declaration that we are inspecting.
256 ///
257 /// \param AsNestedNameSpecifier will be set true if this declaration is
258 /// only interesting when it is a nested-name-specifier.
259 bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000260
261 /// \brief Check whether the result is hidden by the Hiding declaration.
262 ///
263 /// \returns true if the result is hidden and cannot be found, false if
264 /// the hidden result could still be found. When false, \p R may be
265 /// modified to describe how the result can be found (e.g., via extra
266 /// qualification).
267 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
268 NamedDecl *Hiding);
269
Douglas Gregor86d9a522009-09-21 16:56:56 +0000270 /// \brief Add a new result to this result set (if it isn't already in one
271 /// of the shadow maps), or replace an existing result (for, e.g., a
272 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000273 ///
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000274 /// \param CurContext the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000275 ///
276 /// \param R the context in which this result will be named.
277 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000278
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000279 /// \brief Add a new result to this result set, where we already know
280 /// the hiding declation (if any).
281 ///
282 /// \param R the result to add (if it is unique).
283 ///
284 /// \param CurContext the context in which this result will be named.
285 ///
286 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000287 ///
288 /// \param InBaseClass whether the result was found in a base
289 /// class of the searched context.
290 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
291 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000292
Douglas Gregora4477812010-01-14 16:01:26 +0000293 /// \brief Add a new non-declaration result to this result set.
294 void AddResult(Result R);
295
Douglas Gregor86d9a522009-09-21 16:56:56 +0000296 /// \brief Enter into a new scope.
297 void EnterNewScope();
298
299 /// \brief Exit from the current scope.
300 void ExitScope();
301
Douglas Gregor55385fe2009-11-18 04:19:12 +0000302 /// \brief Ignore this declaration, if it is seen again.
303 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
304
Douglas Gregor86d9a522009-09-21 16:56:56 +0000305 /// \name Name lookup predicates
306 ///
307 /// These predicates can be passed to the name lookup functions to filter the
308 /// results of name lookup. All of the predicates have the same type, so that
309 ///
310 //@{
Douglas Gregor791215b2009-09-21 20:51:25 +0000311 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000312 bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
Douglas Gregorf9578432010-07-28 21:50:18 +0000313 bool IsIntegralConstantValue(NamedDecl *ND) const;
Douglas Gregor01dfea02010-01-10 23:08:15 +0000314 bool IsOrdinaryNonValueName(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000315 bool IsNestedNameSpecifier(NamedDecl *ND) const;
316 bool IsEnum(NamedDecl *ND) const;
317 bool IsClassOrStruct(NamedDecl *ND) const;
318 bool IsUnion(NamedDecl *ND) const;
319 bool IsNamespace(NamedDecl *ND) const;
320 bool IsNamespaceOrAlias(NamedDecl *ND) const;
321 bool IsType(NamedDecl *ND) const;
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000322 bool IsMember(NamedDecl *ND) const;
Douglas Gregor80f4f4c2010-01-14 16:08:12 +0000323 bool IsObjCIvar(NamedDecl *ND) const;
Douglas Gregor8e254cf2010-05-27 23:06:34 +0000324 bool IsObjCMessageReceiver(NamedDecl *ND) const;
Douglas Gregorfb629412010-08-23 21:17:50 +0000325 bool IsObjCCollection(NamedDecl *ND) const;
Douglas Gregor52779fb2010-09-23 23:01:17 +0000326 bool IsImpossibleToSatisfy(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000327 //@}
328 };
329}
330
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000331class ResultBuilder::ShadowMapEntry::iterator {
332 llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
333 unsigned SingleDeclIndex;
334
335public:
336 typedef DeclIndexPair value_type;
337 typedef value_type reference;
338 typedef std::ptrdiff_t difference_type;
339 typedef std::input_iterator_tag iterator_category;
340
341 class pointer {
342 DeclIndexPair Value;
343
344 public:
345 pointer(const DeclIndexPair &Value) : Value(Value) { }
346
347 const DeclIndexPair *operator->() const {
348 return &Value;
349 }
350 };
351
352 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
353
354 iterator(NamedDecl *SingleDecl, unsigned Index)
355 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
356
357 iterator(const DeclIndexPair *Iterator)
358 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
359
360 iterator &operator++() {
361 if (DeclOrIterator.is<NamedDecl *>()) {
362 DeclOrIterator = (NamedDecl *)0;
363 SingleDeclIndex = 0;
364 return *this;
365 }
366
367 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
368 ++I;
369 DeclOrIterator = I;
370 return *this;
371 }
372
Chris Lattner66392d42010-09-04 18:12:20 +0000373 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000374 iterator tmp(*this);
375 ++(*this);
376 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000377 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000378
379 reference operator*() const {
380 if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
381 return reference(ND, SingleDeclIndex);
382
Douglas Gregord490f952009-12-06 21:27:58 +0000383 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000384 }
385
386 pointer operator->() const {
387 return pointer(**this);
388 }
389
390 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000391 return X.DeclOrIterator.getOpaqueValue()
392 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000393 X.SingleDeclIndex == Y.SingleDeclIndex;
394 }
395
396 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000397 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000398 }
399};
400
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000401ResultBuilder::ShadowMapEntry::iterator
402ResultBuilder::ShadowMapEntry::begin() const {
403 if (DeclOrVector.isNull())
404 return iterator();
405
406 if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
407 return iterator(ND, SingleDeclIndex);
408
409 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
410}
411
412ResultBuilder::ShadowMapEntry::iterator
413ResultBuilder::ShadowMapEntry::end() const {
414 if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
415 return iterator();
416
417 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
418}
419
Douglas Gregor456c4a12009-09-21 20:12:40 +0000420/// \brief Compute the qualification required to get from the current context
421/// (\p CurContext) to the target context (\p TargetContext).
422///
423/// \param Context the AST context in which the qualification will be used.
424///
425/// \param CurContext the context where an entity is being named, which is
426/// typically based on the current scope.
427///
428/// \param TargetContext the context in which the named entity actually
429/// resides.
430///
431/// \returns a nested name specifier that refers into the target context, or
432/// NULL if no qualification is needed.
433static NestedNameSpecifier *
434getRequiredQualification(ASTContext &Context,
435 DeclContext *CurContext,
436 DeclContext *TargetContext) {
437 llvm::SmallVector<DeclContext *, 4> TargetParents;
438
439 for (DeclContext *CommonAncestor = TargetContext;
440 CommonAncestor && !CommonAncestor->Encloses(CurContext);
441 CommonAncestor = CommonAncestor->getLookupParent()) {
442 if (CommonAncestor->isTransparentContext() ||
443 CommonAncestor->isFunctionOrMethod())
444 continue;
445
446 TargetParents.push_back(CommonAncestor);
447 }
448
449 NestedNameSpecifier *Result = 0;
450 while (!TargetParents.empty()) {
451 DeclContext *Parent = TargetParents.back();
452 TargetParents.pop_back();
453
Douglas Gregorfb629412010-08-23 21:17:50 +0000454 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
455 if (!Namespace->getIdentifier())
456 continue;
457
Douglas Gregor456c4a12009-09-21 20:12:40 +0000458 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000459 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000460 else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
461 Result = NestedNameSpecifier::Create(Context, Result,
462 false,
463 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000464 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000465 return Result;
466}
467
Douglas Gregor45bcd432010-01-14 03:21:49 +0000468bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
469 bool &AsNestedNameSpecifier) const {
470 AsNestedNameSpecifier = false;
471
Douglas Gregore495b7f2010-01-14 00:20:49 +0000472 ND = ND->getUnderlyingDecl();
473 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000474
475 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000476 if (!ND->getDeclName())
477 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000478
479 // Friend declarations and declarations introduced due to friends are never
480 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000481 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000482 return false;
483
Douglas Gregor76282942009-12-11 17:31:05 +0000484 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000485 if (isa<ClassTemplateSpecializationDecl>(ND) ||
486 isa<ClassTemplatePartialSpecializationDecl>(ND))
487 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000488
Douglas Gregor76282942009-12-11 17:31:05 +0000489 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000490 if (isa<UsingDecl>(ND))
491 return false;
492
493 // Some declarations have reserved names that we don't want to ever show.
494 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000495 // __va_list_tag is a freak of nature. Find it and skip it.
496 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000497 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000498
Douglas Gregorf52cede2009-10-09 22:16:47 +0000499 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000500 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000501 //
502 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000503 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000504 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000505 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000506 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
507 (ND->getLocation().isInvalid() ||
508 SemaRef.SourceMgr.isInSystemHeader(
509 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000510 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000511 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000512 }
Douglas Gregor6f942b22010-09-21 16:06:22 +0000513
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000514 // Skip out-of-line declarations and definitions.
515 // NOTE: Unless it's an Objective-C property, method, or ivar, where
516 // the contexts can be messy.
517 if (!ND->getDeclContext()->Equals(ND->getLexicalDeclContext()) &&
518 !(isa<ObjCPropertyDecl>(ND) || isa<ObjCIvarDecl>(ND) ||
519 isa<ObjCMethodDecl>(ND)))
520 return false;
521
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000522 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
523 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
524 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000525 Filter != &ResultBuilder::IsNamespaceOrAlias &&
526 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000527 AsNestedNameSpecifier = true;
528
Douglas Gregor86d9a522009-09-21 16:56:56 +0000529 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000530 if (Filter && !(this->*Filter)(ND)) {
531 // Check whether it is interesting as a nested-name-specifier.
532 if (AllowNestedNameSpecifiers && SemaRef.getLangOptions().CPlusPlus &&
533 IsNestedNameSpecifier(ND) &&
534 (Filter != &ResultBuilder::IsMember ||
535 (isa<CXXRecordDecl>(ND) &&
536 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
537 AsNestedNameSpecifier = true;
538 return true;
539 }
540
Douglas Gregore495b7f2010-01-14 00:20:49 +0000541 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000542 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000543 // ... then it must be interesting!
544 return true;
545}
546
Douglas Gregor6660d842010-01-14 00:41:07 +0000547bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
548 NamedDecl *Hiding) {
549 // In C, there is no way to refer to a hidden name.
550 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
551 // name if we introduce the tag type.
552 if (!SemaRef.getLangOptions().CPlusPlus)
553 return true;
554
Sebastian Redl7a126a42010-08-31 00:36:30 +0000555 DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000556
557 // There is no way to qualify a name declared in a function or method.
558 if (HiddenCtx->isFunctionOrMethod())
559 return true;
560
Sebastian Redl7a126a42010-08-31 00:36:30 +0000561 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000562 return true;
563
564 // We can refer to the result with the appropriate qualification. Do it.
565 R.Hidden = true;
566 R.QualifierIsInformative = false;
567
568 if (!R.Qualifier)
569 R.Qualifier = getRequiredQualification(SemaRef.Context,
570 CurContext,
571 R.Declaration->getDeclContext());
572 return false;
573}
574
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000575/// \brief A simplified classification of types used to determine whether two
576/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000577SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000578 switch (T->getTypeClass()) {
579 case Type::Builtin:
580 switch (cast<BuiltinType>(T)->getKind()) {
581 case BuiltinType::Void:
582 return STC_Void;
583
584 case BuiltinType::NullPtr:
585 return STC_Pointer;
586
587 case BuiltinType::Overload:
588 case BuiltinType::Dependent:
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000589 return STC_Other;
590
591 case BuiltinType::ObjCId:
592 case BuiltinType::ObjCClass:
593 case BuiltinType::ObjCSel:
594 return STC_ObjectiveC;
595
596 default:
597 return STC_Arithmetic;
598 }
599 return STC_Other;
600
601 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();
670
671 return T.getNonReferenceType();
672}
673
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000674void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
675 // If this is an Objective-C method declaration whose selector matches our
676 // preferred selector, give it a priority boost.
677 if (!PreferredSelector.isNull())
678 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
679 if (PreferredSelector == Method->getSelector())
680 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000681
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000682 // If we have a preferred type, adjust the priority for results with exactly-
683 // matching or nearly-matching types.
684 if (!PreferredType.isNull()) {
685 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
686 if (!T.isNull()) {
687 CanQualType TC = SemaRef.Context.getCanonicalType(T);
688 // Check for exactly-matching types (modulo qualifiers).
689 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
690 R.Priority /= CCF_ExactTypeMatch;
691 // Check for nearly-matching types, based on classification of each.
692 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000693 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000694 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
695 R.Priority /= CCF_SimilarTypeMatch;
696 }
697 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000698}
699
Douglas Gregor6f942b22010-09-21 16:06:22 +0000700void ResultBuilder::MaybeAddConstructorResults(Result R) {
701 if (!SemaRef.getLangOptions().CPlusPlus || !R.Declaration ||
702 !CompletionContext.wantConstructorResults())
703 return;
704
705 ASTContext &Context = SemaRef.Context;
706 NamedDecl *D = R.Declaration;
707 CXXRecordDecl *Record = 0;
708 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
709 Record = ClassTemplate->getTemplatedDecl();
710 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
711 // Skip specializations and partial specializations.
712 if (isa<ClassTemplateSpecializationDecl>(Record))
713 return;
714 } else {
715 // There are no constructors here.
716 return;
717 }
718
719 Record = Record->getDefinition();
720 if (!Record)
721 return;
722
723
724 QualType RecordTy = Context.getTypeDeclType(Record);
725 DeclarationName ConstructorName
726 = Context.DeclarationNames.getCXXConstructorName(
727 Context.getCanonicalType(RecordTy));
728 for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
729 Ctors.first != Ctors.second; ++Ctors.first) {
730 R.Declaration = *Ctors.first;
731 R.CursorKind = getCursorKindForDecl(R.Declaration);
732 Results.push_back(R);
733 }
734}
735
Douglas Gregore495b7f2010-01-14 00:20:49 +0000736void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
737 assert(!ShadowMaps.empty() && "Must enter into a results scope");
738
739 if (R.Kind != Result::RK_Declaration) {
740 // For non-declaration results, just add the result.
741 Results.push_back(R);
742 return;
743 }
744
745 // Look through using declarations.
746 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
747 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
748 return;
749 }
750
751 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
752 unsigned IDNS = CanonDecl->getIdentifierNamespace();
753
Douglas Gregor45bcd432010-01-14 03:21:49 +0000754 bool AsNestedNameSpecifier = false;
755 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000756 return;
757
Douglas Gregor6f942b22010-09-21 16:06:22 +0000758 // C++ constructors are never found by name lookup.
759 if (isa<CXXConstructorDecl>(R.Declaration))
760 return;
761
Douglas Gregor86d9a522009-09-21 16:56:56 +0000762 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000763 ShadowMapEntry::iterator I, IEnd;
764 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
765 if (NamePos != SMap.end()) {
766 I = NamePos->second.begin();
767 IEnd = NamePos->second.end();
768 }
769
770 for (; I != IEnd; ++I) {
771 NamedDecl *ND = I->first;
772 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000773 if (ND->getCanonicalDecl() == CanonDecl) {
774 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000775 Results[Index].Declaration = R.Declaration;
776
Douglas Gregor86d9a522009-09-21 16:56:56 +0000777 // We're done.
778 return;
779 }
780 }
781
782 // This is a new declaration in this scope. However, check whether this
783 // declaration name is hidden by a similarly-named declaration in an outer
784 // scope.
785 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
786 --SMEnd;
787 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000788 ShadowMapEntry::iterator I, IEnd;
789 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
790 if (NamePos != SM->end()) {
791 I = NamePos->second.begin();
792 IEnd = NamePos->second.end();
793 }
794 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000795 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000796 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000797 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
798 Decl::IDNS_ObjCProtocol)))
799 continue;
800
801 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000802 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000803 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000804 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000805 continue;
806
807 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000808 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000809 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000810
811 break;
812 }
813 }
814
815 // Make sure that any given declaration only shows up in the result set once.
816 if (!AllDeclsFound.insert(CanonDecl))
817 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000818
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000819 // If the filter is for nested-name-specifiers, then this result starts a
820 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000821 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000822 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000823 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000824 } else
825 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000826
Douglas Gregor0563c262009-09-22 23:15:58 +0000827 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000828 if (R.QualifierIsInformative && !R.Qualifier &&
829 !R.StartsNestedNameSpecifier) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000830 DeclContext *Ctx = R.Declaration->getDeclContext();
831 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
832 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
833 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
834 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
835 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
836 else
837 R.QualifierIsInformative = false;
838 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000839
Douglas Gregor86d9a522009-09-21 16:56:56 +0000840 // Insert this result into the set of results and into the current shadow
841 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000842 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000843 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000844
845 if (!AsNestedNameSpecifier)
846 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000847}
848
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000849void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000850 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000851 if (R.Kind != Result::RK_Declaration) {
852 // For non-declaration results, just add the result.
853 Results.push_back(R);
854 return;
855 }
856
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000857 // Look through using declarations.
858 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
859 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
860 return;
861 }
862
Douglas Gregor45bcd432010-01-14 03:21:49 +0000863 bool AsNestedNameSpecifier = false;
864 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000865 return;
866
Douglas Gregor6f942b22010-09-21 16:06:22 +0000867 // C++ constructors are never found by name lookup.
868 if (isa<CXXConstructorDecl>(R.Declaration))
869 return;
870
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000871 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
872 return;
873
874 // Make sure that any given declaration only shows up in the result set once.
875 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
876 return;
877
878 // If the filter is for nested-name-specifiers, then this result starts a
879 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000880 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000881 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000882 R.Priority = CCP_NestedNameSpecifier;
883 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000884 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
885 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000886 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000887 R.QualifierIsInformative = true;
888
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000889 // If this result is supposed to have an informative qualifier, add one.
890 if (R.QualifierIsInformative && !R.Qualifier &&
891 !R.StartsNestedNameSpecifier) {
892 DeclContext *Ctx = R.Declaration->getDeclContext();
893 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
894 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
895 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
896 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000897 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000898 else
899 R.QualifierIsInformative = false;
900 }
901
Douglas Gregor12e13132010-05-26 22:00:08 +0000902 // Adjust the priority if this result comes from a base class.
903 if (InBaseClass)
904 R.Priority += CCD_InBaseClass;
905
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000906 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000907
Douglas Gregor3cdee122010-08-26 16:36:48 +0000908 if (HasObjectTypeQualifiers)
909 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
910 if (Method->isInstance()) {
911 Qualifiers MethodQuals
912 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
913 if (ObjectTypeQualifiers == MethodQuals)
914 R.Priority += CCD_ObjectQualifierMatch;
915 else if (ObjectTypeQualifiers - MethodQuals) {
916 // The method cannot be invoked, because doing so would drop
917 // qualifiers.
918 return;
919 }
920 }
921
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000922 // Insert this result into the set of results.
923 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000924
925 if (!AsNestedNameSpecifier)
926 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000927}
928
Douglas Gregora4477812010-01-14 16:01:26 +0000929void ResultBuilder::AddResult(Result R) {
930 assert(R.Kind != Result::RK_Declaration &&
931 "Declaration results need more context");
932 Results.push_back(R);
933}
934
Douglas Gregor86d9a522009-09-21 16:56:56 +0000935/// \brief Enter into a new scope.
936void ResultBuilder::EnterNewScope() {
937 ShadowMaps.push_back(ShadowMap());
938}
939
940/// \brief Exit from the current scope.
941void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000942 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
943 EEnd = ShadowMaps.back().end();
944 E != EEnd;
945 ++E)
946 E->second.Destroy();
947
Douglas Gregor86d9a522009-09-21 16:56:56 +0000948 ShadowMaps.pop_back();
949}
950
Douglas Gregor791215b2009-09-21 20:51:25 +0000951/// \brief Determines whether this given declaration will be found by
952/// ordinary name lookup.
953bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000954 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
955
Douglas Gregor791215b2009-09-21 20:51:25 +0000956 unsigned IDNS = Decl::IDNS_Ordinary;
957 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000958 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Douglas Gregorca45da02010-11-02 20:36:02 +0000959 else if (SemaRef.getLangOptions().ObjC1) {
960 if (isa<ObjCIvarDecl>(ND))
961 return true;
962 if (isa<ObjCPropertyDecl>(ND) &&
963 SemaRef.canSynthesizeProvisionalIvar(cast<ObjCPropertyDecl>(ND)))
964 return true;
965 }
966
Douglas Gregor791215b2009-09-21 20:51:25 +0000967 return ND->getIdentifierNamespace() & IDNS;
968}
969
Douglas Gregor01dfea02010-01-10 23:08:15 +0000970/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000971/// ordinary name lookup but is not a type name.
972bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
973 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
974 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
975 return false;
976
977 unsigned IDNS = Decl::IDNS_Ordinary;
978 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000979 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Douglas Gregorca45da02010-11-02 20:36:02 +0000980 else if (SemaRef.getLangOptions().ObjC1) {
981 if (isa<ObjCIvarDecl>(ND))
982 return true;
983 if (isa<ObjCPropertyDecl>(ND) &&
984 SemaRef.canSynthesizeProvisionalIvar(cast<ObjCPropertyDecl>(ND)))
985 return true;
986 }
987
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000988 return ND->getIdentifierNamespace() & IDNS;
989}
990
Douglas Gregorf9578432010-07-28 21:50:18 +0000991bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
992 if (!IsOrdinaryNonTypeName(ND))
993 return 0;
994
995 if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
996 if (VD->getType()->isIntegralOrEnumerationType())
997 return true;
998
999 return false;
1000}
1001
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001002/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001003/// ordinary name lookup.
1004bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001005 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1006
Douglas Gregor01dfea02010-01-10 23:08:15 +00001007 unsigned IDNS = Decl::IDNS_Ordinary;
1008 if (SemaRef.getLangOptions().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001009 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001010
1011 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001012 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1013 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001014}
1015
Douglas Gregor86d9a522009-09-21 16:56:56 +00001016/// \brief Determines whether the given declaration is suitable as the
1017/// start of a C++ nested-name-specifier, e.g., a class or namespace.
1018bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
1019 // Allow us to find class templates, too.
1020 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1021 ND = ClassTemplate->getTemplatedDecl();
1022
1023 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1024}
1025
1026/// \brief Determines whether the given declaration is an enumeration.
1027bool ResultBuilder::IsEnum(NamedDecl *ND) const {
1028 return isa<EnumDecl>(ND);
1029}
1030
1031/// \brief Determines whether the given declaration is a class or struct.
1032bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
1033 // Allow us to find class templates, too.
1034 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1035 ND = ClassTemplate->getTemplatedDecl();
1036
1037 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001038 return RD->getTagKind() == TTK_Class ||
1039 RD->getTagKind() == TTK_Struct;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001040
1041 return false;
1042}
1043
1044/// \brief Determines whether the given declaration is a union.
1045bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1046 // Allow us to find class templates, too.
1047 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1048 ND = ClassTemplate->getTemplatedDecl();
1049
1050 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001051 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001052
1053 return false;
1054}
1055
1056/// \brief Determines whether the given declaration is a namespace.
1057bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1058 return isa<NamespaceDecl>(ND);
1059}
1060
1061/// \brief Determines whether the given declaration is a namespace or
1062/// namespace alias.
1063bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1064 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1065}
1066
Douglas Gregor76282942009-12-11 17:31:05 +00001067/// \brief Determines whether the given declaration is a type.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001068bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregord32b0222010-08-24 01:06:58 +00001069 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1070 ND = Using->getTargetDecl();
1071
1072 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001073}
1074
Douglas Gregor76282942009-12-11 17:31:05 +00001075/// \brief Determines which members of a class should be visible via
1076/// "." or "->". Only value declarations, nested name specifiers, and
1077/// using declarations thereof should show up.
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001078bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor76282942009-12-11 17:31:05 +00001079 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1080 ND = Using->getTargetDecl();
1081
Douglas Gregorce821962009-12-11 18:14:22 +00001082 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1083 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001084}
1085
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001086static bool isObjCReceiverType(ASTContext &C, QualType T) {
1087 T = C.getCanonicalType(T);
1088 switch (T->getTypeClass()) {
1089 case Type::ObjCObject:
1090 case Type::ObjCInterface:
1091 case Type::ObjCObjectPointer:
1092 return true;
1093
1094 case Type::Builtin:
1095 switch (cast<BuiltinType>(T)->getKind()) {
1096 case BuiltinType::ObjCId:
1097 case BuiltinType::ObjCClass:
1098 case BuiltinType::ObjCSel:
1099 return true;
1100
1101 default:
1102 break;
1103 }
1104 return false;
1105
1106 default:
1107 break;
1108 }
1109
1110 if (!C.getLangOptions().CPlusPlus)
1111 return false;
1112
1113 // FIXME: We could perform more analysis here to determine whether a
1114 // particular class type has any conversions to Objective-C types. For now,
1115 // just accept all class types.
1116 return T->isDependentType() || T->isRecordType();
1117}
1118
1119bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1120 QualType T = getDeclUsageType(SemaRef.Context, ND);
1121 if (T.isNull())
1122 return false;
1123
1124 T = SemaRef.Context.getBaseElementType(T);
1125 return isObjCReceiverType(SemaRef.Context, T);
1126}
1127
Douglas Gregorfb629412010-08-23 21:17:50 +00001128bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
1129 if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) ||
1130 (!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
1131 return false;
1132
1133 QualType T = getDeclUsageType(SemaRef.Context, ND);
1134 if (T.isNull())
1135 return false;
1136
1137 T = SemaRef.Context.getBaseElementType(T);
1138 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1139 T->isObjCIdType() ||
1140 (SemaRef.getLangOptions().CPlusPlus && T->isRecordType());
1141}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001142
Douglas Gregor52779fb2010-09-23 23:01:17 +00001143bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1144 return false;
1145}
1146
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001147/// \rief Determines whether the given declaration is an Objective-C
1148/// instance variable.
1149bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1150 return isa<ObjCIvarDecl>(ND);
1151}
1152
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001153namespace {
1154 /// \brief Visible declaration consumer that adds a code-completion result
1155 /// for each visible declaration.
1156 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1157 ResultBuilder &Results;
1158 DeclContext *CurContext;
1159
1160 public:
1161 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1162 : Results(Results), CurContext(CurContext) { }
1163
Douglas Gregor0cc84042010-01-14 15:47:35 +00001164 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass) {
1165 Results.AddResult(ND, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001166 }
1167 };
1168}
1169
Douglas Gregor86d9a522009-09-21 16:56:56 +00001170/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001171static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001172 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001173 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001174 Results.AddResult(Result("short", CCP_Type));
1175 Results.AddResult(Result("long", CCP_Type));
1176 Results.AddResult(Result("signed", CCP_Type));
1177 Results.AddResult(Result("unsigned", CCP_Type));
1178 Results.AddResult(Result("void", CCP_Type));
1179 Results.AddResult(Result("char", CCP_Type));
1180 Results.AddResult(Result("int", CCP_Type));
1181 Results.AddResult(Result("float", CCP_Type));
1182 Results.AddResult(Result("double", CCP_Type));
1183 Results.AddResult(Result("enum", CCP_Type));
1184 Results.AddResult(Result("struct", CCP_Type));
1185 Results.AddResult(Result("union", CCP_Type));
1186 Results.AddResult(Result("const", CCP_Type));
1187 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001188
Douglas Gregor86d9a522009-09-21 16:56:56 +00001189 if (LangOpts.C99) {
1190 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001191 Results.AddResult(Result("_Complex", CCP_Type));
1192 Results.AddResult(Result("_Imaginary", CCP_Type));
1193 Results.AddResult(Result("_Bool", CCP_Type));
1194 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001195 }
1196
Douglas Gregor218937c2011-02-01 19:23:04 +00001197 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001198 if (LangOpts.CPlusPlus) {
1199 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001200 Results.AddResult(Result("bool", CCP_Type +
1201 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001202 Results.AddResult(Result("class", CCP_Type));
1203 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001204
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001205 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001206 Builder.AddTypedTextChunk("typename");
1207 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1208 Builder.AddPlaceholderChunk("qualifier");
1209 Builder.AddTextChunk("::");
1210 Builder.AddPlaceholderChunk("name");
1211 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001212
Douglas Gregor86d9a522009-09-21 16:56:56 +00001213 if (LangOpts.CPlusPlus0x) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001214 Results.AddResult(Result("auto", CCP_Type));
1215 Results.AddResult(Result("char16_t", CCP_Type));
1216 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001217
Douglas Gregor218937c2011-02-01 19:23:04 +00001218 Builder.AddTypedTextChunk("decltype");
1219 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1220 Builder.AddPlaceholderChunk("expression");
1221 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1222 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001223 }
1224 }
1225
1226 // GNU extensions
1227 if (LangOpts.GNUMode) {
1228 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001229 // Results.AddResult(Result("_Decimal32"));
1230 // Results.AddResult(Result("_Decimal64"));
1231 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001232
Douglas Gregor218937c2011-02-01 19:23:04 +00001233 Builder.AddTypedTextChunk("typeof");
1234 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1235 Builder.AddPlaceholderChunk("expression");
1236 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001237
Douglas Gregor218937c2011-02-01 19:23:04 +00001238 Builder.AddTypedTextChunk("typeof");
1239 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1240 Builder.AddPlaceholderChunk("type");
1241 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1242 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001243 }
1244}
1245
John McCallf312b1e2010-08-26 23:41:50 +00001246static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001247 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001248 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001249 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001250 // Note: we don't suggest either "auto" or "register", because both
1251 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1252 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001253 Results.AddResult(Result("extern"));
1254 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001255}
1256
John McCallf312b1e2010-08-26 23:41:50 +00001257static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001258 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001259 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001260 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001261 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001262 case Sema::PCC_Class:
1263 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001264 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001265 Results.AddResult(Result("explicit"));
1266 Results.AddResult(Result("friend"));
1267 Results.AddResult(Result("mutable"));
1268 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001269 }
1270 // Fall through
1271
John McCallf312b1e2010-08-26 23:41:50 +00001272 case Sema::PCC_ObjCInterface:
1273 case Sema::PCC_ObjCImplementation:
1274 case Sema::PCC_Namespace:
1275 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001276 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001277 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001278 break;
1279
John McCallf312b1e2010-08-26 23:41:50 +00001280 case Sema::PCC_ObjCInstanceVariableList:
1281 case Sema::PCC_Expression:
1282 case Sema::PCC_Statement:
1283 case Sema::PCC_ForInit:
1284 case Sema::PCC_Condition:
1285 case Sema::PCC_RecoveryInFunction:
1286 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001287 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001288 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001289 break;
1290 }
1291}
1292
Douglas Gregorbca403c2010-01-13 23:51:12 +00001293static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1294static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1295static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001296 ResultBuilder &Results,
1297 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001298static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001299 ResultBuilder &Results,
1300 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001301static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001302 ResultBuilder &Results,
1303 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001304static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001305
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001306static void AddTypedefResult(ResultBuilder &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001307 CodeCompletionBuilder Builder(Results.getAllocator());
1308 Builder.AddTypedTextChunk("typedef");
1309 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1310 Builder.AddPlaceholderChunk("type");
1311 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1312 Builder.AddPlaceholderChunk("name");
1313 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001314}
1315
John McCallf312b1e2010-08-26 23:41:50 +00001316static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001317 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001318 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001319 case Sema::PCC_Namespace:
1320 case Sema::PCC_Class:
1321 case Sema::PCC_ObjCInstanceVariableList:
1322 case Sema::PCC_Template:
1323 case Sema::PCC_MemberTemplate:
1324 case Sema::PCC_Statement:
1325 case Sema::PCC_RecoveryInFunction:
1326 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001327 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001328 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001329 return true;
1330
John McCallf312b1e2010-08-26 23:41:50 +00001331 case Sema::PCC_Expression:
1332 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001333 return LangOpts.CPlusPlus;
1334
1335 case Sema::PCC_ObjCInterface:
1336 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001337 return false;
1338
John McCallf312b1e2010-08-26 23:41:50 +00001339 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001340 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001341 }
1342
1343 return false;
1344}
1345
Douglas Gregor01dfea02010-01-10 23:08:15 +00001346/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001347static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001348 Scope *S,
1349 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001350 ResultBuilder &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001351 CodeCompletionBuilder Builder(Results.getAllocator());
1352
John McCall0a2c5e22010-08-25 06:19:51 +00001353 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001354 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001355 case Sema::PCC_Namespace:
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001356 if (SemaRef.getLangOptions().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001357 if (Results.includeCodePatterns()) {
1358 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001359 Builder.AddTypedTextChunk("namespace");
1360 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1361 Builder.AddPlaceholderChunk("identifier");
1362 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1363 Builder.AddPlaceholderChunk("declarations");
1364 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1365 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1366 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001367 }
1368
Douglas Gregor01dfea02010-01-10 23:08:15 +00001369 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001370 Builder.AddTypedTextChunk("namespace");
1371 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1372 Builder.AddPlaceholderChunk("name");
1373 Builder.AddChunk(CodeCompletionString::CK_Equal);
1374 Builder.AddPlaceholderChunk("namespace");
1375 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001376
1377 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001378 Builder.AddTypedTextChunk("using");
1379 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1380 Builder.AddTextChunk("namespace");
1381 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1382 Builder.AddPlaceholderChunk("identifier");
1383 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001384
1385 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001386 Builder.AddTypedTextChunk("asm");
1387 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1388 Builder.AddPlaceholderChunk("string-literal");
1389 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1390 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001391
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001392 if (Results.includeCodePatterns()) {
1393 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001394 Builder.AddTypedTextChunk("template");
1395 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1396 Builder.AddPlaceholderChunk("declaration");
1397 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001398 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001399 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001400
1401 if (SemaRef.getLangOptions().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001402 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001403
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001404 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001405 // Fall through
1406
John McCallf312b1e2010-08-26 23:41:50 +00001407 case Sema::PCC_Class:
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001408 if (SemaRef.getLangOptions().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001409 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001410 Builder.AddTypedTextChunk("using");
1411 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1412 Builder.AddPlaceholderChunk("qualifier");
1413 Builder.AddTextChunk("::");
1414 Builder.AddPlaceholderChunk("name");
1415 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001416
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001417 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001418 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001419 Builder.AddTypedTextChunk("using");
1420 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1421 Builder.AddTextChunk("typename");
1422 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1423 Builder.AddPlaceholderChunk("qualifier");
1424 Builder.AddTextChunk("::");
1425 Builder.AddPlaceholderChunk("name");
1426 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001427 }
1428
John McCallf312b1e2010-08-26 23:41:50 +00001429 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001430 AddTypedefResult(Results);
1431
Douglas Gregor01dfea02010-01-10 23:08:15 +00001432 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001433 Builder.AddTypedTextChunk("public");
1434 Builder.AddChunk(CodeCompletionString::CK_Colon);
1435 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001436
1437 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001438 Builder.AddTypedTextChunk("protected");
1439 Builder.AddChunk(CodeCompletionString::CK_Colon);
1440 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001441
1442 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001443 Builder.AddTypedTextChunk("private");
1444 Builder.AddChunk(CodeCompletionString::CK_Colon);
1445 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001446 }
1447 }
1448 // Fall through
1449
John McCallf312b1e2010-08-26 23:41:50 +00001450 case Sema::PCC_Template:
1451 case Sema::PCC_MemberTemplate:
Douglas Gregord8e8a582010-05-25 21:41:55 +00001452 if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001453 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001454 Builder.AddTypedTextChunk("template");
1455 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1456 Builder.AddPlaceholderChunk("parameters");
1457 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1458 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001459 }
1460
Douglas Gregorbca403c2010-01-13 23:51:12 +00001461 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1462 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001463 break;
1464
John McCallf312b1e2010-08-26 23:41:50 +00001465 case Sema::PCC_ObjCInterface:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001466 AddObjCInterfaceResults(SemaRef.getLangOptions(), Results, true);
1467 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1468 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001469 break;
1470
John McCallf312b1e2010-08-26 23:41:50 +00001471 case Sema::PCC_ObjCImplementation:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001472 AddObjCImplementationResults(SemaRef.getLangOptions(), Results, true);
1473 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1474 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001475 break;
1476
John McCallf312b1e2010-08-26 23:41:50 +00001477 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001478 AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001479 break;
1480
John McCallf312b1e2010-08-26 23:41:50 +00001481 case Sema::PCC_RecoveryInFunction:
1482 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001483 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001484
Douglas Gregorec3310a2011-04-12 02:47:21 +00001485 if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns() &&
1486 SemaRef.getLangOptions().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001487 Builder.AddTypedTextChunk("try");
1488 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1489 Builder.AddPlaceholderChunk("statements");
1490 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1491 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1492 Builder.AddTextChunk("catch");
1493 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1494 Builder.AddPlaceholderChunk("declaration");
1495 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1496 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1497 Builder.AddPlaceholderChunk("statements");
1498 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1499 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1500 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001501 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001502 if (SemaRef.getLangOptions().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001503 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001504
Douglas Gregord8e8a582010-05-25 21:41:55 +00001505 if (Results.includeCodePatterns()) {
1506 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001507 Builder.AddTypedTextChunk("if");
1508 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001509 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001510 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001511 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001512 Builder.AddPlaceholderChunk("expression");
1513 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1514 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1515 Builder.AddPlaceholderChunk("statements");
1516 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1517 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1518 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001519
Douglas Gregord8e8a582010-05-25 21:41:55 +00001520 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001521 Builder.AddTypedTextChunk("switch");
1522 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001523 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001524 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001525 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001526 Builder.AddPlaceholderChunk("expression");
1527 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1528 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1529 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1530 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1531 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001532 }
1533
Douglas Gregor01dfea02010-01-10 23:08:15 +00001534 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001535 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001536 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001537 Builder.AddTypedTextChunk("case");
1538 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1539 Builder.AddPlaceholderChunk("expression");
1540 Builder.AddChunk(CodeCompletionString::CK_Colon);
1541 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001542
1543 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001544 Builder.AddTypedTextChunk("default");
1545 Builder.AddChunk(CodeCompletionString::CK_Colon);
1546 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001547 }
1548
Douglas Gregord8e8a582010-05-25 21:41:55 +00001549 if (Results.includeCodePatterns()) {
1550 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001551 Builder.AddTypedTextChunk("while");
1552 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001553 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001554 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001555 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001556 Builder.AddPlaceholderChunk("expression");
1557 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1558 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1559 Builder.AddPlaceholderChunk("statements");
1560 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1561 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1562 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001563
1564 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001565 Builder.AddTypedTextChunk("do");
1566 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1567 Builder.AddPlaceholderChunk("statements");
1568 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1569 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1570 Builder.AddTextChunk("while");
1571 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1572 Builder.AddPlaceholderChunk("expression");
1573 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1574 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001575
Douglas Gregord8e8a582010-05-25 21:41:55 +00001576 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001577 Builder.AddTypedTextChunk("for");
1578 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001579 if (SemaRef.getLangOptions().CPlusPlus || SemaRef.getLangOptions().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001580 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001581 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001582 Builder.AddPlaceholderChunk("init-expression");
1583 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1584 Builder.AddPlaceholderChunk("condition");
1585 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1586 Builder.AddPlaceholderChunk("inc-expression");
1587 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1588 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1589 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1590 Builder.AddPlaceholderChunk("statements");
1591 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1592 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1593 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001594 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001595
1596 if (S->getContinueParent()) {
1597 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001598 Builder.AddTypedTextChunk("continue");
1599 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001600 }
1601
1602 if (S->getBreakParent()) {
1603 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001604 Builder.AddTypedTextChunk("break");
1605 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001606 }
1607
1608 // "return expression ;" or "return ;", depending on whether we
1609 // know the function is void or not.
1610 bool isVoid = false;
1611 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1612 isVoid = Function->getResultType()->isVoidType();
1613 else if (ObjCMethodDecl *Method
1614 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1615 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001616 else if (SemaRef.getCurBlock() &&
1617 !SemaRef.getCurBlock()->ReturnType.isNull())
1618 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001619 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001620 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001621 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1622 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001623 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001624 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001625
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001626 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001627 Builder.AddTypedTextChunk("goto");
1628 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1629 Builder.AddPlaceholderChunk("label");
1630 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001631
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001632 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001633 Builder.AddTypedTextChunk("using");
1634 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1635 Builder.AddTextChunk("namespace");
1636 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1637 Builder.AddPlaceholderChunk("identifier");
1638 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001639 }
1640
1641 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001642 case Sema::PCC_ForInit:
1643 case Sema::PCC_Condition:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001644 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001645 // Fall through: conditions and statements can have expressions.
1646
Douglas Gregor02688102010-09-14 23:59:36 +00001647 case Sema::PCC_ParenthesizedExpression:
John McCallf312b1e2010-08-26 23:41:50 +00001648 case Sema::PCC_Expression: {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001649 if (SemaRef.getLangOptions().CPlusPlus) {
1650 // 'this', if we're in a non-static member function.
1651 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(SemaRef.CurContext))
1652 if (!Method->isStatic())
Douglas Gregora4477812010-01-14 16:01:26 +00001653 Results.AddResult(Result("this"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001654
1655 // true, false
Douglas Gregora4477812010-01-14 16:01:26 +00001656 Results.AddResult(Result("true"));
1657 Results.AddResult(Result("false"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001658
Douglas Gregorec3310a2011-04-12 02:47:21 +00001659 if (SemaRef.getLangOptions().RTTI) {
1660 // dynamic_cast < type-id > ( expression )
1661 Builder.AddTypedTextChunk("dynamic_cast");
1662 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1663 Builder.AddPlaceholderChunk("type");
1664 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1665 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1666 Builder.AddPlaceholderChunk("expression");
1667 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1668 Results.AddResult(Result(Builder.TakeString()));
1669 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001670
1671 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001672 Builder.AddTypedTextChunk("static_cast");
1673 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1674 Builder.AddPlaceholderChunk("type");
1675 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1676 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1677 Builder.AddPlaceholderChunk("expression");
1678 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1679 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001680
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001681 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001682 Builder.AddTypedTextChunk("reinterpret_cast");
1683 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1684 Builder.AddPlaceholderChunk("type");
1685 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1686 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1687 Builder.AddPlaceholderChunk("expression");
1688 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1689 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001690
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001691 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001692 Builder.AddTypedTextChunk("const_cast");
1693 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1694 Builder.AddPlaceholderChunk("type");
1695 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1696 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1697 Builder.AddPlaceholderChunk("expression");
1698 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1699 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001700
Douglas Gregorec3310a2011-04-12 02:47:21 +00001701 if (SemaRef.getLangOptions().RTTI) {
1702 // typeid ( expression-or-type )
1703 Builder.AddTypedTextChunk("typeid");
1704 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1705 Builder.AddPlaceholderChunk("expression-or-type");
1706 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1707 Results.AddResult(Result(Builder.TakeString()));
1708 }
1709
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001710 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001711 Builder.AddTypedTextChunk("new");
1712 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1713 Builder.AddPlaceholderChunk("type");
1714 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1715 Builder.AddPlaceholderChunk("expressions");
1716 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1717 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001718
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001719 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001720 Builder.AddTypedTextChunk("new");
1721 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1722 Builder.AddPlaceholderChunk("type");
1723 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1724 Builder.AddPlaceholderChunk("size");
1725 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1726 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1727 Builder.AddPlaceholderChunk("expressions");
1728 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1729 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001730
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001731 // delete expression
Douglas Gregor218937c2011-02-01 19:23:04 +00001732 Builder.AddTypedTextChunk("delete");
1733 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1734 Builder.AddPlaceholderChunk("expression");
1735 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001736
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001737 // delete [] expression
Douglas Gregor218937c2011-02-01 19:23:04 +00001738 Builder.AddTypedTextChunk("delete");
1739 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1740 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1741 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1742 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1743 Builder.AddPlaceholderChunk("expression");
1744 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001745
Douglas Gregorec3310a2011-04-12 02:47:21 +00001746 if (SemaRef.getLangOptions().CXXExceptions) {
1747 // throw expression
1748 Builder.AddTypedTextChunk("throw");
1749 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1750 Builder.AddPlaceholderChunk("expression");
1751 Results.AddResult(Result(Builder.TakeString()));
1752 }
Douglas Gregor12e13132010-05-26 22:00:08 +00001753
1754 // FIXME: Rethrow?
Douglas Gregor01dfea02010-01-10 23:08:15 +00001755 }
1756
1757 if (SemaRef.getLangOptions().ObjC1) {
1758 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001759 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1760 // The interface can be NULL.
1761 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
1762 if (ID->getSuperClass())
1763 Results.AddResult(Result("super"));
1764 }
1765
Douglas Gregorbca403c2010-01-13 23:51:12 +00001766 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001767 }
1768
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001769 // sizeof expression
Douglas Gregor218937c2011-02-01 19:23:04 +00001770 Builder.AddTypedTextChunk("sizeof");
1771 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1772 Builder.AddPlaceholderChunk("expression-or-type");
1773 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1774 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001775 break;
1776 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001777
John McCallf312b1e2010-08-26 23:41:50 +00001778 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001779 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00001780 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001781 }
1782
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001783 if (WantTypesInContext(CCC, SemaRef.getLangOptions()))
1784 AddTypeSpecifierResults(SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001785
John McCallf312b1e2010-08-26 23:41:50 +00001786 if (SemaRef.getLangOptions().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00001787 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001788}
1789
Douglas Gregora63f6de2011-02-01 21:15:40 +00001790/// \brief Retrieve the string representation of the given type as a string
1791/// that has the appropriate lifetime for code completion.
1792///
1793/// This routine provides a fast path where we provide constant strings for
1794/// common type names.
Benjamin Kramerda57f3e2011-03-26 12:38:21 +00001795static const char *GetCompletionTypeString(QualType T,
1796 ASTContext &Context,
1797 CodeCompletionAllocator &Allocator) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00001798 PrintingPolicy Policy(Context.PrintingPolicy);
1799 Policy.AnonymousTagLocations = false;
1800
1801 if (!T.getLocalQualifiers()) {
1802 // Built-in type names are constant strings.
1803 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
1804 return BT->getName(Context.getLangOptions());
1805
1806 // Anonymous tag types are constant strings.
1807 if (const TagType *TagT = dyn_cast<TagType>(T))
1808 if (TagDecl *Tag = TagT->getDecl())
1809 if (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl()) {
1810 switch (Tag->getTagKind()) {
1811 case TTK_Struct: return "struct <anonymous>";
1812 case TTK_Class: return "class <anonymous>";
1813 case TTK_Union: return "union <anonymous>";
1814 case TTK_Enum: return "enum <anonymous>";
1815 }
1816 }
1817 }
1818
1819 // Slow path: format the type as a string.
1820 std::string Result;
1821 T.getAsStringInternal(Result, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00001822 return Allocator.CopyString(Result);
Douglas Gregora63f6de2011-02-01 21:15:40 +00001823}
1824
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001825/// \brief If the given declaration has an associated type, add it as a result
1826/// type chunk.
1827static void AddResultTypeChunk(ASTContext &Context,
1828 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00001829 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001830 if (!ND)
1831 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00001832
1833 // Skip constructors and conversion functions, which have their return types
1834 // built into their names.
1835 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
1836 return;
1837
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001838 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00001839 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001840 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
1841 T = Function->getResultType();
1842 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
1843 T = Method->getResultType();
1844 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
1845 T = FunTmpl->getTemplatedDecl()->getResultType();
1846 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
1847 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
1848 else if (isa<UnresolvedUsingValueDecl>(ND)) {
1849 /* Do nothing: ignore unresolved using declarations*/
1850 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
1851 T = Value->getType();
1852 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
1853 T = Property->getType();
1854
1855 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
1856 return;
1857
Douglas Gregora63f6de2011-02-01 21:15:40 +00001858 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context,
1859 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001860}
1861
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001862static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00001863 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001864 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
1865 if (Sentinel->getSentinel() == 0) {
1866 if (Context.getLangOptions().ObjC1 &&
1867 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00001868 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001869 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00001870 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001871 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001872 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001873 }
1874}
1875
Douglas Gregor83482d12010-08-24 16:15:59 +00001876static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregoraba48082010-08-29 19:47:46 +00001877 ParmVarDecl *Param,
1878 bool SuppressName = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00001879 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
1880 if (Param->getType()->isDependentType() ||
1881 !Param->getType()->isBlockPointerType()) {
1882 // The argument for a dependent or non-block parameter is a placeholder
1883 // containing that parameter's type.
1884 std::string Result;
1885
Douglas Gregoraba48082010-08-29 19:47:46 +00001886 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00001887 Result = Param->getIdentifier()->getName();
1888
1889 Param->getType().getAsStringInternal(Result,
1890 Context.PrintingPolicy);
1891
1892 if (ObjCMethodParam) {
1893 Result = "(" + Result;
1894 Result += ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00001895 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00001896 Result += Param->getIdentifier()->getName();
1897 }
1898 return Result;
1899 }
1900
1901 // The argument for a block pointer parameter is a block literal with
1902 // the appropriate type.
Douglas Gregor830072c2011-02-15 22:37:09 +00001903 FunctionTypeLoc *Block = 0;
1904 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregor83482d12010-08-24 16:15:59 +00001905 TypeLoc TL;
1906 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
1907 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
1908 while (true) {
1909 // Look through typedefs.
1910 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
1911 if (TypeSourceInfo *InnerTSInfo
1912 = TypedefTL->getTypedefDecl()->getTypeSourceInfo()) {
1913 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
1914 continue;
1915 }
1916 }
1917
1918 // Look through qualified types
1919 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
1920 TL = QualifiedTL->getUnqualifiedLoc();
1921 continue;
1922 }
1923
1924 // Try to get the function prototype behind the block pointer type,
1925 // then we're done.
1926 if (BlockPointerTypeLoc *BlockPtr
1927 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00001928 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor830072c2011-02-15 22:37:09 +00001929 Block = dyn_cast<FunctionTypeLoc>(&TL);
1930 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregor83482d12010-08-24 16:15:59 +00001931 }
1932 break;
1933 }
1934 }
1935
1936 if (!Block) {
1937 // We were unable to find a FunctionProtoTypeLoc with parameter names
1938 // for the block; just use the parameter type as a placeholder.
1939 std::string Result;
1940 Param->getType().getUnqualifiedType().
1941 getAsStringInternal(Result, Context.PrintingPolicy);
1942
1943 if (ObjCMethodParam) {
1944 Result = "(" + Result;
1945 Result += ")";
1946 if (Param->getIdentifier())
1947 Result += Param->getIdentifier()->getName();
1948 }
1949
1950 return Result;
1951 }
1952
1953 // We have the function prototype behind the block pointer type, as it was
1954 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00001955 std::string Result;
1956 QualType ResultType = Block->getTypePtr()->getResultType();
1957 if (!ResultType->isVoidType())
1958 ResultType.getAsStringInternal(Result, Context.PrintingPolicy);
1959
1960 Result = '^' + Result;
Douglas Gregor830072c2011-02-15 22:37:09 +00001961 if (!BlockProto || Block->getNumArgs() == 0) {
1962 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregor38276252010-09-08 22:47:51 +00001963 Result += "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00001964 else
1965 Result += "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00001966 } else {
1967 Result += "(";
1968 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
1969 if (I)
1970 Result += ", ";
1971 Result += FormatFunctionParameter(Context, Block->getArg(I));
1972
Douglas Gregor830072c2011-02-15 22:37:09 +00001973 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregor38276252010-09-08 22:47:51 +00001974 Result += ", ...";
1975 }
1976 Result += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00001977 }
Douglas Gregor38276252010-09-08 22:47:51 +00001978
Douglas Gregorc2760bc2010-10-02 23:49:58 +00001979 if (Param->getIdentifier())
1980 Result += Param->getIdentifier()->getName();
1981
Douglas Gregor83482d12010-08-24 16:15:59 +00001982 return Result;
1983}
1984
Douglas Gregor86d9a522009-09-21 16:56:56 +00001985/// \brief Add function parameter chunks to the given code completion string.
1986static void AddFunctionParameterChunks(ASTContext &Context,
1987 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00001988 CodeCompletionBuilder &Result,
1989 unsigned Start = 0,
1990 bool InOptional = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00001991 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00001992 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00001993
Douglas Gregor218937c2011-02-01 19:23:04 +00001994 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001995 ParmVarDecl *Param = Function->getParamDecl(P);
1996
Douglas Gregor218937c2011-02-01 19:23:04 +00001997 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001998 // When we see an optional default argument, put that argument and
1999 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002000 CodeCompletionBuilder Opt(Result.getAllocator());
2001 if (!FirstParameter)
2002 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
2003 AddFunctionParameterChunks(Context, Function, Opt, P, true);
2004 Result.AddOptionalChunk(Opt.TakeString());
2005 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002006 }
2007
Douglas Gregor218937c2011-02-01 19:23:04 +00002008 if (FirstParameter)
2009 FirstParameter = false;
2010 else
2011 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
2012
2013 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002014
2015 // Format the placeholder string.
Douglas Gregor83482d12010-08-24 16:15:59 +00002016 std::string PlaceholderStr = FormatFunctionParameter(Context, Param);
2017
Douglas Gregore17794f2010-08-31 05:13:43 +00002018 if (Function->isVariadic() && P == N - 1)
2019 PlaceholderStr += ", ...";
2020
Douglas Gregor86d9a522009-09-21 16:56:56 +00002021 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002022 Result.AddPlaceholderChunk(
2023 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002024 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002025
2026 if (const FunctionProtoType *Proto
2027 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002028 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002029 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002030 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002031
Douglas Gregor218937c2011-02-01 19:23:04 +00002032 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002033 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002034}
2035
2036/// \brief Add template parameter chunks to the given code completion string.
2037static void AddTemplateParameterChunks(ASTContext &Context,
2038 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002039 CodeCompletionBuilder &Result,
2040 unsigned MaxParameters = 0,
2041 unsigned Start = 0,
2042 bool InDefaultArg = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002043 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002044 bool FirstParameter = true;
2045
2046 TemplateParameterList *Params = Template->getTemplateParameters();
2047 TemplateParameterList::iterator PEnd = Params->end();
2048 if (MaxParameters)
2049 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002050 for (TemplateParameterList::iterator P = Params->begin() + Start;
2051 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002052 bool HasDefaultArg = false;
2053 std::string PlaceholderStr;
2054 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2055 if (TTP->wasDeclaredWithTypename())
2056 PlaceholderStr = "typename";
2057 else
2058 PlaceholderStr = "class";
2059
2060 if (TTP->getIdentifier()) {
2061 PlaceholderStr += ' ';
2062 PlaceholderStr += TTP->getIdentifier()->getName();
2063 }
2064
2065 HasDefaultArg = TTP->hasDefaultArgument();
2066 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002067 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002068 if (NTTP->getIdentifier())
2069 PlaceholderStr = NTTP->getIdentifier()->getName();
2070 NTTP->getType().getAsStringInternal(PlaceholderStr,
2071 Context.PrintingPolicy);
2072 HasDefaultArg = NTTP->hasDefaultArgument();
2073 } else {
2074 assert(isa<TemplateTemplateParmDecl>(*P));
2075 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2076
2077 // Since putting the template argument list into the placeholder would
2078 // be very, very long, we just use an abbreviation.
2079 PlaceholderStr = "template<...> class";
2080 if (TTP->getIdentifier()) {
2081 PlaceholderStr += ' ';
2082 PlaceholderStr += TTP->getIdentifier()->getName();
2083 }
2084
2085 HasDefaultArg = TTP->hasDefaultArgument();
2086 }
2087
Douglas Gregor218937c2011-02-01 19:23:04 +00002088 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002089 // When we see an optional default argument, put that argument and
2090 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002091 CodeCompletionBuilder Opt(Result.getAllocator());
2092 if (!FirstParameter)
2093 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
2094 AddTemplateParameterChunks(Context, Template, Opt, MaxParameters,
2095 P - Params->begin(), true);
2096 Result.AddOptionalChunk(Opt.TakeString());
2097 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002098 }
2099
Douglas Gregor218937c2011-02-01 19:23:04 +00002100 InDefaultArg = false;
2101
Douglas Gregor86d9a522009-09-21 16:56:56 +00002102 if (FirstParameter)
2103 FirstParameter = false;
2104 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002105 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002106
2107 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002108 Result.AddPlaceholderChunk(
2109 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002110 }
2111}
2112
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002113/// \brief Add a qualifier to the given code-completion string, if the
2114/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002115static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002116AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002117 NestedNameSpecifier *Qualifier,
2118 bool QualifierIsInformative,
2119 ASTContext &Context) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002120 if (!Qualifier)
2121 return;
2122
2123 std::string PrintedNNS;
2124 {
2125 llvm::raw_string_ostream OS(PrintedNNS);
2126 Qualifier->print(OS, Context.PrintingPolicy);
2127 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002128 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002129 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002130 else
Douglas Gregordae68752011-02-01 22:57:45 +00002131 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002132}
2133
Douglas Gregor218937c2011-02-01 19:23:04 +00002134static void
2135AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2136 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002137 const FunctionProtoType *Proto
2138 = Function->getType()->getAs<FunctionProtoType>();
2139 if (!Proto || !Proto->getTypeQuals())
2140 return;
2141
Douglas Gregora63f6de2011-02-01 21:15:40 +00002142 // FIXME: Add ref-qualifier!
2143
2144 // Handle single qualifiers without copying
2145 if (Proto->getTypeQuals() == Qualifiers::Const) {
2146 Result.AddInformativeChunk(" const");
2147 return;
2148 }
2149
2150 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2151 Result.AddInformativeChunk(" volatile");
2152 return;
2153 }
2154
2155 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2156 Result.AddInformativeChunk(" restrict");
2157 return;
2158 }
2159
2160 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002161 std::string QualsStr;
2162 if (Proto->getTypeQuals() & Qualifiers::Const)
2163 QualsStr += " const";
2164 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2165 QualsStr += " volatile";
2166 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2167 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002168 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002169}
2170
Douglas Gregor6f942b22010-09-21 16:06:22 +00002171/// \brief Add the name of the given declaration
2172static void AddTypedNameChunk(ASTContext &Context, NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00002173 CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002174 typedef CodeCompletionString::Chunk Chunk;
2175
2176 DeclarationName Name = ND->getDeclName();
2177 if (!Name)
2178 return;
2179
2180 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002181 case DeclarationName::CXXOperatorName: {
2182 const char *OperatorName = 0;
2183 switch (Name.getCXXOverloadedOperator()) {
2184 case OO_None:
2185 case OO_Conditional:
2186 case NUM_OVERLOADED_OPERATORS:
2187 OperatorName = "operator";
2188 break;
2189
2190#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2191 case OO_##Name: OperatorName = "operator" Spelling; break;
2192#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2193#include "clang/Basic/OperatorKinds.def"
2194
2195 case OO_New: OperatorName = "operator new"; break;
2196 case OO_Delete: OperatorName = "operator delete"; break;
2197 case OO_Array_New: OperatorName = "operator new[]"; break;
2198 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2199 case OO_Call: OperatorName = "operator()"; break;
2200 case OO_Subscript: OperatorName = "operator[]"; break;
2201 }
2202 Result.AddTypedTextChunk(OperatorName);
2203 break;
2204 }
2205
Douglas Gregor6f942b22010-09-21 16:06:22 +00002206 case DeclarationName::Identifier:
2207 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002208 case DeclarationName::CXXDestructorName:
2209 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002210 Result.AddTypedTextChunk(
2211 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002212 break;
2213
2214 case DeclarationName::CXXUsingDirective:
2215 case DeclarationName::ObjCZeroArgSelector:
2216 case DeclarationName::ObjCOneArgSelector:
2217 case DeclarationName::ObjCMultiArgSelector:
2218 break;
2219
2220 case DeclarationName::CXXConstructorName: {
2221 CXXRecordDecl *Record = 0;
2222 QualType Ty = Name.getCXXNameType();
2223 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2224 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2225 else if (const InjectedClassNameType *InjectedTy
2226 = Ty->getAs<InjectedClassNameType>())
2227 Record = InjectedTy->getDecl();
2228 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002229 Result.AddTypedTextChunk(
2230 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002231 break;
2232 }
2233
Douglas Gregordae68752011-02-01 22:57:45 +00002234 Result.AddTypedTextChunk(
2235 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002236 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002237 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002238 AddTemplateParameterChunks(Context, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002239 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002240 }
2241 break;
2242 }
2243 }
2244}
2245
Douglas Gregor86d9a522009-09-21 16:56:56 +00002246/// \brief If possible, create a new code completion string for the given
2247/// result.
2248///
2249/// \returns Either a new, heap-allocated code completion string describing
2250/// how to use this result, or NULL to indicate that the string or name of the
2251/// result is all that is needed.
2252CodeCompletionString *
John McCall0a2c5e22010-08-25 06:19:51 +00002253CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Douglas Gregordae68752011-02-01 22:57:45 +00002254 CodeCompletionAllocator &Allocator) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002255 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00002256 CodeCompletionBuilder Result(Allocator, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002257
Douglas Gregor218937c2011-02-01 19:23:04 +00002258 if (Kind == RK_Pattern) {
2259 Pattern->Priority = Priority;
2260 Pattern->Availability = Availability;
2261 return Pattern;
2262 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002263
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002264 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002265 Result.AddTypedTextChunk(Keyword);
2266 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002267 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002268
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002269 if (Kind == RK_Macro) {
2270 MacroInfo *MI = S.PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002271 assert(MI && "Not a macro?");
2272
Douglas Gregordae68752011-02-01 22:57:45 +00002273 Result.AddTypedTextChunk(
2274 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002275
2276 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002277 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002278
2279 // Format a function-like macro with placeholders for the arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00002280 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002281 for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
2282 A != AEnd; ++A) {
2283 if (A != MI->arg_begin())
Douglas Gregor218937c2011-02-01 19:23:04 +00002284 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002285
2286 if (!MI->isVariadic() || A != AEnd - 1) {
2287 // Non-variadic argument.
Douglas Gregordae68752011-02-01 22:57:45 +00002288 Result.AddPlaceholderChunk(
2289 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002290 continue;
2291 }
2292
2293 // Variadic argument; cope with the different between GNU and C99
2294 // variadic macros, providing a single placeholder for the rest of the
2295 // arguments.
2296 if ((*A)->isStr("__VA_ARGS__"))
Douglas Gregor218937c2011-02-01 19:23:04 +00002297 Result.AddPlaceholderChunk("...");
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002298 else {
2299 std::string Arg = (*A)->getName();
2300 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002301 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002302 }
2303 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002304 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2305 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002306 }
2307
Douglas Gregord8e8a582010-05-25 21:41:55 +00002308 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002309 NamedDecl *ND = Declaration;
2310
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002311 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002312 Result.AddTypedTextChunk(
2313 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002314 Result.AddTextChunk("::");
2315 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002316 }
2317
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002318 AddResultTypeChunk(S.Context, ND, Result);
2319
Douglas Gregor86d9a522009-09-21 16:56:56 +00002320 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002321 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2322 S.Context);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002323 AddTypedNameChunk(S.Context, ND, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002324 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002325 AddFunctionParameterChunks(S.Context, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002326 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002327 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002328 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002329 }
2330
2331 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002332 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2333 S.Context);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002334 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Douglas Gregor6f942b22010-09-21 16:06:22 +00002335 AddTypedNameChunk(S.Context, Function, Result);
2336
Douglas Gregor86d9a522009-09-21 16:56:56 +00002337 // Figure out which template parameters are deduced (or have default
2338 // arguments).
2339 llvm::SmallVector<bool, 16> Deduced;
2340 S.MarkDeducedTemplateParameters(FunTmpl, Deduced);
2341 unsigned LastDeducibleArgument;
2342 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2343 --LastDeducibleArgument) {
2344 if (!Deduced[LastDeducibleArgument - 1]) {
2345 // C++0x: Figure out if the template argument has a default. If so,
2346 // the user doesn't need to type this argument.
2347 // FIXME: We need to abstract template parameters better!
2348 bool HasDefaultArg = false;
2349 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002350 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002351 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2352 HasDefaultArg = TTP->hasDefaultArgument();
2353 else if (NonTypeTemplateParmDecl *NTTP
2354 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2355 HasDefaultArg = NTTP->hasDefaultArgument();
2356 else {
2357 assert(isa<TemplateTemplateParmDecl>(Param));
2358 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002359 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002360 }
2361
2362 if (!HasDefaultArg)
2363 break;
2364 }
2365 }
2366
2367 if (LastDeducibleArgument) {
2368 // Some of the function template arguments cannot be deduced from a
2369 // function call, so we introduce an explicit template argument list
2370 // containing all of the arguments up to the first deducible argument.
Douglas Gregor218937c2011-02-01 19:23:04 +00002371 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002372 AddTemplateParameterChunks(S.Context, FunTmpl, Result,
2373 LastDeducibleArgument);
Douglas Gregor218937c2011-02-01 19:23:04 +00002374 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002375 }
2376
2377 // Add the function parameters
Douglas Gregor218937c2011-02-01 19:23:04 +00002378 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002379 AddFunctionParameterChunks(S.Context, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002380 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002381 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002382 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002383 }
2384
2385 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002386 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2387 S.Context);
Douglas Gregordae68752011-02-01 22:57:45 +00002388 Result.AddTypedTextChunk(
2389 Result.getAllocator().CopyString(Template->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002390 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002391 AddTemplateParameterChunks(S.Context, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002392 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
2393 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002394 }
2395
Douglas Gregor9630eb62009-11-17 16:44:22 +00002396 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002397 Selector Sel = Method->getSelector();
2398 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002399 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002400 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002401 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002402 }
2403
Douglas Gregor813d8342011-02-18 22:29:55 +00002404 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002405 SelName += ':';
2406 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002407 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002408 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002409 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002410
2411 // If there is only one parameter, and we're past it, add an empty
2412 // typed-text chunk since there is nothing to type.
2413 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002414 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002415 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002416 unsigned Idx = 0;
2417 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2418 PEnd = Method->param_end();
2419 P != PEnd; (void)++P, ++Idx) {
2420 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002421 std::string Keyword;
2422 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002423 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002424 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
2425 Keyword += II->getName().str();
2426 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002427 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002428 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002429 else
Douglas Gregordae68752011-02-01 22:57:45 +00002430 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002431 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002432
2433 // If we're before the starting parameter, skip the placeholder.
2434 if (Idx < StartParameter)
2435 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002436
2437 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002438
2439 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Douglas Gregoraba48082010-08-29 19:47:46 +00002440 Arg = FormatFunctionParameter(S.Context, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002441 else {
2442 (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy);
2443 Arg = "(" + Arg + ")";
2444 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002445 if (DeclaringEntity || AllParametersAreInformative)
2446 Arg += II->getName().str();
Douglas Gregor83482d12010-08-24 16:15:59 +00002447 }
2448
Douglas Gregore17794f2010-08-31 05:13:43 +00002449 if (Method->isVariadic() && (P + 1) == PEnd)
2450 Arg += ", ...";
2451
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002452 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002453 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002454 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002455 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002456 else
Douglas Gregordae68752011-02-01 22:57:45 +00002457 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002458 }
2459
Douglas Gregor2a17af02009-12-23 00:21:46 +00002460 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002461 if (Method->param_size() == 0) {
2462 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002463 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002464 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002465 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002466 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002467 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002468 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002469
2470 MaybeAddSentinel(S.Context, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002471 }
2472
Douglas Gregor218937c2011-02-01 19:23:04 +00002473 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002474 }
2475
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002476 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002477 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2478 S.Context);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002479
Douglas Gregordae68752011-02-01 22:57:45 +00002480 Result.AddTypedTextChunk(
2481 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002482 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002483}
2484
Douglas Gregor86d802e2009-09-23 00:34:09 +00002485CodeCompletionString *
2486CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2487 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002488 Sema &S,
Douglas Gregordae68752011-02-01 22:57:45 +00002489 CodeCompletionAllocator &Allocator) const {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002490 typedef CodeCompletionString::Chunk Chunk;
2491
Douglas Gregor218937c2011-02-01 19:23:04 +00002492 // FIXME: Set priority, availability appropriately.
2493 CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002494 FunctionDecl *FDecl = getFunction();
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002495 AddResultTypeChunk(S.Context, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002496 const FunctionProtoType *Proto
2497 = dyn_cast<FunctionProtoType>(getFunctionType());
2498 if (!FDecl && !Proto) {
2499 // Function without a prototype. Just give the return type and a
2500 // highlighted ellipsis.
2501 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002502 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
2503 S.Context,
2504 Result.getAllocator()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002505 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
2506 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
2507 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2508 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002509 }
2510
2511 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002512 Result.AddTextChunk(
2513 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002514 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002515 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002516 Result.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00002517 Proto->getResultType().getAsString(S.Context.PrintingPolicy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002518
Douglas Gregor218937c2011-02-01 19:23:04 +00002519 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002520 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2521 for (unsigned I = 0; I != NumParams; ++I) {
2522 if (I)
Douglas Gregor218937c2011-02-01 19:23:04 +00002523 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002524
2525 std::string ArgString;
2526 QualType ArgType;
2527
2528 if (FDecl) {
2529 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2530 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2531 } else {
2532 ArgType = Proto->getArgType(I);
2533 }
2534
2535 ArgType.getAsStringInternal(ArgString, S.Context.PrintingPolicy);
2536
2537 if (I == CurrentArg)
Douglas Gregor218937c2011-02-01 19:23:04 +00002538 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter,
Douglas Gregordae68752011-02-01 22:57:45 +00002539 Result.getAllocator().CopyString(ArgString)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002540 else
Douglas Gregordae68752011-02-01 22:57:45 +00002541 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002542 }
2543
2544 if (Proto && Proto->isVariadic()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002545 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002546 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002547 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002548 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002549 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002550 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002551 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002552
Douglas Gregor218937c2011-02-01 19:23:04 +00002553 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002554}
2555
Douglas Gregor1827e102010-08-16 16:18:59 +00002556unsigned clang::getMacroUsagePriority(llvm::StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002557 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002558 bool PreferredTypeIsPointer) {
2559 unsigned Priority = CCP_Macro;
2560
Douglas Gregorb05496d2010-09-20 21:11:48 +00002561 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2562 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2563 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002564 Priority = CCP_Constant;
2565 if (PreferredTypeIsPointer)
2566 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002567 }
2568 // Treat "YES", "NO", "true", and "false" as constants.
2569 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2570 MacroName.equals("true") || MacroName.equals("false"))
2571 Priority = CCP_Constant;
2572 // Treat "bool" as a type.
2573 else if (MacroName.equals("bool"))
2574 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2575
Douglas Gregor1827e102010-08-16 16:18:59 +00002576
2577 return Priority;
2578}
2579
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002580CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2581 if (!D)
2582 return CXCursor_UnexposedDecl;
2583
2584 switch (D->getKind()) {
2585 case Decl::Enum: return CXCursor_EnumDecl;
2586 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2587 case Decl::Field: return CXCursor_FieldDecl;
2588 case Decl::Function:
2589 return CXCursor_FunctionDecl;
2590 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2591 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
2592 case Decl::ObjCClass:
2593 // FIXME
2594 return CXCursor_UnexposedDecl;
2595 case Decl::ObjCForwardProtocol:
2596 // FIXME
2597 return CXCursor_UnexposedDecl;
2598 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
2599 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
2600 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2601 case Decl::ObjCMethod:
2602 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2603 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2604 case Decl::CXXMethod: return CXCursor_CXXMethod;
2605 case Decl::CXXConstructor: return CXCursor_Constructor;
2606 case Decl::CXXDestructor: return CXCursor_Destructor;
2607 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2608 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
2609 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
2610 case Decl::ParmVar: return CXCursor_ParmDecl;
2611 case Decl::Typedef: return CXCursor_TypedefDecl;
2612 case Decl::Var: return CXCursor_VarDecl;
2613 case Decl::Namespace: return CXCursor_Namespace;
2614 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2615 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2616 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2617 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2618 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2619 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
2620 case Decl::ClassTemplatePartialSpecialization:
2621 return CXCursor_ClassTemplatePartialSpecialization;
2622 case Decl::UsingDirective: return CXCursor_UsingDirective;
2623
2624 case Decl::Using:
2625 case Decl::UnresolvedUsingValue:
2626 case Decl::UnresolvedUsingTypename:
2627 return CXCursor_UsingDeclaration;
2628
2629 default:
2630 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2631 switch (TD->getTagKind()) {
2632 case TTK_Struct: return CXCursor_StructDecl;
2633 case TTK_Class: return CXCursor_ClassDecl;
2634 case TTK_Union: return CXCursor_UnionDecl;
2635 case TTK_Enum: return CXCursor_EnumDecl;
2636 }
2637 }
2638 }
2639
2640 return CXCursor_UnexposedDecl;
2641}
2642
Douglas Gregor590c7d52010-07-08 20:55:51 +00002643static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2644 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002645 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002646
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002647 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002648
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002649 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2650 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002651 M != MEnd; ++M) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002652 Results.AddResult(Result(M->first,
2653 getMacroUsagePriority(M->first->getName(),
Douglas Gregorb05496d2010-09-20 21:11:48 +00002654 PP.getLangOptions(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002655 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002656 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002657
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002658 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002659
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002660}
2661
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002662static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2663 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002664 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002665
2666 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002667
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002668 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2669 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2670 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2671 Results.AddResult(Result("__func__", CCP_Constant));
2672 Results.ExitScope();
2673}
2674
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002675static void HandleCodeCompleteResults(Sema *S,
2676 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002677 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002678 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002679 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002680 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002681 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002682}
2683
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002684static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2685 Sema::ParserCompletionContext PCC) {
2686 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002687 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002688 return CodeCompletionContext::CCC_TopLevel;
2689
John McCallf312b1e2010-08-26 23:41:50 +00002690 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002691 return CodeCompletionContext::CCC_ClassStructUnion;
2692
John McCallf312b1e2010-08-26 23:41:50 +00002693 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002694 return CodeCompletionContext::CCC_ObjCInterface;
2695
John McCallf312b1e2010-08-26 23:41:50 +00002696 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002697 return CodeCompletionContext::CCC_ObjCImplementation;
2698
John McCallf312b1e2010-08-26 23:41:50 +00002699 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002700 return CodeCompletionContext::CCC_ObjCIvarList;
2701
John McCallf312b1e2010-08-26 23:41:50 +00002702 case Sema::PCC_Template:
2703 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002704 if (S.CurContext->isFileContext())
2705 return CodeCompletionContext::CCC_TopLevel;
2706 else if (S.CurContext->isRecord())
2707 return CodeCompletionContext::CCC_ClassStructUnion;
2708 else
2709 return CodeCompletionContext::CCC_Other;
2710
John McCallf312b1e2010-08-26 23:41:50 +00002711 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002712 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002713
John McCallf312b1e2010-08-26 23:41:50 +00002714 case Sema::PCC_ForInit:
Douglas Gregora5450a02010-10-18 22:01:46 +00002715 if (S.getLangOptions().CPlusPlus || S.getLangOptions().C99 ||
2716 S.getLangOptions().ObjC1)
2717 return CodeCompletionContext::CCC_ParenthesizedExpression;
2718 else
2719 return CodeCompletionContext::CCC_Expression;
2720
2721 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002722 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002723 return CodeCompletionContext::CCC_Expression;
2724
John McCallf312b1e2010-08-26 23:41:50 +00002725 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002726 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002727
John McCallf312b1e2010-08-26 23:41:50 +00002728 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002729 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002730
2731 case Sema::PCC_ParenthesizedExpression:
2732 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002733
2734 case Sema::PCC_LocalDeclarationSpecifiers:
2735 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002736 }
2737
2738 return CodeCompletionContext::CCC_Other;
2739}
2740
Douglas Gregorf6961522010-08-27 21:18:54 +00002741/// \brief If we're in a C++ virtual member function, add completion results
2742/// that invoke the functions we override, since it's common to invoke the
2743/// overridden function as well as adding new functionality.
2744///
2745/// \param S The semantic analysis object for which we are generating results.
2746///
2747/// \param InContext This context in which the nested-name-specifier preceding
2748/// the code-completion point
2749static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2750 ResultBuilder &Results) {
2751 // Look through blocks.
2752 DeclContext *CurContext = S.CurContext;
2753 while (isa<BlockDecl>(CurContext))
2754 CurContext = CurContext->getParent();
2755
2756
2757 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2758 if (!Method || !Method->isVirtual())
2759 return;
2760
2761 // We need to have names for all of the parameters, if we're going to
2762 // generate a forwarding call.
2763 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2764 PEnd = Method->param_end();
2765 P != PEnd;
2766 ++P) {
2767 if (!(*P)->getDeclName())
2768 return;
2769 }
2770
2771 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
2772 MEnd = Method->end_overridden_methods();
2773 M != MEnd; ++M) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002774 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf6961522010-08-27 21:18:54 +00002775 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
2776 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
2777 continue;
2778
2779 // If we need a nested-name-specifier, add one now.
2780 if (!InContext) {
2781 NestedNameSpecifier *NNS
2782 = getRequiredQualification(S.Context, CurContext,
2783 Overridden->getDeclContext());
2784 if (NNS) {
2785 std::string Str;
2786 llvm::raw_string_ostream OS(Str);
2787 NNS->print(OS, S.Context.PrintingPolicy);
Douglas Gregordae68752011-02-01 22:57:45 +00002788 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00002789 }
2790 } else if (!InContext->Equals(Overridden->getDeclContext()))
2791 continue;
2792
Douglas Gregordae68752011-02-01 22:57:45 +00002793 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00002794 Overridden->getNameAsString()));
2795 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00002796 bool FirstParam = true;
2797 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2798 PEnd = Method->param_end();
2799 P != PEnd; ++P) {
2800 if (FirstParam)
2801 FirstParam = false;
2802 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002803 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00002804
Douglas Gregordae68752011-02-01 22:57:45 +00002805 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00002806 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00002807 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002808 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2809 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00002810 CCP_SuperCompletion,
2811 CXCursor_CXXMethod));
2812 Results.Ignore(Overridden);
2813 }
2814}
2815
Douglas Gregor01dfea02010-01-10 23:08:15 +00002816void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002817 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00002818 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00002819 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00002820 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00002821 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00002822
Douglas Gregor01dfea02010-01-10 23:08:15 +00002823 // Determine how to filter results, e.g., so that the names of
2824 // values (functions, enumerators, function templates, etc.) are
2825 // only allowed where we can have an expression.
2826 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002827 case PCC_Namespace:
2828 case PCC_Class:
2829 case PCC_ObjCInterface:
2830 case PCC_ObjCImplementation:
2831 case PCC_ObjCInstanceVariableList:
2832 case PCC_Template:
2833 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00002834 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002835 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00002836 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
2837 break;
2838
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002839 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00002840 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00002841 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002842 case PCC_ForInit:
2843 case PCC_Condition:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00002844 if (WantTypesInContext(CompletionContext, getLangOptions()))
2845 Results.setFilter(&ResultBuilder::IsOrdinaryName);
2846 else
2847 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00002848
2849 if (getLangOptions().CPlusPlus)
2850 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00002851 break;
Douglas Gregordc845342010-05-25 05:58:43 +00002852
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002853 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00002854 // Unfiltered
2855 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00002856 }
2857
Douglas Gregor3cdee122010-08-26 16:36:48 +00002858 // If we are in a C++ non-static member function, check the qualifiers on
2859 // the member function to filter/prioritize the results list.
2860 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
2861 if (CurMethod->isInstance())
2862 Results.setObjectTypeQualifiers(
2863 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
2864
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00002865 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00002866 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
2867 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00002868
Douglas Gregorbca403c2010-01-13 23:51:12 +00002869 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00002870 Results.ExitScope();
2871
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002872 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00002873 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00002874 case PCC_Expression:
2875 case PCC_Statement:
2876 case PCC_RecoveryInFunction:
2877 if (S->getFnParent())
2878 AddPrettyFunctionResults(PP.getLangOptions(), Results);
2879 break;
2880
2881 case PCC_Namespace:
2882 case PCC_Class:
2883 case PCC_ObjCInterface:
2884 case PCC_ObjCImplementation:
2885 case PCC_ObjCInstanceVariableList:
2886 case PCC_Template:
2887 case PCC_MemberTemplate:
2888 case PCC_ForInit:
2889 case PCC_Condition:
2890 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002891 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00002892 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002893 }
2894
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002895 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00002896 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002897
Douglas Gregorcee9ff12010-09-20 22:39:41 +00002898 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002899 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00002900}
2901
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002902static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
2903 ParsedType Receiver,
2904 IdentifierInfo **SelIdents,
2905 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00002906 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002907 bool IsSuper,
2908 ResultBuilder &Results);
2909
2910void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
2911 bool AllowNonIdentifiers,
2912 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00002913 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00002914 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00002915 AllowNestedNameSpecifiers
2916 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
2917 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002918 Results.EnterNewScope();
2919
2920 // Type qualifiers can come after names.
2921 Results.AddResult(Result("const"));
2922 Results.AddResult(Result("volatile"));
2923 if (getLangOptions().C99)
2924 Results.AddResult(Result("restrict"));
2925
2926 if (getLangOptions().CPlusPlus) {
2927 if (AllowNonIdentifiers) {
2928 Results.AddResult(Result("operator"));
2929 }
2930
2931 // Add nested-name-specifiers.
2932 if (AllowNestedNameSpecifiers) {
2933 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00002934 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002935 CodeCompletionDeclConsumer Consumer(Results, CurContext);
2936 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
2937 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00002938 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002939 }
2940 }
2941 Results.ExitScope();
2942
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002943 // If we're in a context where we might have an expression (rather than a
2944 // declaration), and what we've seen so far is an Objective-C type that could
2945 // be a receiver of a class message, this may be a class message send with
2946 // the initial opening bracket '[' missing. Add appropriate completions.
2947 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
2948 DS.getTypeSpecType() == DeclSpec::TST_typename &&
2949 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
2950 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
2951 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
2952 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
2953 DS.getTypeQualifiers() == 0 &&
2954 S &&
2955 (S->getFlags() & Scope::DeclScope) != 0 &&
2956 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
2957 Scope::FunctionPrototypeScope |
2958 Scope::AtCatchScope)) == 0) {
2959 ParsedType T = DS.getRepAsType();
2960 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00002961 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002962 }
2963
Douglas Gregor4497dd42010-08-24 04:59:56 +00002964 // Note that we intentionally suppress macro results here, since we do not
2965 // encourage using macros to produce the names of entities.
2966
Douglas Gregor52779fb2010-09-23 23:01:17 +00002967 HandleCodeCompleteResults(this, CodeCompleter,
2968 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002969 Results.data(), Results.size());
2970}
2971
Douglas Gregorfb629412010-08-23 21:17:50 +00002972struct Sema::CodeCompleteExpressionData {
2973 CodeCompleteExpressionData(QualType PreferredType = QualType())
2974 : PreferredType(PreferredType), IntegralConstantExpression(false),
2975 ObjCCollection(false) { }
2976
2977 QualType PreferredType;
2978 bool IntegralConstantExpression;
2979 bool ObjCCollection;
2980 llvm::SmallVector<Decl *, 4> IgnoreDecls;
2981};
2982
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002983/// \brief Perform code-completion in an expression context when we know what
2984/// type we're looking for.
Douglas Gregorf9578432010-07-28 21:50:18 +00002985///
2986/// \param IntegralConstantExpression Only permit integral constant
2987/// expressions.
Douglas Gregorfb629412010-08-23 21:17:50 +00002988void Sema::CodeCompleteExpression(Scope *S,
2989 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00002990 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00002991 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
2992 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00002993 if (Data.ObjCCollection)
2994 Results.setFilter(&ResultBuilder::IsObjCCollection);
2995 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00002996 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002997 else if (WantTypesInContext(PCC_Expression, getLangOptions()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002998 Results.setFilter(&ResultBuilder::IsOrdinaryName);
2999 else
3000 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003001
3002 if (!Data.PreferredType.isNull())
3003 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3004
3005 // Ignore any declarations that we were told that we don't care about.
3006 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3007 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003008
3009 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003010 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3011 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003012
3013 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003014 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003015 Results.ExitScope();
3016
Douglas Gregor590c7d52010-07-08 20:55:51 +00003017 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003018 if (!Data.PreferredType.isNull())
3019 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3020 || Data.PreferredType->isMemberPointerType()
3021 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003022
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003023 if (S->getFnParent() &&
3024 !Data.ObjCCollection &&
3025 !Data.IntegralConstantExpression)
3026 AddPrettyFunctionResults(PP.getLangOptions(), Results);
3027
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003028 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003029 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003030 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003031 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3032 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003033 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003034}
3035
Douglas Gregorac5fd842010-09-18 01:28:11 +00003036void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3037 if (E.isInvalid())
3038 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
3039 else if (getLangOptions().ObjC1)
3040 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003041}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003042
Douglas Gregor73449212010-12-09 23:01:55 +00003043/// \brief The set of properties that have already been added, referenced by
3044/// property name.
3045typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3046
Douglas Gregor95ac6552009-11-18 01:29:26 +00003047static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003048 bool AllowCategories,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003049 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003050 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003051 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003052 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003053
3054 // Add properties in this container.
3055 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3056 PEnd = Container->prop_end();
3057 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003058 ++P) {
3059 if (AddedProperties.insert(P->getIdentifier()))
3060 Results.MaybeAddResult(Result(*P, 0), CurContext);
3061 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003062
3063 // Add properties in referenced protocols.
3064 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3065 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3066 PEnd = Protocol->protocol_end();
3067 P != PEnd; ++P)
Douglas Gregor73449212010-12-09 23:01:55 +00003068 AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties,
3069 Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003070 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003071 if (AllowCategories) {
3072 // Look through categories.
3073 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3074 Category; Category = Category->getNextClassCategory())
Douglas Gregor73449212010-12-09 23:01:55 +00003075 AddObjCProperties(Category, AllowCategories, CurContext,
3076 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003077 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003078
3079 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003080 for (ObjCInterfaceDecl::all_protocol_iterator
3081 I = IFace->all_referenced_protocol_begin(),
3082 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor73449212010-12-09 23:01:55 +00003083 AddObjCProperties(*I, AllowCategories, CurContext, AddedProperties,
3084 Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003085
3086 // Look in the superclass.
3087 if (IFace->getSuperClass())
Douglas Gregor322328b2009-11-18 22:32:06 +00003088 AddObjCProperties(IFace->getSuperClass(), AllowCategories, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003089 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003090 } else if (const ObjCCategoryDecl *Category
3091 = dyn_cast<ObjCCategoryDecl>(Container)) {
3092 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003093 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3094 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003095 P != PEnd; ++P)
Douglas Gregor73449212010-12-09 23:01:55 +00003096 AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties,
3097 Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003098 }
3099}
3100
Douglas Gregor81b747b2009-09-17 21:32:03 +00003101void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
3102 SourceLocation OpLoc,
3103 bool IsArrow) {
3104 if (!BaseE || !CodeCompleter)
3105 return;
3106
John McCall0a2c5e22010-08-25 06:19:51 +00003107 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003108
Douglas Gregor81b747b2009-09-17 21:32:03 +00003109 Expr *Base = static_cast<Expr *>(BaseE);
3110 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003111
3112 if (IsArrow) {
3113 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3114 BaseType = Ptr->getPointeeType();
3115 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003116 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003117 else
3118 return;
3119 }
3120
Douglas Gregor218937c2011-02-01 19:23:04 +00003121 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003122 CodeCompletionContext(CodeCompletionContext::CCC_MemberAccess,
3123 BaseType),
3124 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003125 Results.EnterNewScope();
3126 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003127 // Indicate that we are performing a member access, and the cv-qualifiers
3128 // for the base object type.
3129 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3130
Douglas Gregor95ac6552009-11-18 01:29:26 +00003131 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003132 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003133 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003134 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3135 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003136
Douglas Gregor95ac6552009-11-18 01:29:26 +00003137 if (getLangOptions().CPlusPlus) {
3138 if (!Results.empty()) {
3139 // The "template" keyword can follow "->" or "." in the grammar.
3140 // However, we only want to suggest the template keyword if something
3141 // is dependent.
3142 bool IsDependent = BaseType->isDependentType();
3143 if (!IsDependent) {
3144 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3145 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3146 IsDependent = Ctx->isDependentContext();
3147 break;
3148 }
3149 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003150
Douglas Gregor95ac6552009-11-18 01:29:26 +00003151 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003152 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003153 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003154 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003155 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3156 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003157 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003158
3159 // Add property results based on our interface.
3160 const ObjCObjectPointerType *ObjCPtr
3161 = BaseType->getAsObjCInterfacePointerType();
3162 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor73449212010-12-09 23:01:55 +00003163 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, CurContext,
3164 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003165
3166 // Add properties from the protocols in a qualified interface.
3167 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3168 E = ObjCPtr->qual_end();
3169 I != E; ++I)
Douglas Gregor73449212010-12-09 23:01:55 +00003170 AddObjCProperties(*I, true, CurContext, AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003171 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003172 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003173 // Objective-C instance variable access.
3174 ObjCInterfaceDecl *Class = 0;
3175 if (const ObjCObjectPointerType *ObjCPtr
3176 = BaseType->getAs<ObjCObjectPointerType>())
3177 Class = ObjCPtr->getInterfaceDecl();
3178 else
John McCallc12c5bb2010-05-15 11:32:37 +00003179 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003180
3181 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003182 if (Class) {
3183 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3184 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003185 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3186 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003187 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003188 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003189
3190 // FIXME: How do we cope with isa?
3191
3192 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003193
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003194 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003195 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003196 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003197 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003198}
3199
Douglas Gregor374929f2009-09-18 15:37:17 +00003200void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3201 if (!CodeCompleter)
3202 return;
3203
John McCall0a2c5e22010-08-25 06:19:51 +00003204 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003205 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003206 enum CodeCompletionContext::Kind ContextKind
3207 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003208 switch ((DeclSpec::TST)TagSpec) {
3209 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003210 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003211 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003212 break;
3213
3214 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003215 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003216 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003217 break;
3218
3219 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003220 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003221 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003222 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003223 break;
3224
3225 default:
3226 assert(false && "Unknown type specifier kind in CodeCompleteTag");
3227 return;
3228 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003229
Douglas Gregor218937c2011-02-01 19:23:04 +00003230 ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003231 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003232
3233 // First pass: look for tags.
3234 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003235 LookupVisibleDecls(S, LookupTagName, Consumer,
3236 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003237
Douglas Gregor8071e422010-08-15 06:18:01 +00003238 if (CodeCompleter->includeGlobals()) {
3239 // Second pass: look for nested name specifiers.
3240 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3241 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3242 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003243
Douglas Gregor52779fb2010-09-23 23:01:17 +00003244 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003245 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003246}
3247
Douglas Gregor1a480c42010-08-27 17:35:51 +00003248void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003249 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3250 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003251 Results.EnterNewScope();
3252 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3253 Results.AddResult("const");
3254 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3255 Results.AddResult("volatile");
3256 if (getLangOptions().C99 &&
3257 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3258 Results.AddResult("restrict");
3259 Results.ExitScope();
3260 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003261 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003262 Results.data(), Results.size());
3263}
3264
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003265void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003266 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003267 return;
3268
John McCall781472f2010-08-25 08:40:02 +00003269 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
Douglas Gregorf9578432010-07-28 21:50:18 +00003270 if (!Switch->getCond()->getType()->isEnumeralType()) {
Douglas Gregorfb629412010-08-23 21:17:50 +00003271 CodeCompleteExpressionData Data(Switch->getCond()->getType());
3272 Data.IntegralConstantExpression = true;
3273 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003274 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003275 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003276
3277 // Code-complete the cases of a switch statement over an enumeration type
3278 // by providing the list of
3279 EnumDecl *Enum = Switch->getCond()->getType()->getAs<EnumType>()->getDecl();
3280
3281 // Determine which enumerators we have already seen in the switch statement.
3282 // FIXME: Ideally, we would also be able to look *past* the code-completion
3283 // token, in case we are code-completing in the middle of the switch and not
3284 // at the end. However, we aren't able to do so at the moment.
3285 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003286 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003287 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3288 SC = SC->getNextSwitchCase()) {
3289 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3290 if (!Case)
3291 continue;
3292
3293 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3294 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3295 if (EnumConstantDecl *Enumerator
3296 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3297 // We look into the AST of the case statement to determine which
3298 // enumerator was named. Alternatively, we could compute the value of
3299 // the integral constant expression, then compare it against the
3300 // values of each enumerator. However, value-based approach would not
3301 // work as well with C++ templates where enumerators declared within a
3302 // template are type- and value-dependent.
3303 EnumeratorsSeen.insert(Enumerator);
3304
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003305 // If this is a qualified-id, keep track of the nested-name-specifier
3306 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003307 //
3308 // switch (TagD.getKind()) {
3309 // case TagDecl::TK_enum:
3310 // break;
3311 // case XXX
3312 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003313 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003314 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3315 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003316 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003317 }
3318 }
3319
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003320 if (getLangOptions().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
3321 // If there are no prior enumerators in C++, check whether we have to
3322 // qualify the names of the enumerators that we suggest, because they
3323 // may not be visible in this scope.
3324 Qualifier = getRequiredQualification(Context, CurContext,
3325 Enum->getDeclContext());
3326
3327 // FIXME: Scoped enums need to start with "EnumDecl" as the context!
3328 }
3329
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003330 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003331 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3332 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003333 Results.EnterNewScope();
3334 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3335 EEnd = Enum->enumerator_end();
3336 E != EEnd; ++E) {
3337 if (EnumeratorsSeen.count(*E))
3338 continue;
3339
Douglas Gregor5c722c702011-02-18 23:30:37 +00003340 CodeCompletionResult R(*E, Qualifier);
3341 R.Priority = CCP_EnumInCase;
3342 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003343 }
3344 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003345
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003346 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003347 AddMacroResults(PP, Results);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003348 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor5c722c702011-02-18 23:30:37 +00003349 CodeCompletionContext::CCC_OtherWithMacros,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003350 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003351}
3352
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003353namespace {
3354 struct IsBetterOverloadCandidate {
3355 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003356 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003357
3358 public:
John McCall5769d612010-02-08 23:07:23 +00003359 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3360 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003361
3362 bool
3363 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003364 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003365 }
3366 };
3367}
3368
Douglas Gregord28dcd72010-05-30 06:10:08 +00003369static bool anyNullArguments(Expr **Args, unsigned NumArgs) {
3370 if (NumArgs && !Args)
3371 return true;
3372
3373 for (unsigned I = 0; I != NumArgs; ++I)
3374 if (!Args[I])
3375 return true;
3376
3377 return false;
3378}
3379
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003380void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
3381 ExprTy **ArgsIn, unsigned NumArgs) {
3382 if (!CodeCompleter)
3383 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003384
3385 // When we're code-completing for a call, we fall back to ordinary
3386 // name code-completion whenever we can't produce specific
3387 // results. We may want to revisit this strategy in the future,
3388 // e.g., by merging the two kinds of results.
3389
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003390 Expr *Fn = (Expr *)FnIn;
3391 Expr **Args = (Expr **)ArgsIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003392
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003393 // Ignore type-dependent call expressions entirely.
Douglas Gregord28dcd72010-05-30 06:10:08 +00003394 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) ||
Douglas Gregoref96eac2009-12-11 19:06:04 +00003395 Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003396 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003397 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003398 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003399
John McCall3b4294e2009-12-16 12:17:52 +00003400 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003401 SourceLocation Loc = Fn->getExprLoc();
3402 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003403
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003404 // FIXME: What if we're calling something that isn't a function declaration?
3405 // FIXME: What if we're calling a pseudo-destructor?
3406 // FIXME: What if we're calling a member function?
3407
Douglas Gregorc0265402010-01-21 15:46:19 +00003408 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
3409 llvm::SmallVector<ResultCandidate, 8> Results;
3410
John McCall3b4294e2009-12-16 12:17:52 +00003411 Expr *NakedFn = Fn->IgnoreParenCasts();
3412 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
3413 AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet,
3414 /*PartialOverloading=*/ true);
3415 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3416 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003417 if (FDecl) {
Douglas Gregord28dcd72010-05-30 06:10:08 +00003418 if (!getLangOptions().CPlusPlus ||
3419 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003420 Results.push_back(ResultCandidate(FDecl));
3421 else
John McCall86820f52010-01-26 01:37:31 +00003422 // FIXME: access?
John McCall9aa472c2010-03-19 07:35:19 +00003423 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none),
3424 Args, NumArgs, CandidateSet,
Douglas Gregorc27d6c52010-04-16 17:41:49 +00003425 false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003426 }
John McCall3b4294e2009-12-16 12:17:52 +00003427 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003428
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003429 QualType ParamType;
3430
Douglas Gregorc0265402010-01-21 15:46:19 +00003431 if (!CandidateSet.empty()) {
3432 // Sort the overload candidate set by placing the best overloads first.
3433 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003434 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003435
Douglas Gregorc0265402010-01-21 15:46:19 +00003436 // Add the remaining viable overload candidates as code-completion reslults.
3437 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3438 CandEnd = CandidateSet.end();
3439 Cand != CandEnd; ++Cand) {
3440 if (Cand->Viable)
3441 Results.push_back(ResultCandidate(Cand->Function));
3442 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003443
3444 // From the viable candidates, try to determine the type of this parameter.
3445 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3446 if (const FunctionType *FType = Results[I].getFunctionType())
3447 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
3448 if (NumArgs < Proto->getNumArgs()) {
3449 if (ParamType.isNull())
3450 ParamType = Proto->getArgType(NumArgs);
3451 else if (!Context.hasSameUnqualifiedType(
3452 ParamType.getNonReferenceType(),
3453 Proto->getArgType(NumArgs).getNonReferenceType())) {
3454 ParamType = QualType();
3455 break;
3456 }
3457 }
3458 }
3459 } else {
3460 // Try to determine the parameter type from the type of the expression
3461 // being called.
3462 QualType FunctionType = Fn->getType();
3463 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3464 FunctionType = Ptr->getPointeeType();
3465 else if (const BlockPointerType *BlockPtr
3466 = FunctionType->getAs<BlockPointerType>())
3467 FunctionType = BlockPtr->getPointeeType();
3468 else if (const MemberPointerType *MemPtr
3469 = FunctionType->getAs<MemberPointerType>())
3470 FunctionType = MemPtr->getPointeeType();
3471
3472 if (const FunctionProtoType *Proto
3473 = FunctionType->getAs<FunctionProtoType>()) {
3474 if (NumArgs < Proto->getNumArgs())
3475 ParamType = Proto->getArgType(NumArgs);
3476 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003477 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003478
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003479 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003480 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003481 else
3482 CodeCompleteExpression(S, ParamType);
3483
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003484 if (!Results.empty())
Douglas Gregoref96eac2009-12-11 19:06:04 +00003485 CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(),
3486 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003487}
3488
John McCalld226f652010-08-21 09:40:31 +00003489void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3490 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003491 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003492 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003493 return;
3494 }
3495
3496 CodeCompleteExpression(S, VD->getType());
3497}
3498
3499void Sema::CodeCompleteReturn(Scope *S) {
3500 QualType ResultType;
3501 if (isa<BlockDecl>(CurContext)) {
3502 if (BlockScopeInfo *BSI = getCurBlock())
3503 ResultType = BSI->ReturnType;
3504 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3505 ResultType = Function->getResultType();
3506 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3507 ResultType = Method->getResultType();
3508
3509 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003510 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003511 else
3512 CodeCompleteExpression(S, ResultType);
3513}
3514
3515void Sema::CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) {
3516 if (LHS)
3517 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3518 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003519 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003520}
3521
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003522void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003523 bool EnteringContext) {
3524 if (!SS.getScopeRep() || !CodeCompleter)
3525 return;
3526
Douglas Gregor86d9a522009-09-21 16:56:56 +00003527 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3528 if (!Ctx)
3529 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003530
3531 // Try to instantiate any non-dependent declaration contexts before
3532 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003533 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003534 return;
3535
Douglas Gregor218937c2011-02-01 19:23:04 +00003536 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3537 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003538 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003539
Douglas Gregor86d9a522009-09-21 16:56:56 +00003540 // The "template" keyword can follow "::" in the grammar, but only
3541 // put it into the grammar if the nested-name-specifier is dependent.
3542 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3543 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003544 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003545
3546 // Add calls to overridden virtual functions, if there are any.
3547 //
3548 // FIXME: This isn't wonderful, because we don't know whether we're actually
3549 // in a context that permits expressions. This is a general issue with
3550 // qualified-id completions.
3551 if (!EnteringContext)
3552 MaybeAddOverrideCalls(*this, Ctx, Results);
3553 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003554
Douglas Gregorf6961522010-08-27 21:18:54 +00003555 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3556 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3557
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003558 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorf6961522010-08-27 21:18:54 +00003559 CodeCompletionContext::CCC_Name,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003560 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003561}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003562
3563void Sema::CodeCompleteUsing(Scope *S) {
3564 if (!CodeCompleter)
3565 return;
3566
Douglas Gregor218937c2011-02-01 19:23:04 +00003567 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003568 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3569 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003570 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003571
3572 // If we aren't in class scope, we could see the "namespace" keyword.
3573 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00003574 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003575
3576 // After "using", we can see anything that would start a
3577 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003578 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003579 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3580 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003581 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003582
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003583 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003584 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003585 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003586}
3587
3588void Sema::CodeCompleteUsingDirective(Scope *S) {
3589 if (!CodeCompleter)
3590 return;
3591
Douglas Gregor86d9a522009-09-21 16:56:56 +00003592 // After "using namespace", we expect to see a namespace name or namespace
3593 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003594 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3595 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003596 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003597 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003598 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003599 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3600 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003601 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003602 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003603 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003604 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003605}
3606
3607void Sema::CodeCompleteNamespaceDecl(Scope *S) {
3608 if (!CodeCompleter)
3609 return;
3610
Douglas Gregor86d9a522009-09-21 16:56:56 +00003611 DeclContext *Ctx = (DeclContext *)S->getEntity();
3612 if (!S->getParent())
3613 Ctx = Context.getTranslationUnitDecl();
3614
Douglas Gregor52779fb2010-09-23 23:01:17 +00003615 bool SuppressedGlobalResults
3616 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
3617
Douglas Gregor218937c2011-02-01 19:23:04 +00003618 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003619 SuppressedGlobalResults
3620 ? CodeCompletionContext::CCC_Namespace
3621 : CodeCompletionContext::CCC_Other,
3622 &ResultBuilder::IsNamespace);
3623
3624 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00003625 // We only want to see those namespaces that have already been defined
3626 // within this scope, because its likely that the user is creating an
3627 // extended namespace declaration. Keep track of the most recent
3628 // definition of each namespace.
3629 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
3630 for (DeclContext::specific_decl_iterator<NamespaceDecl>
3631 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
3632 NS != NSEnd; ++NS)
3633 OrigToLatest[NS->getOriginalNamespace()] = *NS;
3634
3635 // Add the most recent definition (or extended definition) of each
3636 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003637 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003638 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
3639 NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
3640 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00003641 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00003642 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003643 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003644 }
3645
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003646 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003647 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003648 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003649}
3650
3651void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
3652 if (!CodeCompleter)
3653 return;
3654
Douglas Gregor86d9a522009-09-21 16:56:56 +00003655 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003656 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3657 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003658 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003659 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003660 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3661 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003662 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003663 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003664 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003665}
3666
Douglas Gregored8d3222009-09-18 20:05:18 +00003667void Sema::CodeCompleteOperatorName(Scope *S) {
3668 if (!CodeCompleter)
3669 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003670
John McCall0a2c5e22010-08-25 06:19:51 +00003671 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003672 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3673 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003674 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003675 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00003676
Douglas Gregor86d9a522009-09-21 16:56:56 +00003677 // Add the names of overloadable operators.
3678#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
3679 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00003680 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003681#include "clang/Basic/OperatorKinds.def"
3682
3683 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00003684 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003685 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003686 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3687 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00003688
3689 // Add any type specifiers
Douglas Gregorbca403c2010-01-13 23:51:12 +00003690 AddTypeSpecifierResults(getLangOptions(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003691 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003692
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003693 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003694 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003695 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00003696}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003697
Douglas Gregor0133f522010-08-28 00:00:50 +00003698void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00003699 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00003700 unsigned NumInitializers) {
3701 CXXConstructorDecl *Constructor
3702 = static_cast<CXXConstructorDecl *>(ConstructorD);
3703 if (!Constructor)
3704 return;
3705
Douglas Gregor218937c2011-02-01 19:23:04 +00003706 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003707 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00003708 Results.EnterNewScope();
3709
3710 // Fill in any already-initialized fields or base classes.
3711 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
3712 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
3713 for (unsigned I = 0; I != NumInitializers; ++I) {
3714 if (Initializers[I]->isBaseInitializer())
3715 InitializedBases.insert(
3716 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
3717 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00003718 InitializedFields.insert(cast<FieldDecl>(
3719 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00003720 }
3721
3722 // Add completions for base classes.
Douglas Gregor218937c2011-02-01 19:23:04 +00003723 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor0c431c82010-08-29 19:27:27 +00003724 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00003725 CXXRecordDecl *ClassDecl = Constructor->getParent();
3726 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
3727 BaseEnd = ClassDecl->bases_end();
3728 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00003729 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
3730 SawLastInitializer
3731 = NumInitializers > 0 &&
3732 Initializers[NumInitializers - 1]->isBaseInitializer() &&
3733 Context.hasSameUnqualifiedType(Base->getType(),
3734 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00003735 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00003736 }
Douglas Gregor0133f522010-08-28 00:00:50 +00003737
Douglas Gregor218937c2011-02-01 19:23:04 +00003738 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00003739 Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003740 Base->getType().getAsString(Context.PrintingPolicy)));
3741 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3742 Builder.AddPlaceholderChunk("args");
3743 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3744 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00003745 SawLastInitializer? CCP_NextInitializer
3746 : CCP_MemberDeclaration));
3747 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00003748 }
3749
3750 // Add completions for virtual base classes.
3751 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
3752 BaseEnd = ClassDecl->vbases_end();
3753 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00003754 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
3755 SawLastInitializer
3756 = NumInitializers > 0 &&
3757 Initializers[NumInitializers - 1]->isBaseInitializer() &&
3758 Context.hasSameUnqualifiedType(Base->getType(),
3759 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00003760 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00003761 }
Douglas Gregor0133f522010-08-28 00:00:50 +00003762
Douglas Gregor218937c2011-02-01 19:23:04 +00003763 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00003764 Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003765 Base->getType().getAsString(Context.PrintingPolicy)));
3766 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3767 Builder.AddPlaceholderChunk("args");
3768 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3769 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00003770 SawLastInitializer? CCP_NextInitializer
3771 : CCP_MemberDeclaration));
3772 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00003773 }
3774
3775 // Add completions for members.
3776 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
3777 FieldEnd = ClassDecl->field_end();
3778 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00003779 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
3780 SawLastInitializer
3781 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00003782 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
3783 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00003784 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00003785 }
Douglas Gregor0133f522010-08-28 00:00:50 +00003786
3787 if (!Field->getDeclName())
3788 continue;
3789
Douglas Gregordae68752011-02-01 22:57:45 +00003790 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003791 Field->getIdentifier()->getName()));
3792 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3793 Builder.AddPlaceholderChunk("args");
3794 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3795 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00003796 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00003797 : CCP_MemberDeclaration,
3798 CXCursor_MemberRef));
Douglas Gregor0c431c82010-08-29 19:27:27 +00003799 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00003800 }
3801 Results.ExitScope();
3802
Douglas Gregor52779fb2010-09-23 23:01:17 +00003803 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00003804 Results.data(), Results.size());
3805}
3806
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003807// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
3808// true or false.
3809#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorbca403c2010-01-13 23:51:12 +00003810static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003811 ResultBuilder &Results,
3812 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003813 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003814 // Since we have an implementation, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00003815 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003816
Douglas Gregor218937c2011-02-01 19:23:04 +00003817 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003818 if (LangOpts.ObjC2) {
3819 // @dynamic
Douglas Gregor218937c2011-02-01 19:23:04 +00003820 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
3821 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3822 Builder.AddPlaceholderChunk("property");
3823 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003824
3825 // @synthesize
Douglas Gregor218937c2011-02-01 19:23:04 +00003826 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
3827 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3828 Builder.AddPlaceholderChunk("property");
3829 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003830 }
3831}
3832
Douglas Gregorbca403c2010-01-13 23:51:12 +00003833static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003834 ResultBuilder &Results,
3835 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003836 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003837
3838 // Since we have an interface or protocol, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00003839 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003840
3841 if (LangOpts.ObjC2) {
3842 // @property
Douglas Gregora4477812010-01-14 16:01:26 +00003843 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003844
3845 // @required
Douglas Gregora4477812010-01-14 16:01:26 +00003846 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003847
3848 // @optional
Douglas Gregora4477812010-01-14 16:01:26 +00003849 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003850 }
3851}
3852
Douglas Gregorbca403c2010-01-13 23:51:12 +00003853static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003854 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003855 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003856
3857 // @class name ;
Douglas Gregor218937c2011-02-01 19:23:04 +00003858 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
3859 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3860 Builder.AddPlaceholderChunk("name");
3861 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003862
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003863 if (Results.includeCodePatterns()) {
3864 // @interface name
3865 // FIXME: Could introduce the whole pattern, including superclasses and
3866 // such.
Douglas Gregor218937c2011-02-01 19:23:04 +00003867 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
3868 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3869 Builder.AddPlaceholderChunk("class");
3870 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003871
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003872 // @protocol name
Douglas Gregor218937c2011-02-01 19:23:04 +00003873 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
3874 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3875 Builder.AddPlaceholderChunk("protocol");
3876 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003877
3878 // @implementation name
Douglas Gregor218937c2011-02-01 19:23:04 +00003879 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
3880 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3881 Builder.AddPlaceholderChunk("class");
3882 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003883 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003884
3885 // @compatibility_alias name
Douglas Gregor218937c2011-02-01 19:23:04 +00003886 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
3887 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3888 Builder.AddPlaceholderChunk("alias");
3889 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3890 Builder.AddPlaceholderChunk("class");
3891 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003892}
3893
John McCalld226f652010-08-21 09:40:31 +00003894void Sema::CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl,
Douglas Gregorc464ae82009-12-07 09:27:33 +00003895 bool InInterface) {
John McCall0a2c5e22010-08-25 06:19:51 +00003896 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003897 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3898 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00003899 Results.EnterNewScope();
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003900 if (ObjCImpDecl)
Douglas Gregorbca403c2010-01-13 23:51:12 +00003901 AddObjCImplementationResults(getLangOptions(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003902 else if (InInterface)
Douglas Gregorbca403c2010-01-13 23:51:12 +00003903 AddObjCInterfaceResults(getLangOptions(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003904 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00003905 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00003906 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003907 HandleCodeCompleteResults(this, CodeCompleter,
3908 CodeCompletionContext::CCC_Other,
3909 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00003910}
3911
Douglas Gregorbca403c2010-01-13 23:51:12 +00003912static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003913 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003914 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003915
3916 // @encode ( type-name )
Douglas Gregor218937c2011-02-01 19:23:04 +00003917 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
3918 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3919 Builder.AddPlaceholderChunk("type-name");
3920 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3921 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003922
3923 // @protocol ( protocol-name )
Douglas Gregor218937c2011-02-01 19:23:04 +00003924 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
3925 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3926 Builder.AddPlaceholderChunk("protocol-name");
3927 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3928 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003929
3930 // @selector ( selector )
Douglas Gregor218937c2011-02-01 19:23:04 +00003931 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
3932 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3933 Builder.AddPlaceholderChunk("selector");
3934 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3935 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003936}
3937
Douglas Gregorbca403c2010-01-13 23:51:12 +00003938static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003939 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003940 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003941
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003942 if (Results.includeCodePatterns()) {
3943 // @try { statements } @catch ( declaration ) { statements } @finally
3944 // { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00003945 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
3946 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3947 Builder.AddPlaceholderChunk("statements");
3948 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3949 Builder.AddTextChunk("@catch");
3950 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3951 Builder.AddPlaceholderChunk("parameter");
3952 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3953 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3954 Builder.AddPlaceholderChunk("statements");
3955 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3956 Builder.AddTextChunk("@finally");
3957 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3958 Builder.AddPlaceholderChunk("statements");
3959 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3960 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003961 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003962
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003963 // @throw
Douglas Gregor218937c2011-02-01 19:23:04 +00003964 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
3965 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3966 Builder.AddPlaceholderChunk("expression");
3967 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003968
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003969 if (Results.includeCodePatterns()) {
3970 // @synchronized ( expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00003971 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
3972 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3973 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3974 Builder.AddPlaceholderChunk("expression");
3975 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3976 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3977 Builder.AddPlaceholderChunk("statements");
3978 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3979 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003980 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003981}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003982
Douglas Gregorbca403c2010-01-13 23:51:12 +00003983static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003984 ResultBuilder &Results,
3985 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003986 typedef CodeCompletionResult Result;
Douglas Gregora4477812010-01-14 16:01:26 +00003987 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
3988 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
3989 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003990 if (LangOpts.ObjC2)
Douglas Gregora4477812010-01-14 16:01:26 +00003991 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003992}
3993
3994void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003995 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3996 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003997 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00003998 AddObjCVisibilityResults(getLangOptions(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003999 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004000 HandleCodeCompleteResults(this, CodeCompleter,
4001 CodeCompletionContext::CCC_Other,
4002 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004003}
4004
4005void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004006 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4007 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004008 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004009 AddObjCStatementResults(Results, false);
4010 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004011 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004012 HandleCodeCompleteResults(this, CodeCompleter,
4013 CodeCompletionContext::CCC_Other,
4014 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004015}
4016
4017void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004018 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4019 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004020 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004021 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004022 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004023 HandleCodeCompleteResults(this, CodeCompleter,
4024 CodeCompletionContext::CCC_Other,
4025 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004026}
4027
Douglas Gregor988358f2009-11-19 00:14:45 +00004028/// \brief Determine whether the addition of the given flag to an Objective-C
4029/// property's attributes will cause a conflict.
4030static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4031 // Check if we've already added this flag.
4032 if (Attributes & NewFlag)
4033 return true;
4034
4035 Attributes |= NewFlag;
4036
4037 // Check for collisions with "readonly".
4038 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4039 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4040 ObjCDeclSpec::DQ_PR_assign |
4041 ObjCDeclSpec::DQ_PR_copy |
4042 ObjCDeclSpec::DQ_PR_retain)))
4043 return true;
4044
4045 // Check for more than one of { assign, copy, retain }.
4046 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
4047 ObjCDeclSpec::DQ_PR_copy |
4048 ObjCDeclSpec::DQ_PR_retain);
4049 if (AssignCopyRetMask &&
4050 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
4051 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
4052 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain)
4053 return true;
4054
4055 return false;
4056}
4057
Douglas Gregora93b1082009-11-18 23:08:07 +00004058void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004059 if (!CodeCompleter)
4060 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004061
Steve Naroffece8e712009-10-08 21:55:05 +00004062 unsigned Attributes = ODS.getPropertyAttributes();
4063
John McCall0a2c5e22010-08-25 06:19:51 +00004064 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004065 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4066 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004067 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004068 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004069 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004070 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004071 Results.AddResult(CodeCompletionResult("assign"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004072 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004073 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004074 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004075 Results.AddResult(CodeCompletionResult("retain"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004076 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004077 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004078 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004079 Results.AddResult(CodeCompletionResult("nonatomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004080 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004081 CodeCompletionBuilder Setter(Results.getAllocator());
4082 Setter.AddTypedTextChunk("setter");
4083 Setter.AddTextChunk(" = ");
4084 Setter.AddPlaceholderChunk("method");
4085 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004086 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004087 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004088 CodeCompletionBuilder Getter(Results.getAllocator());
4089 Getter.AddTypedTextChunk("getter");
4090 Getter.AddTextChunk(" = ");
4091 Getter.AddPlaceholderChunk("method");
4092 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004093 }
Steve Naroffece8e712009-10-08 21:55:05 +00004094 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004095 HandleCodeCompleteResults(this, CodeCompleter,
4096 CodeCompletionContext::CCC_Other,
4097 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004098}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004099
Douglas Gregor4ad96852009-11-19 07:41:15 +00004100/// \brief Descripts the kind of Objective-C method that we want to find
4101/// via code completion.
4102enum ObjCMethodKind {
4103 MK_Any, //< Any kind of method, provided it means other specified criteria.
4104 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4105 MK_OneArgSelector //< One-argument selector.
4106};
4107
Douglas Gregor458433d2010-08-26 15:07:07 +00004108static bool isAcceptableObjCSelector(Selector Sel,
4109 ObjCMethodKind WantKind,
4110 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004111 unsigned NumSelIdents,
4112 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004113 if (NumSelIdents > Sel.getNumArgs())
4114 return false;
4115
4116 switch (WantKind) {
4117 case MK_Any: break;
4118 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4119 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4120 }
4121
Douglas Gregorcf544262010-11-17 21:36:08 +00004122 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4123 return false;
4124
Douglas Gregor458433d2010-08-26 15:07:07 +00004125 for (unsigned I = 0; I != NumSelIdents; ++I)
4126 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4127 return false;
4128
4129 return true;
4130}
4131
Douglas Gregor4ad96852009-11-19 07:41:15 +00004132static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4133 ObjCMethodKind WantKind,
4134 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004135 unsigned NumSelIdents,
4136 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004137 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004138 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004139}
Douglas Gregord36adf52010-09-16 16:06:31 +00004140
4141namespace {
4142 /// \brief A set of selectors, which is used to avoid introducing multiple
4143 /// completions with the same selector into the result set.
4144 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4145}
4146
Douglas Gregor36ecb042009-11-17 23:22:23 +00004147/// \brief Add all of the Objective-C methods in the given Objective-C
4148/// container to the set of results.
4149///
4150/// The container will be a class, protocol, category, or implementation of
4151/// any of the above. This mether will recurse to include methods from
4152/// the superclasses of classes along with their categories, protocols, and
4153/// implementations.
4154///
4155/// \param Container the container in which we'll look to find methods.
4156///
4157/// \param WantInstance whether to add instance methods (only); if false, this
4158/// routine will add factory methods (only).
4159///
4160/// \param CurContext the context in which we're performing the lookup that
4161/// finds methods.
4162///
Douglas Gregorcf544262010-11-17 21:36:08 +00004163/// \param AllowSameLength Whether we allow a method to be added to the list
4164/// when it has the same number of parameters as we have selector identifiers.
4165///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004166/// \param Results the structure into which we'll add results.
4167static void AddObjCMethods(ObjCContainerDecl *Container,
4168 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004169 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004170 IdentifierInfo **SelIdents,
4171 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004172 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004173 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004174 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004175 ResultBuilder &Results,
4176 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004177 typedef CodeCompletionResult Result;
Douglas Gregor36ecb042009-11-17 23:22:23 +00004178 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4179 MEnd = Container->meth_end();
4180 M != MEnd; ++M) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004181 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4182 // Check whether the selector identifiers we've been given are a
4183 // subset of the identifiers for this particular method.
Douglas Gregorcf544262010-11-17 21:36:08 +00004184 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4185 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004186 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004187
Douglas Gregord36adf52010-09-16 16:06:31 +00004188 if (!Selectors.insert((*M)->getSelector()))
4189 continue;
4190
Douglas Gregord3c68542009-11-19 01:08:35 +00004191 Result R = Result(*M, 0);
4192 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004193 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004194 if (!InOriginalClass)
4195 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004196 Results.MaybeAddResult(R, CurContext);
4197 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004198 }
4199
Douglas Gregore396c7b2010-09-16 15:34:59 +00004200 // Visit the protocols of protocols.
4201 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
4202 const ObjCList<ObjCProtocolDecl> &Protocols
4203 = Protocol->getReferencedProtocols();
4204 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4205 E = Protocols.end();
4206 I != E; ++I)
4207 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004208 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregore396c7b2010-09-16 15:34:59 +00004209 }
4210
Douglas Gregor36ecb042009-11-17 23:22:23 +00004211 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
4212 if (!IFace)
4213 return;
4214
4215 // Add methods in protocols.
4216 const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols();
4217 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4218 E = Protocols.end();
4219 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004220 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004221 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004222
4223 // Add methods in categories.
4224 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4225 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004226 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004227 NumSelIdents, CurContext, Selectors, AllowSameLength,
4228 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004229
4230 // Add a categories protocol methods.
4231 const ObjCList<ObjCProtocolDecl> &Protocols
4232 = CatDecl->getReferencedProtocols();
4233 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4234 E = Protocols.end();
4235 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004236 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004237 NumSelIdents, CurContext, Selectors, AllowSameLength,
4238 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004239
4240 // Add methods in category implementations.
4241 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004242 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004243 NumSelIdents, CurContext, Selectors, AllowSameLength,
4244 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004245 }
4246
4247 // Add methods in superclass.
4248 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004249 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004250 SelIdents, NumSelIdents, CurContext, Selectors,
4251 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004252
4253 // Add methods in our implementation, if any.
4254 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004255 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004256 NumSelIdents, CurContext, Selectors, AllowSameLength,
4257 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004258}
4259
4260
Douglas Gregorbdb2d502010-12-21 17:34:17 +00004261void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00004262 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004263
4264 // Try to find the interface where getters might live.
John McCalld226f652010-08-21 09:40:31 +00004265 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(ClassDecl);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004266 if (!Class) {
4267 if (ObjCCategoryDecl *Category
John McCalld226f652010-08-21 09:40:31 +00004268 = dyn_cast_or_null<ObjCCategoryDecl>(ClassDecl))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004269 Class = Category->getClassInterface();
4270
4271 if (!Class)
4272 return;
4273 }
4274
4275 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004276 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4277 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004278 Results.EnterNewScope();
4279
Douglas Gregord36adf52010-09-16 16:06:31 +00004280 VisitedSelectorSet Selectors;
4281 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004282 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004283 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004284 HandleCodeCompleteResults(this, CodeCompleter,
4285 CodeCompletionContext::CCC_Other,
4286 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004287}
4288
Douglas Gregorbdb2d502010-12-21 17:34:17 +00004289void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00004290 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004291
4292 // Try to find the interface where setters might live.
4293 ObjCInterfaceDecl *Class
John McCalld226f652010-08-21 09:40:31 +00004294 = dyn_cast_or_null<ObjCInterfaceDecl>(ObjCImplDecl);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004295 if (!Class) {
4296 if (ObjCCategoryDecl *Category
John McCalld226f652010-08-21 09:40:31 +00004297 = dyn_cast_or_null<ObjCCategoryDecl>(ObjCImplDecl))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004298 Class = Category->getClassInterface();
4299
4300 if (!Class)
4301 return;
4302 }
4303
4304 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004305 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4306 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004307 Results.EnterNewScope();
4308
Douglas Gregord36adf52010-09-16 16:06:31 +00004309 VisitedSelectorSet Selectors;
4310 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004311 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004312
4313 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004314 HandleCodeCompleteResults(this, CodeCompleter,
4315 CodeCompletionContext::CCC_Other,
4316 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004317}
4318
Douglas Gregorafc45782011-02-15 22:19:42 +00004319void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4320 bool IsParameter) {
John McCall0a2c5e22010-08-25 06:19:51 +00004321 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004322 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4323 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004324 Results.EnterNewScope();
4325
4326 // Add context-sensitive, Objective-C parameter-passing keywords.
4327 bool AddedInOut = false;
4328 if ((DS.getObjCDeclQualifier() &
4329 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4330 Results.AddResult("in");
4331 Results.AddResult("inout");
4332 AddedInOut = true;
4333 }
4334 if ((DS.getObjCDeclQualifier() &
4335 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4336 Results.AddResult("out");
4337 if (!AddedInOut)
4338 Results.AddResult("inout");
4339 }
4340 if ((DS.getObjCDeclQualifier() &
4341 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4342 ObjCDeclSpec::DQ_Oneway)) == 0) {
4343 Results.AddResult("bycopy");
4344 Results.AddResult("byref");
4345 Results.AddResult("oneway");
4346 }
4347
Douglas Gregorafc45782011-02-15 22:19:42 +00004348 // If we're completing the return type of an Objective-C method and the
4349 // identifier IBAction refers to a macro, provide a completion item for
4350 // an action, e.g.,
4351 // IBAction)<#selector#>:(id)sender
4352 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4353 Context.Idents.get("IBAction").hasMacroDefinition()) {
4354 typedef CodeCompletionString::Chunk Chunk;
4355 CodeCompletionBuilder Builder(Results.getAllocator(), CCP_CodePattern,
4356 CXAvailability_Available);
4357 Builder.AddTypedTextChunk("IBAction");
4358 Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
4359 Builder.AddPlaceholderChunk("selector");
4360 Builder.AddChunk(Chunk(CodeCompletionString::CK_Colon));
4361 Builder.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
4362 Builder.AddTextChunk("id");
4363 Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
4364 Builder.AddTextChunk("sender");
4365 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4366 }
4367
Douglas Gregord32b0222010-08-24 01:06:58 +00004368 // Add various builtin type names and specifiers.
4369 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4370 Results.ExitScope();
4371
4372 // Add the various type names
4373 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4374 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4375 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4376 CodeCompleter->includeGlobals());
4377
4378 if (CodeCompleter->includeMacros())
4379 AddMacroResults(PP, Results);
4380
4381 HandleCodeCompleteResults(this, CodeCompleter,
4382 CodeCompletionContext::CCC_Type,
4383 Results.data(), Results.size());
4384}
4385
Douglas Gregor22f56992010-04-06 19:22:33 +00004386/// \brief When we have an expression with type "id", we may assume
4387/// that it has some more-specific class type based on knowledge of
4388/// common uses of Objective-C. This routine returns that class type,
4389/// or NULL if no better result could be determined.
4390static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004391 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004392 if (!Msg)
4393 return 0;
4394
4395 Selector Sel = Msg->getSelector();
4396 if (Sel.isNull())
4397 return 0;
4398
4399 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4400 if (!Id)
4401 return 0;
4402
4403 ObjCMethodDecl *Method = Msg->getMethodDecl();
4404 if (!Method)
4405 return 0;
4406
4407 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004408 ObjCInterfaceDecl *IFace = 0;
4409 switch (Msg->getReceiverKind()) {
4410 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004411 if (const ObjCObjectType *ObjType
4412 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4413 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004414 break;
4415
4416 case ObjCMessageExpr::Instance: {
4417 QualType T = Msg->getInstanceReceiver()->getType();
4418 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4419 IFace = Ptr->getInterfaceDecl();
4420 break;
4421 }
4422
4423 case ObjCMessageExpr::SuperInstance:
4424 case ObjCMessageExpr::SuperClass:
4425 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00004426 }
4427
4428 if (!IFace)
4429 return 0;
4430
4431 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4432 if (Method->isInstanceMethod())
4433 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4434 .Case("retain", IFace)
4435 .Case("autorelease", IFace)
4436 .Case("copy", IFace)
4437 .Case("copyWithZone", IFace)
4438 .Case("mutableCopy", IFace)
4439 .Case("mutableCopyWithZone", IFace)
4440 .Case("awakeFromCoder", IFace)
4441 .Case("replacementObjectFromCoder", IFace)
4442 .Case("class", IFace)
4443 .Case("classForCoder", IFace)
4444 .Case("superclass", Super)
4445 .Default(0);
4446
4447 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4448 .Case("new", IFace)
4449 .Case("alloc", IFace)
4450 .Case("allocWithZone", IFace)
4451 .Case("class", IFace)
4452 .Case("superclass", Super)
4453 .Default(0);
4454}
4455
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004456// Add a special completion for a message send to "super", which fills in the
4457// most likely case of forwarding all of our arguments to the superclass
4458// function.
4459///
4460/// \param S The semantic analysis object.
4461///
4462/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4463/// the "super" keyword. Otherwise, we just need to provide the arguments.
4464///
4465/// \param SelIdents The identifiers in the selector that have already been
4466/// provided as arguments for a send to "super".
4467///
4468/// \param NumSelIdents The number of identifiers in \p SelIdents.
4469///
4470/// \param Results The set of results to augment.
4471///
4472/// \returns the Objective-C method declaration that would be invoked by
4473/// this "super" completion. If NULL, no completion was added.
4474static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4475 IdentifierInfo **SelIdents,
4476 unsigned NumSelIdents,
4477 ResultBuilder &Results) {
4478 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
4479 if (!CurMethod)
4480 return 0;
4481
4482 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
4483 if (!Class)
4484 return 0;
4485
4486 // Try to find a superclass method with the same selector.
4487 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00004488 while ((Class = Class->getSuperClass()) && !SuperMethod) {
4489 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004490 SuperMethod = Class->getMethod(CurMethod->getSelector(),
4491 CurMethod->isInstanceMethod());
4492
Douglas Gregor78bcd912011-02-16 00:51:18 +00004493 // Check in categories or class extensions.
4494 if (!SuperMethod) {
4495 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
4496 Category = Category->getNextClassCategory())
4497 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
4498 CurMethod->isInstanceMethod())))
4499 break;
4500 }
4501 }
4502
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004503 if (!SuperMethod)
4504 return 0;
4505
4506 // Check whether the superclass method has the same signature.
4507 if (CurMethod->param_size() != SuperMethod->param_size() ||
4508 CurMethod->isVariadic() != SuperMethod->isVariadic())
4509 return 0;
4510
4511 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
4512 CurPEnd = CurMethod->param_end(),
4513 SuperP = SuperMethod->param_begin();
4514 CurP != CurPEnd; ++CurP, ++SuperP) {
4515 // Make sure the parameter types are compatible.
4516 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
4517 (*SuperP)->getType()))
4518 return 0;
4519
4520 // Make sure we have a parameter name to forward!
4521 if (!(*CurP)->getIdentifier())
4522 return 0;
4523 }
4524
4525 // We have a superclass method. Now, form the send-to-super completion.
Douglas Gregor218937c2011-02-01 19:23:04 +00004526 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004527
4528 // Give this completion a return type.
Douglas Gregor218937c2011-02-01 19:23:04 +00004529 AddResultTypeChunk(S.Context, SuperMethod, Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004530
4531 // If we need the "super" keyword, add it (plus some spacing).
4532 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004533 Builder.AddTypedTextChunk("super");
4534 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004535 }
4536
4537 Selector Sel = CurMethod->getSelector();
4538 if (Sel.isUnarySelector()) {
4539 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00004540 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004541 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004542 else
Douglas Gregordae68752011-02-01 22:57:45 +00004543 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004544 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004545 } else {
4546 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
4547 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
4548 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004549 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004550
4551 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004552 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004553 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004554 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004555 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004556 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004557 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004558 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00004559 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004560 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004561 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00004562 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004563 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004564 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00004565 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004566 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004567 }
4568 }
4569 }
4570
Douglas Gregor218937c2011-02-01 19:23:04 +00004571 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004572 SuperMethod->isInstanceMethod()
4573 ? CXCursor_ObjCInstanceMethodDecl
4574 : CXCursor_ObjCClassMethodDecl));
4575 return SuperMethod;
4576}
4577
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004578void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004579 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004580 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4581 CodeCompletionContext::CCC_ObjCMessageReceiver,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004582 &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004583
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004584 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4585 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00004586 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4587 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004588
4589 // If we are in an Objective-C method inside a class that has a superclass,
4590 // add "super" as an option.
4591 if (ObjCMethodDecl *Method = getCurMethodDecl())
4592 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004593 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004594 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004595
4596 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
4597 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004598
4599 Results.ExitScope();
4600
4601 if (CodeCompleter->includeMacros())
4602 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00004603 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004604 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004605
4606}
4607
Douglas Gregor2725ca82010-04-21 19:57:20 +00004608void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
4609 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004610 unsigned NumSelIdents,
4611 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00004612 ObjCInterfaceDecl *CDecl = 0;
4613 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
4614 // Figure out which interface we're in.
4615 CDecl = CurMethod->getClassInterface();
4616 if (!CDecl)
4617 return;
4618
4619 // Find the superclass of this class.
4620 CDecl = CDecl->getSuperClass();
4621 if (!CDecl)
4622 return;
4623
4624 if (CurMethod->isInstanceMethod()) {
4625 // We are inside an instance method, which means that the message
4626 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004627 // current object.
4628 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004629 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004630 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004631 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004632 }
4633
4634 // Fall through to send to the superclass in CDecl.
4635 } else {
4636 // "super" may be the name of a type or variable. Figure out which
4637 // it is.
4638 IdentifierInfo *Super = &Context.Idents.get("super");
4639 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
4640 LookupOrdinaryName);
4641 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
4642 // "super" names an interface. Use it.
4643 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00004644 if (const ObjCObjectType *Iface
4645 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
4646 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00004647 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
4648 // "super" names an unresolved type; we can't be more specific.
4649 } else {
4650 // Assume that "super" names some kind of value and parse that way.
4651 CXXScopeSpec SS;
4652 UnqualifiedId id;
4653 id.setIdentifier(Super, SuperLoc);
John McCall60d7b3a2010-08-24 06:29:42 +00004654 ExprResult SuperExpr = ActOnIdExpression(S, SS, id, false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004655 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004656 SelIdents, NumSelIdents,
4657 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004658 }
4659
4660 // Fall through
4661 }
4662
John McCallb3d87482010-08-24 05:47:05 +00004663 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00004664 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00004665 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00004666 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004667 NumSelIdents, AtArgumentExpression,
4668 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004669}
4670
Douglas Gregorb9d77572010-09-21 00:03:25 +00004671/// \brief Given a set of code-completion results for the argument of a message
4672/// send, determine the preferred type (if any) for that argument expression.
4673static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
4674 unsigned NumSelIdents) {
4675 typedef CodeCompletionResult Result;
4676 ASTContext &Context = Results.getSema().Context;
4677
4678 QualType PreferredType;
4679 unsigned BestPriority = CCP_Unlikely * 2;
4680 Result *ResultsData = Results.data();
4681 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
4682 Result &R = ResultsData[I];
4683 if (R.Kind == Result::RK_Declaration &&
4684 isa<ObjCMethodDecl>(R.Declaration)) {
4685 if (R.Priority <= BestPriority) {
4686 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
4687 if (NumSelIdents <= Method->param_size()) {
4688 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
4689 ->getType();
4690 if (R.Priority < BestPriority || PreferredType.isNull()) {
4691 BestPriority = R.Priority;
4692 PreferredType = MyPreferredType;
4693 } else if (!Context.hasSameUnqualifiedType(PreferredType,
4694 MyPreferredType)) {
4695 PreferredType = QualType();
4696 }
4697 }
4698 }
4699 }
4700 }
4701
4702 return PreferredType;
4703}
4704
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004705static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
4706 ParsedType Receiver,
4707 IdentifierInfo **SelIdents,
4708 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004709 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004710 bool IsSuper,
4711 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00004712 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00004713 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004714
Douglas Gregor24a069f2009-11-17 17:59:40 +00004715 // If the given name refers to an interface type, retrieve the
4716 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00004717 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004718 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004719 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00004720 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
4721 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00004722 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004723
Douglas Gregor36ecb042009-11-17 23:22:23 +00004724 // Add all of the factory methods in this Objective-C class, its protocols,
4725 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00004726 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004727
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004728 // If this is a send-to-super, try to add the special "super" send
4729 // completion.
4730 if (IsSuper) {
4731 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004732 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
4733 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004734 Results.Ignore(SuperMethod);
4735 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004736
Douglas Gregor265f7492010-08-27 15:29:55 +00004737 // If we're inside an Objective-C method definition, prefer its selector to
4738 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004739 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00004740 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004741
Douglas Gregord36adf52010-09-16 16:06:31 +00004742 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00004743 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004744 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004745 SemaRef.CurContext, Selectors, AtArgumentExpression,
4746 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004747 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00004748 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004749
Douglas Gregor719770d2010-04-06 17:30:22 +00004750 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00004751 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004752 if (SemaRef.ExternalSource) {
4753 for (uint32_t I = 0,
4754 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00004755 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004756 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
4757 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00004758 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004759
4760 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00004761 }
4762 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004763
4764 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
4765 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00004766 M != MEnd; ++M) {
4767 for (ObjCMethodList *MethList = &M->second.second;
4768 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00004769 MethList = MethList->Next) {
4770 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
4771 NumSelIdents))
4772 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004773
Douglas Gregor13438f92010-04-06 16:40:00 +00004774 Result R(MethList->Method, 0);
4775 R.StartParameter = NumSelIdents;
4776 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004777 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00004778 }
4779 }
4780 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004781
4782 Results.ExitScope();
4783}
Douglas Gregor13438f92010-04-06 16:40:00 +00004784
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004785void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
4786 IdentifierInfo **SelIdents,
4787 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004788 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004789 bool IsSuper) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004790 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4791 CodeCompletionContext::CCC_Other);
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004792 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
4793 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00004794
4795 // If we're actually at the argument expression (rather than prior to the
4796 // selector), we're actually performing code completion for an expression.
4797 // Determine whether we have a single, best method. If so, we can
4798 // code-complete the expression using the corresponding parameter type as
4799 // our preferred type, improving completion results.
4800 if (AtArgumentExpression) {
4801 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
4802 NumSelIdents);
4803 if (PreferredType.isNull())
4804 CodeCompleteOrdinaryName(S, PCC_Expression);
4805 else
4806 CodeCompleteExpression(S, PreferredType);
4807 return;
4808 }
4809
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004810 HandleCodeCompleteResults(this, CodeCompleter,
4811 CodeCompletionContext::CCC_Other,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004812 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00004813}
4814
Douglas Gregord3c68542009-11-19 01:08:35 +00004815void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
4816 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004817 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004818 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004819 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00004820 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00004821
4822 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00004823
Douglas Gregor36ecb042009-11-17 23:22:23 +00004824 // If necessary, apply function/array conversion to the receiver.
4825 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00004826 if (RecExpr) {
4827 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
4828 if (Conv.isInvalid()) // conversion failed. bail.
4829 return;
4830 RecExpr = Conv.take();
4831 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004832 QualType ReceiverType = RecExpr? RecExpr->getType()
4833 : Super? Context.getObjCObjectPointerType(
4834 Context.getObjCInterfaceType(Super))
4835 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00004836
Douglas Gregorda892642010-11-08 21:12:30 +00004837 // If we're messaging an expression with type "id" or "Class", check
4838 // whether we know something special about the receiver that allows
4839 // us to assume a more-specific receiver type.
4840 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
4841 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
4842 if (ReceiverType->isObjCClassType())
4843 return CodeCompleteObjCClassMessage(S,
4844 ParsedType::make(Context.getObjCInterfaceType(IFace)),
4845 SelIdents, NumSelIdents,
4846 AtArgumentExpression, Super);
4847
4848 ReceiverType = Context.getObjCObjectPointerType(
4849 Context.getObjCInterfaceType(IFace));
4850 }
4851
Douglas Gregor36ecb042009-11-17 23:22:23 +00004852 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00004853 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4854 CodeCompletionContext::CCC_Other);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004855 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00004856
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004857 // If this is a send-to-super, try to add the special "super" send
4858 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004859 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004860 if (ObjCMethodDecl *SuperMethod
4861 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
4862 Results))
4863 Results.Ignore(SuperMethod);
4864 }
4865
Douglas Gregor265f7492010-08-27 15:29:55 +00004866 // If we're inside an Objective-C method definition, prefer its selector to
4867 // others.
4868 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
4869 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004870
Douglas Gregord36adf52010-09-16 16:06:31 +00004871 // Keep track of the selectors we've already added.
4872 VisitedSelectorSet Selectors;
4873
Douglas Gregorf74a4192009-11-18 00:06:18 +00004874 // Handle messages to Class. This really isn't a message to an instance
4875 // method, so we treat it the same way we would treat a message send to a
4876 // class method.
4877 if (ReceiverType->isObjCClassType() ||
4878 ReceiverType->isObjCQualifiedClassType()) {
4879 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
4880 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004881 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004882 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004883 }
4884 }
4885 // Handle messages to a qualified ID ("id<foo>").
4886 else if (const ObjCObjectPointerType *QualID
4887 = ReceiverType->getAsObjCQualifiedIdType()) {
4888 // Search protocols for instance methods.
4889 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
4890 E = QualID->qual_end();
4891 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004892 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004893 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004894 }
4895 // Handle messages to a pointer to interface type.
4896 else if (const ObjCObjectPointerType *IFacePtr
4897 = ReceiverType->getAsObjCInterfacePointerType()) {
4898 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004899 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004900 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
4901 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004902
4903 // Search protocols for instance methods.
4904 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
4905 E = IFacePtr->qual_end();
4906 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004907 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004908 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004909 }
Douglas Gregor13438f92010-04-06 16:40:00 +00004910 // Handle messages to "id".
4911 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00004912 // We're messaging "id", so provide all instance methods we know
4913 // about as code-completion results.
4914
4915 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00004916 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00004917 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00004918 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
4919 I != N; ++I) {
4920 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00004921 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00004922 continue;
4923
Sebastian Redldb9d2142010-08-02 23:18:59 +00004924 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00004925 }
4926 }
4927
Sebastian Redldb9d2142010-08-02 23:18:59 +00004928 for (GlobalMethodPool::iterator M = MethodPool.begin(),
4929 MEnd = MethodPool.end();
4930 M != MEnd; ++M) {
4931 for (ObjCMethodList *MethList = &M->second.first;
4932 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00004933 MethList = MethList->Next) {
4934 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
4935 NumSelIdents))
4936 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00004937
4938 if (!Selectors.insert(MethList->Method->getSelector()))
4939 continue;
4940
Douglas Gregor13438f92010-04-06 16:40:00 +00004941 Result R(MethList->Method, 0);
4942 R.StartParameter = NumSelIdents;
4943 R.AllParametersAreInformative = false;
4944 Results.MaybeAddResult(R, CurContext);
4945 }
4946 }
4947 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00004948 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00004949
4950
4951 // If we're actually at the argument expression (rather than prior to the
4952 // selector), we're actually performing code completion for an expression.
4953 // Determine whether we have a single, best method. If so, we can
4954 // code-complete the expression using the corresponding parameter type as
4955 // our preferred type, improving completion results.
4956 if (AtArgumentExpression) {
4957 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
4958 NumSelIdents);
4959 if (PreferredType.isNull())
4960 CodeCompleteOrdinaryName(S, PCC_Expression);
4961 else
4962 CodeCompleteExpression(S, PreferredType);
4963 return;
4964 }
4965
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004966 HandleCodeCompleteResults(this, CodeCompleter,
4967 CodeCompletionContext::CCC_Other,
4968 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00004969}
Douglas Gregor55385fe2009-11-18 04:19:12 +00004970
Douglas Gregorfb629412010-08-23 21:17:50 +00004971void Sema::CodeCompleteObjCForCollection(Scope *S,
4972 DeclGroupPtrTy IterationVar) {
4973 CodeCompleteExpressionData Data;
4974 Data.ObjCCollection = true;
4975
4976 if (IterationVar.getAsOpaquePtr()) {
4977 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
4978 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
4979 if (*I)
4980 Data.IgnoreDecls.push_back(*I);
4981 }
4982 }
4983
4984 CodeCompleteExpression(S, Data);
4985}
4986
Douglas Gregor458433d2010-08-26 15:07:07 +00004987void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
4988 unsigned NumSelIdents) {
4989 // If we have an external source, load the entire class method
4990 // pool from the AST file.
4991 if (ExternalSource) {
4992 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
4993 I != N; ++I) {
4994 Selector Sel = ExternalSource->GetExternalSelector(I);
4995 if (Sel.isNull() || MethodPool.count(Sel))
4996 continue;
4997
4998 ReadMethodPool(Sel);
4999 }
5000 }
5001
Douglas Gregor218937c2011-02-01 19:23:04 +00005002 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5003 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005004 Results.EnterNewScope();
5005 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5006 MEnd = MethodPool.end();
5007 M != MEnd; ++M) {
5008
5009 Selector Sel = M->first;
5010 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5011 continue;
5012
Douglas Gregor218937c2011-02-01 19:23:04 +00005013 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor458433d2010-08-26 15:07:07 +00005014 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005015 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005016 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005017 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005018 continue;
5019 }
5020
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005021 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005022 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005023 if (I == NumSelIdents) {
5024 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005025 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005026 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005027 Accumulator.clear();
5028 }
5029 }
5030
Douglas Gregor813d8342011-02-18 22:29:55 +00005031 Accumulator += Sel.getNameForSlot(I).str();
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005032 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005033 }
Douglas Gregordae68752011-02-01 22:57:45 +00005034 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005035 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005036 }
5037 Results.ExitScope();
5038
5039 HandleCodeCompleteResults(this, CodeCompleter,
5040 CodeCompletionContext::CCC_SelectorName,
5041 Results.data(), Results.size());
5042}
5043
Douglas Gregor55385fe2009-11-18 04:19:12 +00005044/// \brief Add all of the protocol declarations that we find in the given
5045/// (translation unit) context.
5046static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005047 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005048 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005049 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005050
5051 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5052 DEnd = Ctx->decls_end();
5053 D != DEnd; ++D) {
5054 // Record any protocols we find.
5055 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor083128f2009-11-18 04:49:41 +00005056 if (!OnlyForwardDeclarations || Proto->isForwardDecl())
Douglas Gregor608300b2010-01-14 16:14:35 +00005057 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005058
5059 // Record any forward-declared protocols we find.
5060 if (ObjCForwardProtocolDecl *Forward
5061 = dyn_cast<ObjCForwardProtocolDecl>(*D)) {
5062 for (ObjCForwardProtocolDecl::protocol_iterator
5063 P = Forward->protocol_begin(),
5064 PEnd = Forward->protocol_end();
5065 P != PEnd; ++P)
Douglas Gregor083128f2009-11-18 04:49:41 +00005066 if (!OnlyForwardDeclarations || (*P)->isForwardDecl())
Douglas Gregor608300b2010-01-14 16:14:35 +00005067 Results.AddResult(Result(*P, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005068 }
5069 }
5070}
5071
5072void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5073 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005074 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5075 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005076
Douglas Gregor70c23352010-12-09 21:44:02 +00005077 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5078 Results.EnterNewScope();
5079
5080 // Tell the result set to ignore all of the protocols we have
5081 // already seen.
5082 // FIXME: This doesn't work when caching code-completion results.
5083 for (unsigned I = 0; I != NumProtocols; ++I)
5084 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5085 Protocols[I].second))
5086 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005087
Douglas Gregor70c23352010-12-09 21:44:02 +00005088 // Add all protocols.
5089 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5090 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005091
Douglas Gregor70c23352010-12-09 21:44:02 +00005092 Results.ExitScope();
5093 }
5094
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005095 HandleCodeCompleteResults(this, CodeCompleter,
5096 CodeCompletionContext::CCC_ObjCProtocolName,
5097 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005098}
5099
5100void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005101 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5102 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005103
Douglas Gregor70c23352010-12-09 21:44:02 +00005104 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5105 Results.EnterNewScope();
5106
5107 // Add all protocols.
5108 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5109 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005110
Douglas Gregor70c23352010-12-09 21:44:02 +00005111 Results.ExitScope();
5112 }
5113
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005114 HandleCodeCompleteResults(this, CodeCompleter,
5115 CodeCompletionContext::CCC_ObjCProtocolName,
5116 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005117}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005118
5119/// \brief Add all of the Objective-C interface declarations that we find in
5120/// the given (translation unit) context.
5121static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5122 bool OnlyForwardDeclarations,
5123 bool OnlyUnimplemented,
5124 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005125 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005126
5127 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5128 DEnd = Ctx->decls_end();
5129 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005130 // Record any interfaces we find.
5131 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
5132 if ((!OnlyForwardDeclarations || Class->isForwardDecl()) &&
5133 (!OnlyUnimplemented || !Class->getImplementation()))
5134 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005135
5136 // Record any forward-declared interfaces we find.
5137 if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
5138 for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end();
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005139 C != CEnd; ++C)
5140 if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) &&
5141 (!OnlyUnimplemented || !C->getInterface()->getImplementation()))
5142 Results.AddResult(Result(C->getInterface(), 0), CurContext,
Douglas Gregor608300b2010-01-14 16:14:35 +00005143 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005144 }
5145 }
5146}
5147
5148void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005149 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5150 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005151 Results.EnterNewScope();
5152
5153 // Add all classes.
5154 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, true,
5155 false, Results);
5156
5157 Results.ExitScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00005158 // FIXME: Add a special context for this, use cached global completion
5159 // results.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005160 HandleCodeCompleteResults(this, CodeCompleter,
5161 CodeCompletionContext::CCC_Other,
5162 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005163}
5164
Douglas Gregorc83c6872010-04-15 22:33:43 +00005165void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5166 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005167 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5168 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005169 Results.EnterNewScope();
5170
5171 // Make sure that we ignore the class we're currently defining.
5172 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005173 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005174 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005175 Results.Ignore(CurClass);
5176
5177 // Add all classes.
5178 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5179 false, Results);
5180
5181 Results.ExitScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00005182 // FIXME: Add a special context for this, use cached global completion
5183 // results.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005184 HandleCodeCompleteResults(this, CodeCompleter,
5185 CodeCompletionContext::CCC_Other,
5186 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005187}
5188
5189void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005190 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5191 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005192 Results.EnterNewScope();
5193
5194 // Add all unimplemented classes.
5195 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5196 true, Results);
5197
5198 Results.ExitScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00005199 // FIXME: Add a special context for this, use cached global completion
5200 // results.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005201 HandleCodeCompleteResults(this, CodeCompleter,
5202 CodeCompletionContext::CCC_Other,
5203 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005204}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005205
5206void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005207 IdentifierInfo *ClassName,
5208 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005209 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005210
Douglas Gregor218937c2011-02-01 19:23:04 +00005211 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5212 CodeCompletionContext::CCC_Other);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005213
5214 // Ignore any categories we find that have already been implemented by this
5215 // interface.
5216 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5217 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005218 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005219 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5220 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5221 Category = Category->getNextClassCategory())
5222 CategoryNames.insert(Category->getIdentifier());
5223
5224 // Add all of the categories we know about.
5225 Results.EnterNewScope();
5226 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5227 for (DeclContext::decl_iterator D = TU->decls_begin(),
5228 DEnd = TU->decls_end();
5229 D != DEnd; ++D)
5230 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5231 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005232 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005233 Results.ExitScope();
5234
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005235 HandleCodeCompleteResults(this, CodeCompleter,
5236 CodeCompletionContext::CCC_Other,
5237 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005238}
5239
5240void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005241 IdentifierInfo *ClassName,
5242 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005243 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005244
5245 // Find the corresponding interface. If we couldn't find the interface, the
5246 // program itself is ill-formed. However, we'll try to be helpful still by
5247 // providing the list of all of the categories we know about.
5248 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005249 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005250 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5251 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005252 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005253
Douglas Gregor218937c2011-02-01 19:23:04 +00005254 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5255 CodeCompletionContext::CCC_Other);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005256
5257 // Add all of the categories that have have corresponding interface
5258 // declarations in this class and any of its superclasses, except for
5259 // already-implemented categories in the class itself.
5260 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5261 Results.EnterNewScope();
5262 bool IgnoreImplemented = true;
5263 while (Class) {
5264 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5265 Category = Category->getNextClassCategory())
5266 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5267 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005268 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005269
5270 Class = Class->getSuperClass();
5271 IgnoreImplemented = false;
5272 }
5273 Results.ExitScope();
5274
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005275 HandleCodeCompleteResults(this, CodeCompleter,
5276 CodeCompletionContext::CCC_Other,
5277 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005278}
Douglas Gregor322328b2009-11-18 22:32:06 +00005279
John McCalld226f652010-08-21 09:40:31 +00005280void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00005281 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005282 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5283 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005284
5285 // Figure out where this @synthesize lives.
5286 ObjCContainerDecl *Container
John McCalld226f652010-08-21 09:40:31 +00005287 = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl);
Douglas Gregor322328b2009-11-18 22:32:06 +00005288 if (!Container ||
5289 (!isa<ObjCImplementationDecl>(Container) &&
5290 !isa<ObjCCategoryImplDecl>(Container)))
5291 return;
5292
5293 // Ignore any properties that have already been implemented.
5294 for (DeclContext::decl_iterator D = Container->decls_begin(),
5295 DEnd = Container->decls_end();
5296 D != DEnd; ++D)
5297 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5298 Results.Ignore(PropertyImpl->getPropertyDecl());
5299
5300 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005301 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005302 Results.EnterNewScope();
5303 if (ObjCImplementationDecl *ClassImpl
5304 = dyn_cast<ObjCImplementationDecl>(Container))
5305 AddObjCProperties(ClassImpl->getClassInterface(), false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005306 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005307 else
5308 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor73449212010-12-09 23:01:55 +00005309 false, CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005310 Results.ExitScope();
5311
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005312 HandleCodeCompleteResults(this, CodeCompleter,
5313 CodeCompletionContext::CCC_Other,
5314 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005315}
5316
5317void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
5318 IdentifierInfo *PropertyName,
John McCalld226f652010-08-21 09:40:31 +00005319 Decl *ObjCImpDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00005320 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005321 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5322 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005323
5324 // Figure out where this @synthesize lives.
5325 ObjCContainerDecl *Container
John McCalld226f652010-08-21 09:40:31 +00005326 = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl);
Douglas Gregor322328b2009-11-18 22:32:06 +00005327 if (!Container ||
5328 (!isa<ObjCImplementationDecl>(Container) &&
5329 !isa<ObjCCategoryImplDecl>(Container)))
5330 return;
5331
5332 // Figure out which interface we're looking into.
5333 ObjCInterfaceDecl *Class = 0;
5334 if (ObjCImplementationDecl *ClassImpl
5335 = dyn_cast<ObjCImplementationDecl>(Container))
5336 Class = ClassImpl->getClassInterface();
5337 else
5338 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5339 ->getClassInterface();
5340
5341 // Add all of the instance variables in this class and its superclasses.
5342 Results.EnterNewScope();
5343 for(; Class; Class = Class->getSuperClass()) {
5344 // FIXME: We could screen the type of each ivar for compatibility with
5345 // the property, but is that being too paternal?
5346 for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(),
5347 IVarEnd = Class->ivar_end();
5348 IVar != IVarEnd; ++IVar)
Douglas Gregor608300b2010-01-14 16:14:35 +00005349 Results.AddResult(Result(*IVar, 0), CurContext, 0, false);
Douglas Gregor322328b2009-11-18 22:32:06 +00005350 }
5351 Results.ExitScope();
5352
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005353 HandleCodeCompleteResults(this, CodeCompleter,
5354 CodeCompletionContext::CCC_Other,
5355 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005356}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005357
Douglas Gregor408be5a2010-08-25 01:08:01 +00005358// Mapping from selectors to the methods that implement that selector, along
5359// with the "in original class" flag.
5360typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5361 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005362
5363/// \brief Find all of the methods that reside in the given container
5364/// (and its superclasses, protocols, etc.) that meet the given
5365/// criteria. Insert those methods into the map of known methods,
5366/// indexed by selector so they can be easily found.
5367static void FindImplementableMethods(ASTContext &Context,
5368 ObjCContainerDecl *Container,
5369 bool WantInstanceMethods,
5370 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00005371 KnownMethodsMap &KnownMethods,
5372 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005373 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5374 // Recurse into protocols.
5375 const ObjCList<ObjCProtocolDecl> &Protocols
5376 = IFace->getReferencedProtocols();
5377 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005378 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005379 I != E; ++I)
5380 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005381 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005382
Douglas Gregorea766182010-10-18 18:21:28 +00005383 // Add methods from any class extensions and categories.
5384 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5385 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00005386 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5387 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005388 KnownMethods, false);
5389
5390 // Visit the superclass.
5391 if (IFace->getSuperClass())
5392 FindImplementableMethods(Context, IFace->getSuperClass(),
5393 WantInstanceMethods, ReturnType,
5394 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005395 }
5396
5397 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5398 // Recurse into protocols.
5399 const ObjCList<ObjCProtocolDecl> &Protocols
5400 = Category->getReferencedProtocols();
5401 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005402 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005403 I != E; ++I)
5404 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005405 KnownMethods, InOriginalClass);
5406
5407 // If this category is the original class, jump to the interface.
5408 if (InOriginalClass && Category->getClassInterface())
5409 FindImplementableMethods(Context, Category->getClassInterface(),
5410 WantInstanceMethods, ReturnType, KnownMethods,
5411 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005412 }
5413
5414 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
5415 // Recurse into protocols.
5416 const ObjCList<ObjCProtocolDecl> &Protocols
5417 = Protocol->getReferencedProtocols();
5418 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5419 E = Protocols.end();
5420 I != E; ++I)
5421 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005422 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005423 }
5424
5425 // Add methods in this container. This operation occurs last because
5426 // we want the methods from this container to override any methods
5427 // we've previously seen with the same selector.
5428 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
5429 MEnd = Container->meth_end();
5430 M != MEnd; ++M) {
5431 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
5432 if (!ReturnType.isNull() &&
5433 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
5434 continue;
5435
Douglas Gregor408be5a2010-08-25 01:08:01 +00005436 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005437 }
5438 }
5439}
5440
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005441/// \brief Add the parenthesized return or parameter type chunk to a code
5442/// completion string.
5443static void AddObjCPassingTypeChunk(QualType Type,
5444 ASTContext &Context,
5445 CodeCompletionBuilder &Builder) {
5446 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5447 Builder.AddTextChunk(GetCompletionTypeString(Type, Context,
5448 Builder.getAllocator()));
5449 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5450}
5451
5452/// \brief Determine whether the given class is or inherits from a class by
5453/// the given name.
5454static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
5455 llvm::StringRef Name) {
5456 if (!Class)
5457 return false;
5458
5459 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
5460 return true;
5461
5462 return InheritsFromClassNamed(Class->getSuperClass(), Name);
5463}
5464
5465/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
5466/// Key-Value Observing (KVO).
5467static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
5468 bool IsInstanceMethod,
5469 QualType ReturnType,
5470 ASTContext &Context,
5471 const KnownMethodsMap &KnownMethods,
5472 ResultBuilder &Results) {
5473 IdentifierInfo *PropName = Property->getIdentifier();
5474 if (!PropName || PropName->getLength() == 0)
5475 return;
5476
5477
5478 // Builder that will create each code completion.
5479 typedef CodeCompletionResult Result;
5480 CodeCompletionAllocator &Allocator = Results.getAllocator();
5481 CodeCompletionBuilder Builder(Allocator);
5482
5483 // The selector table.
5484 SelectorTable &Selectors = Context.Selectors;
5485
5486 // The property name, copied into the code completion allocation region
5487 // on demand.
5488 struct KeyHolder {
5489 CodeCompletionAllocator &Allocator;
5490 llvm::StringRef Key;
5491 const char *CopiedKey;
5492
5493 KeyHolder(CodeCompletionAllocator &Allocator, llvm::StringRef Key)
5494 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
5495
5496 operator const char *() {
5497 if (CopiedKey)
5498 return CopiedKey;
5499
5500 return CopiedKey = Allocator.CopyString(Key);
5501 }
5502 } Key(Allocator, PropName->getName());
5503
5504 // The uppercased name of the property name.
5505 std::string UpperKey = PropName->getName();
5506 if (!UpperKey.empty())
5507 UpperKey[0] = toupper(UpperKey[0]);
5508
5509 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
5510 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
5511 Property->getType());
5512 bool ReturnTypeMatchesVoid
5513 = ReturnType.isNull() || ReturnType->isVoidType();
5514
5515 // Add the normal accessor -(type)key.
5516 if (IsInstanceMethod &&
5517 !KnownMethods.count(Selectors.getNullarySelector(PropName)) &&
5518 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
5519 if (ReturnType.isNull())
5520 AddObjCPassingTypeChunk(Property->getType(), Context, Builder);
5521
5522 Builder.AddTypedTextChunk(Key);
5523 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
5524 CXCursor_ObjCInstanceMethodDecl));
5525 }
5526
5527 // If we have an integral or boolean property (or the user has provided
5528 // an integral or boolean return type), add the accessor -(type)isKey.
5529 if (IsInstanceMethod &&
5530 ((!ReturnType.isNull() &&
5531 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
5532 (ReturnType.isNull() &&
5533 (Property->getType()->isIntegerType() ||
5534 Property->getType()->isBooleanType())))) {
Douglas Gregor62041592011-02-17 03:19:26 +00005535 std::string SelectorName = (llvm::Twine("is") + UpperKey).str();
5536 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005537 if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) {
5538 if (ReturnType.isNull()) {
5539 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5540 Builder.AddTextChunk("BOOL");
5541 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5542 }
5543
5544 Builder.AddTypedTextChunk(
5545 Allocator.CopyString(SelectorId->getName()));
5546 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
5547 CXCursor_ObjCInstanceMethodDecl));
5548 }
5549 }
5550
5551 // Add the normal mutator.
5552 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
5553 !Property->getSetterMethodDecl()) {
Douglas Gregor62041592011-02-17 03:19:26 +00005554 std::string SelectorName = (llvm::Twine("set") + UpperKey).str();
5555 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005556 if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5557 if (ReturnType.isNull()) {
5558 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5559 Builder.AddTextChunk("void");
5560 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5561 }
5562
5563 Builder.AddTypedTextChunk(
5564 Allocator.CopyString(SelectorId->getName()));
5565 Builder.AddTypedTextChunk(":");
5566 AddObjCPassingTypeChunk(Property->getType(), Context, Builder);
5567 Builder.AddTextChunk(Key);
5568 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
5569 CXCursor_ObjCInstanceMethodDecl));
5570 }
5571 }
5572
5573 // Indexed and unordered accessors
5574 unsigned IndexedGetterPriority = CCP_CodePattern;
5575 unsigned IndexedSetterPriority = CCP_CodePattern;
5576 unsigned UnorderedGetterPriority = CCP_CodePattern;
5577 unsigned UnorderedSetterPriority = CCP_CodePattern;
5578 if (const ObjCObjectPointerType *ObjCPointer
5579 = Property->getType()->getAs<ObjCObjectPointerType>()) {
5580 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
5581 // If this interface type is not provably derived from a known
5582 // collection, penalize the corresponding completions.
5583 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
5584 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
5585 if (!InheritsFromClassNamed(IFace, "NSArray"))
5586 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
5587 }
5588
5589 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
5590 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
5591 if (!InheritsFromClassNamed(IFace, "NSSet"))
5592 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
5593 }
5594 }
5595 } else {
5596 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
5597 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
5598 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
5599 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
5600 }
5601
5602 // Add -(NSUInteger)countOf<key>
5603 if (IsInstanceMethod &&
5604 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00005605 std::string SelectorName = (llvm::Twine("countOf") + UpperKey).str();
5606 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005607 if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) {
5608 if (ReturnType.isNull()) {
5609 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5610 Builder.AddTextChunk("NSUInteger");
5611 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5612 }
5613
5614 Builder.AddTypedTextChunk(
5615 Allocator.CopyString(SelectorId->getName()));
5616 Results.AddResult(Result(Builder.TakeString(),
5617 std::min(IndexedGetterPriority,
5618 UnorderedGetterPriority),
5619 CXCursor_ObjCInstanceMethodDecl));
5620 }
5621 }
5622
5623 // Indexed getters
5624 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
5625 if (IsInstanceMethod &&
5626 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00005627 std::string SelectorName
5628 = (llvm::Twine("objectIn") + UpperKey + "AtIndex").str();
5629 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005630 if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5631 if (ReturnType.isNull()) {
5632 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5633 Builder.AddTextChunk("id");
5634 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5635 }
5636
5637 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
5638 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5639 Builder.AddTextChunk("NSUInteger");
5640 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5641 Builder.AddTextChunk("index");
5642 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
5643 CXCursor_ObjCInstanceMethodDecl));
5644 }
5645 }
5646
5647 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
5648 if (IsInstanceMethod &&
5649 (ReturnType.isNull() ||
5650 (ReturnType->isObjCObjectPointerType() &&
5651 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
5652 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
5653 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00005654 std::string SelectorName
5655 = (llvm::Twine(Property->getName()) + "AtIndexes").str();
5656 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005657 if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5658 if (ReturnType.isNull()) {
5659 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5660 Builder.AddTextChunk("NSArray *");
5661 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5662 }
5663
5664 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
5665 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5666 Builder.AddTextChunk("NSIndexSet *");
5667 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5668 Builder.AddTextChunk("indexes");
5669 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
5670 CXCursor_ObjCInstanceMethodDecl));
5671 }
5672 }
5673
5674 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
5675 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00005676 std::string SelectorName = (llvm::Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005677 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00005678 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005679 &Context.Idents.get("range")
5680 };
5681
5682 if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
5683 if (ReturnType.isNull()) {
5684 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5685 Builder.AddTextChunk("void");
5686 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5687 }
5688
5689 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
5690 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5691 Builder.AddPlaceholderChunk("object-type");
5692 Builder.AddTextChunk(" **");
5693 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5694 Builder.AddTextChunk("buffer");
5695 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5696 Builder.AddTypedTextChunk("range:");
5697 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5698 Builder.AddTextChunk("NSRange");
5699 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5700 Builder.AddTextChunk("inRange");
5701 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
5702 CXCursor_ObjCInstanceMethodDecl));
5703 }
5704 }
5705
5706 // Mutable indexed accessors
5707
5708 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
5709 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00005710 std::string SelectorName = (llvm::Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005711 IdentifierInfo *SelectorIds[2] = {
5712 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00005713 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005714 };
5715
5716 if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
5717 if (ReturnType.isNull()) {
5718 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5719 Builder.AddTextChunk("void");
5720 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5721 }
5722
5723 Builder.AddTypedTextChunk("insertObject:");
5724 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5725 Builder.AddPlaceholderChunk("object-type");
5726 Builder.AddTextChunk(" *");
5727 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5728 Builder.AddTextChunk("object");
5729 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5730 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
5731 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5732 Builder.AddPlaceholderChunk("NSUInteger");
5733 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5734 Builder.AddTextChunk("index");
5735 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
5736 CXCursor_ObjCInstanceMethodDecl));
5737 }
5738 }
5739
5740 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
5741 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00005742 std::string SelectorName = (llvm::Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005743 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00005744 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005745 &Context.Idents.get("atIndexes")
5746 };
5747
5748 if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
5749 if (ReturnType.isNull()) {
5750 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5751 Builder.AddTextChunk("void");
5752 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5753 }
5754
5755 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
5756 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5757 Builder.AddTextChunk("NSArray *");
5758 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5759 Builder.AddTextChunk("array");
5760 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5761 Builder.AddTypedTextChunk("atIndexes:");
5762 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5763 Builder.AddPlaceholderChunk("NSIndexSet *");
5764 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5765 Builder.AddTextChunk("indexes");
5766 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
5767 CXCursor_ObjCInstanceMethodDecl));
5768 }
5769 }
5770
5771 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
5772 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00005773 std::string SelectorName
5774 = (llvm::Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
5775 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005776 if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5777 if (ReturnType.isNull()) {
5778 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5779 Builder.AddTextChunk("void");
5780 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5781 }
5782
5783 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
5784 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5785 Builder.AddTextChunk("NSUInteger");
5786 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5787 Builder.AddTextChunk("index");
5788 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
5789 CXCursor_ObjCInstanceMethodDecl));
5790 }
5791 }
5792
5793 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
5794 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00005795 std::string SelectorName
5796 = (llvm::Twine("remove") + UpperKey + "AtIndexes").str();
5797 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005798 if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5799 if (ReturnType.isNull()) {
5800 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5801 Builder.AddTextChunk("void");
5802 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5803 }
5804
5805 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
5806 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5807 Builder.AddTextChunk("NSIndexSet *");
5808 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5809 Builder.AddTextChunk("indexes");
5810 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
5811 CXCursor_ObjCInstanceMethodDecl));
5812 }
5813 }
5814
5815 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
5816 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00005817 std::string SelectorName
5818 = (llvm::Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005819 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00005820 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005821 &Context.Idents.get("withObject")
5822 };
5823
5824 if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
5825 if (ReturnType.isNull()) {
5826 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5827 Builder.AddTextChunk("void");
5828 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5829 }
5830
5831 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
5832 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5833 Builder.AddPlaceholderChunk("NSUInteger");
5834 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5835 Builder.AddTextChunk("index");
5836 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5837 Builder.AddTypedTextChunk("withObject:");
5838 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5839 Builder.AddTextChunk("id");
5840 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5841 Builder.AddTextChunk("object");
5842 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
5843 CXCursor_ObjCInstanceMethodDecl));
5844 }
5845 }
5846
5847 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
5848 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00005849 std::string SelectorName1
5850 = (llvm::Twine("replace") + UpperKey + "AtIndexes").str();
5851 std::string SelectorName2 = (llvm::Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005852 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00005853 &Context.Idents.get(SelectorName1),
5854 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005855 };
5856
5857 if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
5858 if (ReturnType.isNull()) {
5859 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5860 Builder.AddTextChunk("void");
5861 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5862 }
5863
5864 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
5865 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5866 Builder.AddPlaceholderChunk("NSIndexSet *");
5867 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5868 Builder.AddTextChunk("indexes");
5869 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5870 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
5871 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5872 Builder.AddTextChunk("NSArray *");
5873 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5874 Builder.AddTextChunk("array");
5875 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
5876 CXCursor_ObjCInstanceMethodDecl));
5877 }
5878 }
5879
5880 // Unordered getters
5881 // - (NSEnumerator *)enumeratorOfKey
5882 if (IsInstanceMethod &&
5883 (ReturnType.isNull() ||
5884 (ReturnType->isObjCObjectPointerType() &&
5885 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
5886 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
5887 ->getName() == "NSEnumerator"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00005888 std::string SelectorName = (llvm::Twine("enumeratorOf") + UpperKey).str();
5889 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005890 if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) {
5891 if (ReturnType.isNull()) {
5892 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5893 Builder.AddTextChunk("NSEnumerator *");
5894 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5895 }
5896
5897 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
5898 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
5899 CXCursor_ObjCInstanceMethodDecl));
5900 }
5901 }
5902
5903 // - (type *)memberOfKey:(type *)object
5904 if (IsInstanceMethod &&
5905 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00005906 std::string SelectorName = (llvm::Twine("memberOf") + UpperKey).str();
5907 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005908 if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5909 if (ReturnType.isNull()) {
5910 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5911 Builder.AddPlaceholderChunk("object-type");
5912 Builder.AddTextChunk(" *");
5913 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5914 }
5915
5916 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
5917 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5918 if (ReturnType.isNull()) {
5919 Builder.AddPlaceholderChunk("object-type");
5920 Builder.AddTextChunk(" *");
5921 } else {
5922 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
5923 Builder.getAllocator()));
5924 }
5925 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5926 Builder.AddTextChunk("object");
5927 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
5928 CXCursor_ObjCInstanceMethodDecl));
5929 }
5930 }
5931
5932 // Mutable unordered accessors
5933 // - (void)addKeyObject:(type *)object
5934 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00005935 std::string SelectorName
5936 = (llvm::Twine("add") + UpperKey + llvm::Twine("Object")).str();
5937 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005938 if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5939 if (ReturnType.isNull()) {
5940 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5941 Builder.AddTextChunk("void");
5942 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5943 }
5944
5945 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
5946 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5947 Builder.AddPlaceholderChunk("object-type");
5948 Builder.AddTextChunk(" *");
5949 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5950 Builder.AddTextChunk("object");
5951 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
5952 CXCursor_ObjCInstanceMethodDecl));
5953 }
5954 }
5955
5956 // - (void)addKey:(NSSet *)objects
5957 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00005958 std::string SelectorName = (llvm::Twine("add") + UpperKey).str();
5959 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005960 if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5961 if (ReturnType.isNull()) {
5962 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5963 Builder.AddTextChunk("void");
5964 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5965 }
5966
5967 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
5968 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5969 Builder.AddTextChunk("NSSet *");
5970 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5971 Builder.AddTextChunk("objects");
5972 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
5973 CXCursor_ObjCInstanceMethodDecl));
5974 }
5975 }
5976
5977 // - (void)removeKeyObject:(type *)object
5978 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00005979 std::string SelectorName
5980 = (llvm::Twine("remove") + UpperKey + llvm::Twine("Object")).str();
5981 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005982 if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5983 if (ReturnType.isNull()) {
5984 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5985 Builder.AddTextChunk("void");
5986 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5987 }
5988
5989 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
5990 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5991 Builder.AddPlaceholderChunk("object-type");
5992 Builder.AddTextChunk(" *");
5993 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5994 Builder.AddTextChunk("object");
5995 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
5996 CXCursor_ObjCInstanceMethodDecl));
5997 }
5998 }
5999
6000 // - (void)removeKey:(NSSet *)objects
6001 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006002 std::string SelectorName = (llvm::Twine("remove") + UpperKey).str();
6003 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006004 if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
6005 if (ReturnType.isNull()) {
6006 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6007 Builder.AddTextChunk("void");
6008 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6009 }
6010
6011 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6012 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6013 Builder.AddTextChunk("NSSet *");
6014 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6015 Builder.AddTextChunk("objects");
6016 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6017 CXCursor_ObjCInstanceMethodDecl));
6018 }
6019 }
6020
6021 // - (void)intersectKey:(NSSet *)objects
6022 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006023 std::string SelectorName = (llvm::Twine("intersect") + UpperKey).str();
6024 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006025 if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
6026 if (ReturnType.isNull()) {
6027 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6028 Builder.AddTextChunk("void");
6029 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6030 }
6031
6032 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6033 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6034 Builder.AddTextChunk("NSSet *");
6035 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6036 Builder.AddTextChunk("objects");
6037 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6038 CXCursor_ObjCInstanceMethodDecl));
6039 }
6040 }
6041
6042 // Key-Value Observing
6043 // + (NSSet *)keyPathsForValuesAffectingKey
6044 if (!IsInstanceMethod &&
6045 (ReturnType.isNull() ||
6046 (ReturnType->isObjCObjectPointerType() &&
6047 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6048 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6049 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006050 std::string SelectorName
6051 = (llvm::Twine("keyPathsForValuesAffecting") + UpperKey).str();
6052 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006053 if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) {
6054 if (ReturnType.isNull()) {
6055 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6056 Builder.AddTextChunk("NSSet *");
6057 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6058 }
6059
6060 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6061 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6062 CXCursor_ObjCInstanceMethodDecl));
6063 }
6064 }
6065}
6066
Douglas Gregore8f5a172010-04-07 00:21:17 +00006067void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6068 bool IsInstanceMethod,
John McCallb3d87482010-08-24 05:47:05 +00006069 ParsedType ReturnTy,
John McCalld226f652010-08-21 09:40:31 +00006070 Decl *IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006071 // Determine the return type of the method we're declaring, if
6072 // provided.
6073 QualType ReturnType = GetTypeFromParser(ReturnTy);
6074
Douglas Gregorea766182010-10-18 18:21:28 +00006075 // Determine where we should start searching for methods.
6076 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006077 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006078 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006079 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6080 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006081 IsInImplementation = true;
6082 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006083 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006084 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006085 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006086 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006087 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006088 }
6089
6090 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006091 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006092 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006093 }
6094
Douglas Gregorea766182010-10-18 18:21:28 +00006095 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006096 HandleCodeCompleteResults(this, CodeCompleter,
6097 CodeCompletionContext::CCC_Other,
6098 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006099 return;
6100 }
6101
6102 // Find all of the methods that we could declare/implement here.
6103 KnownMethodsMap KnownMethods;
6104 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006105 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006106
Douglas Gregore8f5a172010-04-07 00:21:17 +00006107 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006108 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006109 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6110 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006111 Results.EnterNewScope();
6112 PrintingPolicy Policy(Context.PrintingPolicy);
6113 Policy.AnonymousTagLocations = false;
6114 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6115 MEnd = KnownMethods.end();
6116 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006117 ObjCMethodDecl *Method = M->second.first;
Douglas Gregor218937c2011-02-01 19:23:04 +00006118 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006119
6120 // If the result type was not already provided, add it to the
6121 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006122 if (ReturnType.isNull())
6123 AddObjCPassingTypeChunk(Method->getResultType(), Context, Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006124
6125 Selector Sel = Method->getSelector();
6126
6127 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006128 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006129 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006130
6131 // Add parameters to the pattern.
6132 unsigned I = 0;
6133 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6134 PEnd = Method->param_end();
6135 P != PEnd; (void)++P, ++I) {
6136 // Add the part of the selector name.
6137 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006138 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006139 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006140 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6141 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006142 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006143 } else
6144 break;
6145
6146 // Add the parameter type.
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006147 AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006148
6149 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006150 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006151 }
6152
6153 if (Method->isVariadic()) {
6154 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006155 Builder.AddChunk(CodeCompletionString::CK_Comma);
6156 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006157 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006158
Douglas Gregor447107d2010-05-28 00:57:46 +00006159 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006160 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006161 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6162 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6163 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006164 if (!Method->getResultType()->isVoidType()) {
6165 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006166 Builder.AddTextChunk("return");
6167 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6168 Builder.AddPlaceholderChunk("expression");
6169 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006170 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006171 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006172
Douglas Gregor218937c2011-02-01 19:23:04 +00006173 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6174 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006175 }
6176
Douglas Gregor408be5a2010-08-25 01:08:01 +00006177 unsigned Priority = CCP_CodePattern;
6178 if (!M->second.second)
6179 Priority += CCD_InBaseClass;
6180
Douglas Gregor218937c2011-02-01 19:23:04 +00006181 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor16ed9ad2010-08-17 16:06:07 +00006182 Method->isInstanceMethod()
6183 ? CXCursor_ObjCInstanceMethodDecl
6184 : CXCursor_ObjCClassMethodDecl));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006185 }
6186
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006187 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6188 // the properties in this class and its categories.
6189 if (Context.getLangOptions().ObjC2) {
6190 llvm::SmallVector<ObjCContainerDecl *, 4> Containers;
6191 Containers.push_back(SearchDecl);
6192
6193 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6194 if (!IFace)
6195 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6196 IFace = Category->getClassInterface();
6197
6198 if (IFace) {
6199 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6200 Category = Category->getNextClassCategory())
6201 Containers.push_back(Category);
6202 }
6203
6204 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6205 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6206 PEnd = Containers[I]->prop_end();
6207 P != PEnd; ++P) {
6208 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
6209 KnownMethods, Results);
6210 }
6211 }
6212 }
6213
Douglas Gregore8f5a172010-04-07 00:21:17 +00006214 Results.ExitScope();
6215
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006216 HandleCodeCompleteResults(this, CodeCompleter,
6217 CodeCompletionContext::CCC_Other,
6218 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006219}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006220
6221void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6222 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006223 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006224 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006225 IdentifierInfo **SelIdents,
6226 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006227 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006228 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006229 if (ExternalSource) {
6230 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6231 I != N; ++I) {
6232 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006233 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006234 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006235
6236 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006237 }
6238 }
6239
6240 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006241 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006242 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6243 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006244
6245 if (ReturnTy)
6246 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006247
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006248 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006249 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6250 MEnd = MethodPool.end();
6251 M != MEnd; ++M) {
6252 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6253 &M->second.second;
6254 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006255 MethList = MethList->Next) {
6256 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6257 NumSelIdents))
6258 continue;
6259
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006260 if (AtParameterName) {
6261 // Suggest parameter names we've seen before.
6262 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6263 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6264 if (Param->getIdentifier()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006265 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregordae68752011-02-01 22:57:45 +00006266 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006267 Param->getIdentifier()->getName()));
6268 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006269 }
6270 }
6271
6272 continue;
6273 }
6274
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006275 Result R(MethList->Method, 0);
6276 R.StartParameter = NumSelIdents;
6277 R.AllParametersAreInformative = false;
6278 R.DeclaringEntity = true;
6279 Results.MaybeAddResult(R, CurContext);
6280 }
6281 }
6282
6283 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006284 HandleCodeCompleteResults(this, CodeCompleter,
6285 CodeCompletionContext::CCC_Other,
6286 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006287}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006288
Douglas Gregorf29c5232010-08-24 22:20:20 +00006289void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006290 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006291 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006292 Results.EnterNewScope();
6293
6294 // #if <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006295 CodeCompletionBuilder Builder(Results.getAllocator());
6296 Builder.AddTypedTextChunk("if");
6297 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6298 Builder.AddPlaceholderChunk("condition");
6299 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006300
6301 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006302 Builder.AddTypedTextChunk("ifdef");
6303 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6304 Builder.AddPlaceholderChunk("macro");
6305 Results.AddResult(Builder.TakeString());
6306
Douglas Gregorf44e8542010-08-24 19:08:16 +00006307 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006308 Builder.AddTypedTextChunk("ifndef");
6309 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6310 Builder.AddPlaceholderChunk("macro");
6311 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006312
6313 if (InConditional) {
6314 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006315 Builder.AddTypedTextChunk("elif");
6316 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6317 Builder.AddPlaceholderChunk("condition");
6318 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006319
6320 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00006321 Builder.AddTypedTextChunk("else");
6322 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006323
6324 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00006325 Builder.AddTypedTextChunk("endif");
6326 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006327 }
6328
6329 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006330 Builder.AddTypedTextChunk("include");
6331 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6332 Builder.AddTextChunk("\"");
6333 Builder.AddPlaceholderChunk("header");
6334 Builder.AddTextChunk("\"");
6335 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006336
6337 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006338 Builder.AddTypedTextChunk("include");
6339 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6340 Builder.AddTextChunk("<");
6341 Builder.AddPlaceholderChunk("header");
6342 Builder.AddTextChunk(">");
6343 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006344
6345 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006346 Builder.AddTypedTextChunk("define");
6347 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6348 Builder.AddPlaceholderChunk("macro");
6349 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006350
6351 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00006352 Builder.AddTypedTextChunk("define");
6353 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6354 Builder.AddPlaceholderChunk("macro");
6355 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6356 Builder.AddPlaceholderChunk("args");
6357 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6358 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006359
6360 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006361 Builder.AddTypedTextChunk("undef");
6362 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6363 Builder.AddPlaceholderChunk("macro");
6364 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006365
6366 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00006367 Builder.AddTypedTextChunk("line");
6368 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6369 Builder.AddPlaceholderChunk("number");
6370 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006371
6372 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00006373 Builder.AddTypedTextChunk("line");
6374 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6375 Builder.AddPlaceholderChunk("number");
6376 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6377 Builder.AddTextChunk("\"");
6378 Builder.AddPlaceholderChunk("filename");
6379 Builder.AddTextChunk("\"");
6380 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006381
6382 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006383 Builder.AddTypedTextChunk("error");
6384 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6385 Builder.AddPlaceholderChunk("message");
6386 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006387
6388 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00006389 Builder.AddTypedTextChunk("pragma");
6390 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6391 Builder.AddPlaceholderChunk("arguments");
6392 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006393
6394 if (getLangOptions().ObjC1) {
6395 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006396 Builder.AddTypedTextChunk("import");
6397 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6398 Builder.AddTextChunk("\"");
6399 Builder.AddPlaceholderChunk("header");
6400 Builder.AddTextChunk("\"");
6401 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006402
6403 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006404 Builder.AddTypedTextChunk("import");
6405 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6406 Builder.AddTextChunk("<");
6407 Builder.AddPlaceholderChunk("header");
6408 Builder.AddTextChunk(">");
6409 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006410 }
6411
6412 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006413 Builder.AddTypedTextChunk("include_next");
6414 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6415 Builder.AddTextChunk("\"");
6416 Builder.AddPlaceholderChunk("header");
6417 Builder.AddTextChunk("\"");
6418 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006419
6420 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006421 Builder.AddTypedTextChunk("include_next");
6422 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6423 Builder.AddTextChunk("<");
6424 Builder.AddPlaceholderChunk("header");
6425 Builder.AddTextChunk(">");
6426 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006427
6428 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006429 Builder.AddTypedTextChunk("warning");
6430 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6431 Builder.AddPlaceholderChunk("message");
6432 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006433
6434 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
6435 // completions for them. And __include_macros is a Clang-internal extension
6436 // that we don't want to encourage anyone to use.
6437
6438 // FIXME: we don't support #assert or #unassert, so don't suggest them.
6439 Results.ExitScope();
6440
Douglas Gregorf44e8542010-08-24 19:08:16 +00006441 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00006442 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00006443 Results.data(), Results.size());
6444}
6445
6446void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00006447 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00006448 S->getFnParent()? Sema::PCC_RecoveryInFunction
6449 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006450}
6451
Douglas Gregorf29c5232010-08-24 22:20:20 +00006452void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006453 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006454 IsDefinition? CodeCompletionContext::CCC_MacroName
6455 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006456 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
6457 // Add just the names of macros, not their arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00006458 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006459 Results.EnterNewScope();
6460 for (Preprocessor::macro_iterator M = PP.macro_begin(),
6461 MEnd = PP.macro_end();
6462 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00006463 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006464 M->first->getName()));
6465 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006466 }
6467 Results.ExitScope();
6468 } else if (IsDefinition) {
6469 // FIXME: Can we detect when the user just wrote an include guard above?
6470 }
6471
Douglas Gregor52779fb2010-09-23 23:01:17 +00006472 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006473 Results.data(), Results.size());
6474}
6475
Douglas Gregorf29c5232010-08-24 22:20:20 +00006476void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00006477 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006478 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00006479
6480 if (!CodeCompleter || CodeCompleter->includeMacros())
6481 AddMacroResults(PP, Results);
6482
6483 // defined (<macro>)
6484 Results.EnterNewScope();
Douglas Gregor218937c2011-02-01 19:23:04 +00006485 CodeCompletionBuilder Builder(Results.getAllocator());
6486 Builder.AddTypedTextChunk("defined");
6487 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6488 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6489 Builder.AddPlaceholderChunk("macro");
6490 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6491 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00006492 Results.ExitScope();
6493
6494 HandleCodeCompleteResults(this, CodeCompleter,
6495 CodeCompletionContext::CCC_PreprocessorExpression,
6496 Results.data(), Results.size());
6497}
6498
6499void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
6500 IdentifierInfo *Macro,
6501 MacroInfo *MacroInfo,
6502 unsigned Argument) {
6503 // FIXME: In the future, we could provide "overload" results, much like we
6504 // do for function calls.
6505
6506 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00006507 S->getFnParent()? Sema::PCC_RecoveryInFunction
6508 : Sema::PCC_Namespace);
Douglas Gregorf29c5232010-08-24 22:20:20 +00006509}
6510
Douglas Gregor55817af2010-08-25 17:04:25 +00006511void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00006512 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00006513 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00006514 0, 0);
6515}
6516
Douglas Gregordae68752011-02-01 22:57:45 +00006517void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
John McCall0a2c5e22010-08-25 06:19:51 +00006518 llvm::SmallVectorImpl<CodeCompletionResult> &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006519 ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00006520 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
6521 CodeCompletionDeclConsumer Consumer(Builder,
6522 Context.getTranslationUnitDecl());
6523 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
6524 Consumer);
6525 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00006526
6527 if (!CodeCompleter || CodeCompleter->includeMacros())
6528 AddMacroResults(PP, Builder);
6529
6530 Results.clear();
6531 Results.insert(Results.end(),
6532 Builder.data(), Builder.data() + Builder.size());
6533}