blob: c09cd177bee67bb9d25fee613a5652be68211c05 [file] [log] [blame]
Douglas Gregor81b747b2009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the code-completion semantic actions.
11//
12//===----------------------------------------------------------------------===//
John McCall2d887082010-08-25 22:03:47 +000013#include "clang/Sema/SemaInternal.h"
Douglas Gregore737f502010-08-12 20:07:10 +000014#include "clang/Sema/Lookup.h"
John McCall120d63c2010-08-24 20:38:10 +000015#include "clang/Sema/Overload.h"
Douglas Gregor81b747b2009-09-17 21:32:03 +000016#include "clang/Sema/CodeCompleteConsumer.h"
Douglas Gregor719770d2010-04-06 17:30:22 +000017#include "clang/Sema/ExternalSemaSource.h"
John McCall5f1e0942010-08-24 08:50:51 +000018#include "clang/Sema/Scope.h"
John McCall781472f2010-08-25 08:40:02 +000019#include "clang/Sema/ScopeInfo.h"
John McCall7cd088e2010-08-24 07:21:54 +000020#include "clang/AST/DeclObjC.h"
Douglas Gregorb9d0ef72009-09-21 19:57:38 +000021#include "clang/AST/ExprCXX.h"
Douglas Gregor24a069f2009-11-17 17:59:40 +000022#include "clang/AST/ExprObjC.h"
Douglas Gregorc5b2e582012-01-29 18:15:03 +000023#include "clang/Lex/HeaderSearch.h"
Douglas Gregor3f7c7f42009-10-30 16:50:04 +000024#include "clang/Lex/MacroInfo.h"
25#include "clang/Lex/Preprocessor.h"
Douglas Gregord36adf52010-09-16 16:06:31 +000026#include "llvm/ADT/DenseSet.h"
Benjamin Kramer013b3662012-01-30 16:17:39 +000027#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000028#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer8fe83e12012-02-04 13:45:25 +000029#include "llvm/ADT/SmallString.h"
Douglas Gregor6a684032009-09-28 03:51:44 +000030#include "llvm/ADT/StringExtras.h"
Douglas Gregor22f56992010-04-06 19:22:33 +000031#include "llvm/ADT/StringSwitch.h"
Douglas Gregor458433d2010-08-26 15:07:07 +000032#include "llvm/ADT/Twine.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000033#include <list>
34#include <map>
35#include <vector>
Douglas Gregor81b747b2009-09-17 21:32:03 +000036
37using namespace clang;
John McCall781472f2010-08-25 08:40:02 +000038using namespace sema;
Douglas Gregor81b747b2009-09-17 21:32:03 +000039
Douglas Gregor86d9a522009-09-21 16:56:56 +000040namespace {
41 /// \brief A container of code-completion results.
42 class ResultBuilder {
43 public:
44 /// \brief The type of a name-lookup filter, which can be provided to the
45 /// name-lookup routines to specify which declarations should be included in
46 /// the result set (when it returns true) and which declarations should be
47 /// filtered out (returns false).
48 typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
49
John McCall0a2c5e22010-08-25 06:19:51 +000050 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +000051
52 private:
53 /// \brief The actual results we have found.
54 std::vector<Result> Results;
55
56 /// \brief A record of all of the declarations we have found and placed
57 /// into the result set, used to ensure that no declaration ever gets into
58 /// the result set twice.
59 llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
60
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000061 typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
62
63 /// \brief An entry in the shadow map, which is optimized to store
64 /// a single (declaration, index) mapping (the common case) but
65 /// can also store a list of (declaration, index) mappings.
66 class ShadowMapEntry {
Chris Lattner5f9e2722011-07-23 10:55:15 +000067 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000068
69 /// \brief Contains either the solitary NamedDecl * or a vector
70 /// of (declaration, index) pairs.
71 llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
72
73 /// \brief When the entry contains a single declaration, this is
74 /// the index associated with that entry.
75 unsigned SingleDeclIndex;
76
77 public:
78 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
79
80 void Add(NamedDecl *ND, unsigned Index) {
81 if (DeclOrVector.isNull()) {
82 // 0 - > 1 elements: just set the single element information.
83 DeclOrVector = ND;
84 SingleDeclIndex = Index;
85 return;
86 }
87
88 if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
89 // 1 -> 2 elements: create the vector of results and push in the
90 // existing declaration.
91 DeclIndexPairVector *Vec = new DeclIndexPairVector;
92 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
93 DeclOrVector = Vec;
94 }
95
96 // Add the new element to the end of the vector.
97 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
98 DeclIndexPair(ND, Index));
99 }
100
101 void Destroy() {
102 if (DeclIndexPairVector *Vec
103 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
104 delete Vec;
105 DeclOrVector = ((NamedDecl *)0);
106 }
107 }
108
109 // Iteration.
110 class iterator;
111 iterator begin() const;
112 iterator end() const;
113 };
114
Douglas Gregor86d9a522009-09-21 16:56:56 +0000115 /// \brief A mapping from declaration names to the declarations that have
116 /// this name within a particular scope and their index within the list of
117 /// results.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000118 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000119
120 /// \brief The semantic analysis object for which results are being
121 /// produced.
122 Sema &SemaRef;
Douglas Gregor218937c2011-02-01 19:23:04 +0000123
124 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000125 CodeCompletionAllocator &Allocator;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000126
127 /// \brief If non-NULL, a filter function used to remove any code-completion
128 /// results that are not desirable.
129 LookupFilter Filter;
Douglas Gregor45bcd432010-01-14 03:21:49 +0000130
131 /// \brief Whether we should allow declarations as
132 /// nested-name-specifiers that would otherwise be filtered out.
133 bool AllowNestedNameSpecifiers;
134
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000135 /// \brief If set, the type that we would prefer our resulting value
136 /// declarations to have.
137 ///
138 /// Closely matching the preferred type gives a boost to a result's
139 /// priority.
140 CanQualType PreferredType;
141
Douglas Gregor86d9a522009-09-21 16:56:56 +0000142 /// \brief A list of shadow maps, which is used to model name hiding at
143 /// different levels of, e.g., the inheritance hierarchy.
144 std::list<ShadowMap> ShadowMaps;
145
Douglas Gregor3cdee122010-08-26 16:36:48 +0000146 /// \brief If we're potentially referring to a C++ member function, the set
147 /// of qualifiers applied to the object type.
148 Qualifiers ObjectTypeQualifiers;
149
150 /// \brief Whether the \p ObjectTypeQualifiers field is active.
151 bool HasObjectTypeQualifiers;
152
Douglas Gregor265f7492010-08-27 15:29:55 +0000153 /// \brief The selector that we prefer.
154 Selector PreferredSelector;
155
Douglas Gregorca45da02010-11-02 20:36:02 +0000156 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000157 CodeCompletionContext CompletionContext;
158
Douglas Gregorca45da02010-11-02 20:36:02 +0000159 /// \brief If we are in an instance method definition, the @implementation
160 /// object.
161 ObjCImplementationDecl *ObjCImplementation;
162
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000163 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000164
Douglas Gregor6f942b22010-09-21 16:06:22 +0000165 void MaybeAddConstructorResults(Result R);
166
Douglas Gregor86d9a522009-09-21 16:56:56 +0000167 public:
Douglas Gregordae68752011-02-01 22:57:45 +0000168 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000169 const CodeCompletionContext &CompletionContext,
170 LookupFilter Filter = 0)
Douglas Gregor218937c2011-02-01 19:23:04 +0000171 : SemaRef(SemaRef), Allocator(Allocator), Filter(Filter),
172 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-11-02 20:36:02 +0000173 CompletionContext(CompletionContext),
174 ObjCImplementation(0)
175 {
176 // If this is an Objective-C instance method definition, dig out the
177 // corresponding implementation.
178 switch (CompletionContext.getKind()) {
179 case CodeCompletionContext::CCC_Expression:
180 case CodeCompletionContext::CCC_ObjCMessageReceiver:
181 case CodeCompletionContext::CCC_ParenthesizedExpression:
182 case CodeCompletionContext::CCC_Statement:
183 case CodeCompletionContext::CCC_Recovery:
184 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
185 if (Method->isInstanceMethod())
186 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
187 ObjCImplementation = Interface->getImplementation();
188 break;
189
190 default:
191 break;
192 }
193 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000194
Douglas Gregord8e8a582010-05-25 21:41:55 +0000195 /// \brief Whether we should include code patterns in the completion
196 /// results.
197 bool includeCodePatterns() const {
198 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000199 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000200 }
201
Douglas Gregor86d9a522009-09-21 16:56:56 +0000202 /// \brief Set the filter used for code-completion results.
203 void setFilter(LookupFilter Filter) {
204 this->Filter = Filter;
205 }
206
Douglas Gregor86d9a522009-09-21 16:56:56 +0000207 Result *data() { return Results.empty()? 0 : &Results.front(); }
208 unsigned size() const { return Results.size(); }
209 bool empty() const { return Results.empty(); }
210
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000211 /// \brief Specify the preferred type.
212 void setPreferredType(QualType T) {
213 PreferredType = SemaRef.Context.getCanonicalType(T);
214 }
215
Douglas Gregor3cdee122010-08-26 16:36:48 +0000216 /// \brief Set the cv-qualifiers on the object type, for us in filtering
217 /// calls to member functions.
218 ///
219 /// When there are qualifiers in this set, they will be used to filter
220 /// out member functions that aren't available (because there will be a
221 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
222 /// match.
223 void setObjectTypeQualifiers(Qualifiers Quals) {
224 ObjectTypeQualifiers = Quals;
225 HasObjectTypeQualifiers = true;
226 }
227
Douglas Gregor265f7492010-08-27 15:29:55 +0000228 /// \brief Set the preferred selector.
229 ///
230 /// When an Objective-C method declaration result is added, and that
231 /// method's selector matches this preferred selector, we give that method
232 /// a slight priority boost.
233 void setPreferredSelector(Selector Sel) {
234 PreferredSelector = Sel;
235 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000236
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000237 /// \brief Retrieve the code-completion context for which results are
238 /// being collected.
239 const CodeCompletionContext &getCompletionContext() const {
240 return CompletionContext;
241 }
242
Douglas Gregor45bcd432010-01-14 03:21:49 +0000243 /// \brief Specify whether nested-name-specifiers are allowed.
244 void allowNestedNameSpecifiers(bool Allow = true) {
245 AllowNestedNameSpecifiers = Allow;
246 }
247
Douglas Gregorb9d77572010-09-21 00:03:25 +0000248 /// \brief Return the semantic analysis object for which we are collecting
249 /// code completion results.
250 Sema &getSema() const { return SemaRef; }
251
Douglas Gregor218937c2011-02-01 19:23:04 +0000252 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000253 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Douglas Gregor218937c2011-02-01 19:23:04 +0000254
Douglas Gregore495b7f2010-01-14 00:20:49 +0000255 /// \brief Determine whether the given declaration is at all interesting
256 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000257 ///
258 /// \param ND the declaration that we are inspecting.
259 ///
260 /// \param AsNestedNameSpecifier will be set true if this declaration is
261 /// only interesting when it is a nested-name-specifier.
262 bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000263
264 /// \brief Check whether the result is hidden by the Hiding declaration.
265 ///
266 /// \returns true if the result is hidden and cannot be found, false if
267 /// the hidden result could still be found. When false, \p R may be
268 /// modified to describe how the result can be found (e.g., via extra
269 /// qualification).
270 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
271 NamedDecl *Hiding);
272
Douglas Gregor86d9a522009-09-21 16:56:56 +0000273 /// \brief Add a new result to this result set (if it isn't already in one
274 /// of the shadow maps), or replace an existing result (for, e.g., a
275 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000276 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000277 /// \param R the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000278 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000279 /// \param CurContext the context in which this result will be named.
Douglas Gregor456c4a12009-09-21 20:12:40 +0000280 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000281
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000282 /// \brief Add a new result to this result set, where we already know
283 /// the hiding declation (if any).
284 ///
285 /// \param R the result to add (if it is unique).
286 ///
287 /// \param CurContext the context in which this result will be named.
288 ///
289 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000290 ///
291 /// \param InBaseClass whether the result was found in a base
292 /// class of the searched context.
293 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
294 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000295
Douglas Gregora4477812010-01-14 16:01:26 +0000296 /// \brief Add a new non-declaration result to this result set.
297 void AddResult(Result R);
298
Douglas Gregor86d9a522009-09-21 16:56:56 +0000299 /// \brief Enter into a new scope.
300 void EnterNewScope();
301
302 /// \brief Exit from the current scope.
303 void ExitScope();
304
Douglas Gregor55385fe2009-11-18 04:19:12 +0000305 /// \brief Ignore this declaration, if it is seen again.
306 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
307
Douglas Gregor86d9a522009-09-21 16:56:56 +0000308 /// \name Name lookup predicates
309 ///
310 /// These predicates can be passed to the name lookup functions to filter the
311 /// results of name lookup. All of the predicates have the same type, so that
312 ///
313 //@{
Douglas Gregor791215b2009-09-21 20:51:25 +0000314 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000315 bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
Douglas Gregorf9578432010-07-28 21:50:18 +0000316 bool IsIntegralConstantValue(NamedDecl *ND) const;
Douglas Gregor01dfea02010-01-10 23:08:15 +0000317 bool IsOrdinaryNonValueName(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000318 bool IsNestedNameSpecifier(NamedDecl *ND) const;
319 bool IsEnum(NamedDecl *ND) const;
320 bool IsClassOrStruct(NamedDecl *ND) const;
321 bool IsUnion(NamedDecl *ND) const;
322 bool IsNamespace(NamedDecl *ND) const;
323 bool IsNamespaceOrAlias(NamedDecl *ND) const;
324 bool IsType(NamedDecl *ND) const;
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000325 bool IsMember(NamedDecl *ND) const;
Douglas Gregor80f4f4c2010-01-14 16:08:12 +0000326 bool IsObjCIvar(NamedDecl *ND) const;
Douglas Gregor8e254cf2010-05-27 23:06:34 +0000327 bool IsObjCMessageReceiver(NamedDecl *ND) const;
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000328 bool IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const;
Douglas Gregorfb629412010-08-23 21:17:50 +0000329 bool IsObjCCollection(NamedDecl *ND) const;
Douglas Gregor52779fb2010-09-23 23:01:17 +0000330 bool IsImpossibleToSatisfy(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000331 //@}
332 };
333}
334
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000335class ResultBuilder::ShadowMapEntry::iterator {
336 llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
337 unsigned SingleDeclIndex;
338
339public:
340 typedef DeclIndexPair value_type;
341 typedef value_type reference;
342 typedef std::ptrdiff_t difference_type;
343 typedef std::input_iterator_tag iterator_category;
344
345 class pointer {
346 DeclIndexPair Value;
347
348 public:
349 pointer(const DeclIndexPair &Value) : Value(Value) { }
350
351 const DeclIndexPair *operator->() const {
352 return &Value;
353 }
354 };
355
356 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
357
358 iterator(NamedDecl *SingleDecl, unsigned Index)
359 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
360
361 iterator(const DeclIndexPair *Iterator)
362 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
363
364 iterator &operator++() {
365 if (DeclOrIterator.is<NamedDecl *>()) {
366 DeclOrIterator = (NamedDecl *)0;
367 SingleDeclIndex = 0;
368 return *this;
369 }
370
371 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
372 ++I;
373 DeclOrIterator = I;
374 return *this;
375 }
376
Chris Lattner66392d42010-09-04 18:12:20 +0000377 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000378 iterator tmp(*this);
379 ++(*this);
380 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000381 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000382
383 reference operator*() const {
384 if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
385 return reference(ND, SingleDeclIndex);
386
Douglas Gregord490f952009-12-06 21:27:58 +0000387 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000388 }
389
390 pointer operator->() const {
391 return pointer(**this);
392 }
393
394 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000395 return X.DeclOrIterator.getOpaqueValue()
396 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000397 X.SingleDeclIndex == Y.SingleDeclIndex;
398 }
399
400 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000401 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000402 }
403};
404
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000405ResultBuilder::ShadowMapEntry::iterator
406ResultBuilder::ShadowMapEntry::begin() const {
407 if (DeclOrVector.isNull())
408 return iterator();
409
410 if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
411 return iterator(ND, SingleDeclIndex);
412
413 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
414}
415
416ResultBuilder::ShadowMapEntry::iterator
417ResultBuilder::ShadowMapEntry::end() const {
418 if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
419 return iterator();
420
421 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
422}
423
Douglas Gregor456c4a12009-09-21 20:12:40 +0000424/// \brief Compute the qualification required to get from the current context
425/// (\p CurContext) to the target context (\p TargetContext).
426///
427/// \param Context the AST context in which the qualification will be used.
428///
429/// \param CurContext the context where an entity is being named, which is
430/// typically based on the current scope.
431///
432/// \param TargetContext the context in which the named entity actually
433/// resides.
434///
435/// \returns a nested name specifier that refers into the target context, or
436/// NULL if no qualification is needed.
437static NestedNameSpecifier *
438getRequiredQualification(ASTContext &Context,
439 DeclContext *CurContext,
440 DeclContext *TargetContext) {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000441 SmallVector<DeclContext *, 4> TargetParents;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000442
443 for (DeclContext *CommonAncestor = TargetContext;
444 CommonAncestor && !CommonAncestor->Encloses(CurContext);
445 CommonAncestor = CommonAncestor->getLookupParent()) {
446 if (CommonAncestor->isTransparentContext() ||
447 CommonAncestor->isFunctionOrMethod())
448 continue;
449
450 TargetParents.push_back(CommonAncestor);
451 }
452
453 NestedNameSpecifier *Result = 0;
454 while (!TargetParents.empty()) {
455 DeclContext *Parent = TargetParents.back();
456 TargetParents.pop_back();
457
Douglas Gregorfb629412010-08-23 21:17:50 +0000458 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
459 if (!Namespace->getIdentifier())
460 continue;
461
Douglas Gregor456c4a12009-09-21 20:12:40 +0000462 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000463 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000464 else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
465 Result = NestedNameSpecifier::Create(Context, Result,
466 false,
467 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000468 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000469 return Result;
470}
471
Douglas Gregor45bcd432010-01-14 03:21:49 +0000472bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
473 bool &AsNestedNameSpecifier) const {
474 AsNestedNameSpecifier = false;
475
Douglas Gregore495b7f2010-01-14 00:20:49 +0000476 ND = ND->getUnderlyingDecl();
477 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000478
479 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000480 if (!ND->getDeclName())
481 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000482
483 // Friend declarations and declarations introduced due to friends are never
484 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000485 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000486 return false;
487
Douglas Gregor76282942009-12-11 17:31:05 +0000488 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000489 if (isa<ClassTemplateSpecializationDecl>(ND) ||
490 isa<ClassTemplatePartialSpecializationDecl>(ND))
491 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000492
Douglas Gregor76282942009-12-11 17:31:05 +0000493 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000494 if (isa<UsingDecl>(ND))
495 return false;
496
497 // Some declarations have reserved names that we don't want to ever show.
498 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000499 // __va_list_tag is a freak of nature. Find it and skip it.
500 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000501 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000502
Douglas Gregorf52cede2009-10-09 22:16:47 +0000503 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000504 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000505 //
506 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000507 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000508 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000509 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000510 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
511 (ND->getLocation().isInvalid() ||
512 SemaRef.SourceMgr.isInSystemHeader(
513 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000514 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000515 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000516 }
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000517
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000518 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
519 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
520 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000521 Filter != &ResultBuilder::IsNamespaceOrAlias &&
522 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000523 AsNestedNameSpecifier = true;
524
Douglas Gregor86d9a522009-09-21 16:56:56 +0000525 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000526 if (Filter && !(this->*Filter)(ND)) {
527 // Check whether it is interesting as a nested-name-specifier.
David Blaikie4e4d0842012-03-11 07:00:24 +0000528 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor45bcd432010-01-14 03:21:49 +0000529 IsNestedNameSpecifier(ND) &&
530 (Filter != &ResultBuilder::IsMember ||
531 (isa<CXXRecordDecl>(ND) &&
532 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
533 AsNestedNameSpecifier = true;
534 return true;
535 }
536
Douglas Gregore495b7f2010-01-14 00:20:49 +0000537 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000538 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000539 // ... then it must be interesting!
540 return true;
541}
542
Douglas Gregor6660d842010-01-14 00:41:07 +0000543bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
544 NamedDecl *Hiding) {
545 // In C, there is no way to refer to a hidden name.
546 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
547 // name if we introduce the tag type.
David Blaikie4e4d0842012-03-11 07:00:24 +0000548 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor6660d842010-01-14 00:41:07 +0000549 return true;
550
Sebastian Redl7a126a42010-08-31 00:36:30 +0000551 DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000552
553 // There is no way to qualify a name declared in a function or method.
554 if (HiddenCtx->isFunctionOrMethod())
555 return true;
556
Sebastian Redl7a126a42010-08-31 00:36:30 +0000557 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000558 return true;
559
560 // We can refer to the result with the appropriate qualification. Do it.
561 R.Hidden = true;
562 R.QualifierIsInformative = false;
563
564 if (!R.Qualifier)
565 R.Qualifier = getRequiredQualification(SemaRef.Context,
566 CurContext,
567 R.Declaration->getDeclContext());
568 return false;
569}
570
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000571/// \brief A simplified classification of types used to determine whether two
572/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000573SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000574 switch (T->getTypeClass()) {
575 case Type::Builtin:
576 switch (cast<BuiltinType>(T)->getKind()) {
577 case BuiltinType::Void:
578 return STC_Void;
579
580 case BuiltinType::NullPtr:
581 return STC_Pointer;
582
583 case BuiltinType::Overload:
584 case BuiltinType::Dependent:
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000585 return STC_Other;
586
587 case BuiltinType::ObjCId:
588 case BuiltinType::ObjCClass:
589 case BuiltinType::ObjCSel:
590 return STC_ObjectiveC;
591
592 default:
593 return STC_Arithmetic;
594 }
David Blaikie7530c032012-01-17 06:56:22 +0000595
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000596 case Type::Complex:
597 return STC_Arithmetic;
598
599 case Type::Pointer:
600 return STC_Pointer;
601
602 case Type::BlockPointer:
603 return STC_Block;
604
605 case Type::LValueReference:
606 case Type::RValueReference:
607 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
608
609 case Type::ConstantArray:
610 case Type::IncompleteArray:
611 case Type::VariableArray:
612 case Type::DependentSizedArray:
613 return STC_Array;
614
615 case Type::DependentSizedExtVector:
616 case Type::Vector:
617 case Type::ExtVector:
618 return STC_Arithmetic;
619
620 case Type::FunctionProto:
621 case Type::FunctionNoProto:
622 return STC_Function;
623
624 case Type::Record:
625 return STC_Record;
626
627 case Type::Enum:
628 return STC_Arithmetic;
629
630 case Type::ObjCObject:
631 case Type::ObjCInterface:
632 case Type::ObjCObjectPointer:
633 return STC_ObjectiveC;
634
635 default:
636 return STC_Other;
637 }
638}
639
640/// \brief Get the type that a given expression will have if this declaration
641/// is used as an expression in its "typical" code-completion form.
Douglas Gregor1827e102010-08-16 16:18:59 +0000642QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000643 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
644
645 if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
646 return C.getTypeDeclType(Type);
647 if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
648 return C.getObjCInterfaceType(Iface);
649
650 QualType T;
651 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000652 T = Function->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000653 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000654 T = Method->getSendResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000655 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000656 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000657 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
658 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
659 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
660 T = Property->getType();
661 else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
662 T = Value->getType();
663 else
664 return QualType();
Douglas Gregor3e64d562011-04-14 20:33:34 +0000665
666 // Dig through references, function pointers, and block pointers to
667 // get down to the likely type of an expression when the entity is
668 // used.
669 do {
670 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
671 T = Ref->getPointeeType();
672 continue;
673 }
674
675 if (const PointerType *Pointer = T->getAs<PointerType>()) {
676 if (Pointer->getPointeeType()->isFunctionType()) {
677 T = Pointer->getPointeeType();
678 continue;
679 }
680
681 break;
682 }
683
684 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
685 T = Block->getPointeeType();
686 continue;
687 }
688
689 if (const FunctionType *Function = T->getAs<FunctionType>()) {
690 T = Function->getResultType();
691 continue;
692 }
693
694 break;
695 } while (true);
696
697 return T;
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000698}
699
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000700void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
701 // If this is an Objective-C method declaration whose selector matches our
702 // preferred selector, give it a priority boost.
703 if (!PreferredSelector.isNull())
704 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
705 if (PreferredSelector == Method->getSelector())
706 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000707
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000708 // If we have a preferred type, adjust the priority for results with exactly-
709 // matching or nearly-matching types.
710 if (!PreferredType.isNull()) {
711 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
712 if (!T.isNull()) {
713 CanQualType TC = SemaRef.Context.getCanonicalType(T);
714 // Check for exactly-matching types (modulo qualifiers).
715 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
716 R.Priority /= CCF_ExactTypeMatch;
717 // Check for nearly-matching types, based on classification of each.
718 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000719 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000720 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
721 R.Priority /= CCF_SimilarTypeMatch;
722 }
723 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000724}
725
Douglas Gregor6f942b22010-09-21 16:06:22 +0000726void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikie4e4d0842012-03-11 07:00:24 +0000727 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor6f942b22010-09-21 16:06:22 +0000728 !CompletionContext.wantConstructorResults())
729 return;
730
731 ASTContext &Context = SemaRef.Context;
732 NamedDecl *D = R.Declaration;
733 CXXRecordDecl *Record = 0;
734 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
735 Record = ClassTemplate->getTemplatedDecl();
736 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
737 // Skip specializations and partial specializations.
738 if (isa<ClassTemplateSpecializationDecl>(Record))
739 return;
740 } else {
741 // There are no constructors here.
742 return;
743 }
744
745 Record = Record->getDefinition();
746 if (!Record)
747 return;
748
749
750 QualType RecordTy = Context.getTypeDeclType(Record);
751 DeclarationName ConstructorName
752 = Context.DeclarationNames.getCXXConstructorName(
753 Context.getCanonicalType(RecordTy));
754 for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
755 Ctors.first != Ctors.second; ++Ctors.first) {
756 R.Declaration = *Ctors.first;
757 R.CursorKind = getCursorKindForDecl(R.Declaration);
758 Results.push_back(R);
759 }
760}
761
Douglas Gregore495b7f2010-01-14 00:20:49 +0000762void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
763 assert(!ShadowMaps.empty() && "Must enter into a results scope");
764
765 if (R.Kind != Result::RK_Declaration) {
766 // For non-declaration results, just add the result.
767 Results.push_back(R);
768 return;
769 }
770
771 // Look through using declarations.
772 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
773 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
774 return;
775 }
776
777 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
778 unsigned IDNS = CanonDecl->getIdentifierNamespace();
779
Douglas Gregor45bcd432010-01-14 03:21:49 +0000780 bool AsNestedNameSpecifier = false;
781 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000782 return;
783
Douglas Gregor6f942b22010-09-21 16:06:22 +0000784 // C++ constructors are never found by name lookup.
785 if (isa<CXXConstructorDecl>(R.Declaration))
786 return;
787
Douglas Gregor86d9a522009-09-21 16:56:56 +0000788 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000789 ShadowMapEntry::iterator I, IEnd;
790 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
791 if (NamePos != SMap.end()) {
792 I = NamePos->second.begin();
793 IEnd = NamePos->second.end();
794 }
795
796 for (; I != IEnd; ++I) {
797 NamedDecl *ND = I->first;
798 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000799 if (ND->getCanonicalDecl() == CanonDecl) {
800 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000801 Results[Index].Declaration = R.Declaration;
802
Douglas Gregor86d9a522009-09-21 16:56:56 +0000803 // We're done.
804 return;
805 }
806 }
807
808 // This is a new declaration in this scope. However, check whether this
809 // declaration name is hidden by a similarly-named declaration in an outer
810 // scope.
811 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
812 --SMEnd;
813 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000814 ShadowMapEntry::iterator I, IEnd;
815 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
816 if (NamePos != SM->end()) {
817 I = NamePos->second.begin();
818 IEnd = NamePos->second.end();
819 }
820 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000821 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000822 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000823 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
824 Decl::IDNS_ObjCProtocol)))
825 continue;
826
827 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000828 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000829 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000830 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000831 continue;
832
833 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000834 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000835 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000836
837 break;
838 }
839 }
840
841 // Make sure that any given declaration only shows up in the result set once.
842 if (!AllDeclsFound.insert(CanonDecl))
843 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000844
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000845 // If the filter is for nested-name-specifiers, then this result starts a
846 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000847 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000848 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000849 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000850 } else
851 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000852
Douglas Gregor0563c262009-09-22 23:15:58 +0000853 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000854 if (R.QualifierIsInformative && !R.Qualifier &&
855 !R.StartsNestedNameSpecifier) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000856 DeclContext *Ctx = R.Declaration->getDeclContext();
857 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
858 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
859 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
860 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
861 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
862 else
863 R.QualifierIsInformative = false;
864 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000865
Douglas Gregor86d9a522009-09-21 16:56:56 +0000866 // Insert this result into the set of results and into the current shadow
867 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000868 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000869 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000870
871 if (!AsNestedNameSpecifier)
872 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000873}
874
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000875void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000876 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000877 if (R.Kind != Result::RK_Declaration) {
878 // For non-declaration results, just add the result.
879 Results.push_back(R);
880 return;
881 }
882
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000883 // Look through using declarations.
884 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
885 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
886 return;
887 }
888
Douglas Gregor45bcd432010-01-14 03:21:49 +0000889 bool AsNestedNameSpecifier = false;
890 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000891 return;
892
Douglas Gregor6f942b22010-09-21 16:06:22 +0000893 // C++ constructors are never found by name lookup.
894 if (isa<CXXConstructorDecl>(R.Declaration))
895 return;
896
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000897 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
898 return;
Nick Lewycky173a37a2012-04-03 21:44:08 +0000899
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000900 // Make sure that any given declaration only shows up in the result set once.
901 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
902 return;
903
904 // If the filter is for nested-name-specifiers, then this result starts a
905 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000906 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000907 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000908 R.Priority = CCP_NestedNameSpecifier;
909 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000910 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
911 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000912 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000913 R.QualifierIsInformative = true;
914
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000915 // If this result is supposed to have an informative qualifier, add one.
916 if (R.QualifierIsInformative && !R.Qualifier &&
917 !R.StartsNestedNameSpecifier) {
918 DeclContext *Ctx = R.Declaration->getDeclContext();
919 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
920 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
921 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
922 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000923 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000924 else
925 R.QualifierIsInformative = false;
926 }
927
Douglas Gregor12e13132010-05-26 22:00:08 +0000928 // Adjust the priority if this result comes from a base class.
929 if (InBaseClass)
930 R.Priority += CCD_InBaseClass;
931
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000932 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000933
Douglas Gregor3cdee122010-08-26 16:36:48 +0000934 if (HasObjectTypeQualifiers)
935 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
936 if (Method->isInstance()) {
937 Qualifiers MethodQuals
938 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
939 if (ObjectTypeQualifiers == MethodQuals)
940 R.Priority += CCD_ObjectQualifierMatch;
941 else if (ObjectTypeQualifiers - MethodQuals) {
942 // The method cannot be invoked, because doing so would drop
943 // qualifiers.
944 return;
945 }
946 }
947
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000948 // Insert this result into the set of results.
949 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000950
951 if (!AsNestedNameSpecifier)
952 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000953}
954
Douglas Gregora4477812010-01-14 16:01:26 +0000955void ResultBuilder::AddResult(Result R) {
956 assert(R.Kind != Result::RK_Declaration &&
957 "Declaration results need more context");
958 Results.push_back(R);
959}
960
Douglas Gregor86d9a522009-09-21 16:56:56 +0000961/// \brief Enter into a new scope.
962void ResultBuilder::EnterNewScope() {
963 ShadowMaps.push_back(ShadowMap());
964}
965
966/// \brief Exit from the current scope.
967void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000968 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
969 EEnd = ShadowMaps.back().end();
970 E != EEnd;
971 ++E)
972 E->second.Destroy();
973
Douglas Gregor86d9a522009-09-21 16:56:56 +0000974 ShadowMaps.pop_back();
975}
976
Douglas Gregor791215b2009-09-21 20:51:25 +0000977/// \brief Determines whether this given declaration will be found by
978/// ordinary name lookup.
979bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000980 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
981
Douglas Gregor791215b2009-09-21 20:51:25 +0000982 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +0000983 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000984 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +0000985 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +0000986 if (isa<ObjCIvarDecl>(ND))
987 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +0000988 }
989
Douglas Gregor791215b2009-09-21 20:51:25 +0000990 return ND->getIdentifierNamespace() & IDNS;
991}
992
Douglas Gregor01dfea02010-01-10 23:08:15 +0000993/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000994/// ordinary name lookup but is not a type name.
995bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
996 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
997 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
998 return false;
999
1000 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001001 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +00001002 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +00001003 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +00001004 if (isa<ObjCIvarDecl>(ND))
1005 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001006 }
1007
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001008 return ND->getIdentifierNamespace() & IDNS;
1009}
1010
Douglas Gregorf9578432010-07-28 21:50:18 +00001011bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
1012 if (!IsOrdinaryNonTypeName(ND))
1013 return 0;
1014
1015 if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
1016 if (VD->getType()->isIntegralOrEnumerationType())
1017 return true;
1018
1019 return false;
1020}
1021
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001022/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001023/// ordinary name lookup.
1024bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001025 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1026
Douglas Gregor01dfea02010-01-10 23:08:15 +00001027 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001028 if (SemaRef.getLangOpts().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001029 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001030
1031 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001032 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1033 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001034}
1035
Douglas Gregor86d9a522009-09-21 16:56:56 +00001036/// \brief Determines whether the given declaration is suitable as the
1037/// start of a C++ nested-name-specifier, e.g., a class or namespace.
1038bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
1039 // Allow us to find class templates, too.
1040 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1041 ND = ClassTemplate->getTemplatedDecl();
1042
1043 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1044}
1045
1046/// \brief Determines whether the given declaration is an enumeration.
1047bool ResultBuilder::IsEnum(NamedDecl *ND) const {
1048 return isa<EnumDecl>(ND);
1049}
1050
1051/// \brief Determines whether the given declaration is a class or struct.
1052bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
1053 // Allow us to find class templates, too.
1054 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1055 ND = ClassTemplate->getTemplatedDecl();
1056
1057 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001058 return RD->getTagKind() == TTK_Class ||
1059 RD->getTagKind() == TTK_Struct;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001060
1061 return false;
1062}
1063
1064/// \brief Determines whether the given declaration is a union.
1065bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1066 // Allow us to find class templates, too.
1067 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1068 ND = ClassTemplate->getTemplatedDecl();
1069
1070 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001071 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001072
1073 return false;
1074}
1075
1076/// \brief Determines whether the given declaration is a namespace.
1077bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1078 return isa<NamespaceDecl>(ND);
1079}
1080
1081/// \brief Determines whether the given declaration is a namespace or
1082/// namespace alias.
1083bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1084 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1085}
1086
Douglas Gregor76282942009-12-11 17:31:05 +00001087/// \brief Determines whether the given declaration is a type.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001088bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregord32b0222010-08-24 01:06:58 +00001089 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1090 ND = Using->getTargetDecl();
1091
1092 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001093}
1094
Douglas Gregor76282942009-12-11 17:31:05 +00001095/// \brief Determines which members of a class should be visible via
1096/// "." or "->". Only value declarations, nested name specifiers, and
1097/// using declarations thereof should show up.
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001098bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor76282942009-12-11 17:31:05 +00001099 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1100 ND = Using->getTargetDecl();
1101
Douglas Gregorce821962009-12-11 18:14:22 +00001102 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1103 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001104}
1105
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001106static bool isObjCReceiverType(ASTContext &C, QualType T) {
1107 T = C.getCanonicalType(T);
1108 switch (T->getTypeClass()) {
1109 case Type::ObjCObject:
1110 case Type::ObjCInterface:
1111 case Type::ObjCObjectPointer:
1112 return true;
1113
1114 case Type::Builtin:
1115 switch (cast<BuiltinType>(T)->getKind()) {
1116 case BuiltinType::ObjCId:
1117 case BuiltinType::ObjCClass:
1118 case BuiltinType::ObjCSel:
1119 return true;
1120
1121 default:
1122 break;
1123 }
1124 return false;
1125
1126 default:
1127 break;
1128 }
1129
David Blaikie4e4d0842012-03-11 07:00:24 +00001130 if (!C.getLangOpts().CPlusPlus)
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001131 return false;
1132
1133 // FIXME: We could perform more analysis here to determine whether a
1134 // particular class type has any conversions to Objective-C types. For now,
1135 // just accept all class types.
1136 return T->isDependentType() || T->isRecordType();
1137}
1138
1139bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1140 QualType T = getDeclUsageType(SemaRef.Context, ND);
1141 if (T.isNull())
1142 return false;
1143
1144 T = SemaRef.Context.getBaseElementType(T);
1145 return isObjCReceiverType(SemaRef.Context, T);
1146}
1147
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001148bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const {
1149 if (IsObjCMessageReceiver(ND))
1150 return true;
1151
1152 VarDecl *Var = dyn_cast<VarDecl>(ND);
1153 if (!Var)
1154 return false;
1155
1156 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1157}
1158
Douglas Gregorfb629412010-08-23 21:17:50 +00001159bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
David Blaikie4e4d0842012-03-11 07:00:24 +00001160 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1161 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregorfb629412010-08-23 21:17:50 +00001162 return false;
1163
1164 QualType T = getDeclUsageType(SemaRef.Context, ND);
1165 if (T.isNull())
1166 return false;
1167
1168 T = SemaRef.Context.getBaseElementType(T);
1169 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1170 T->isObjCIdType() ||
David Blaikie4e4d0842012-03-11 07:00:24 +00001171 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregorfb629412010-08-23 21:17:50 +00001172}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001173
Douglas Gregor52779fb2010-09-23 23:01:17 +00001174bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1175 return false;
1176}
1177
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001178/// \rief Determines whether the given declaration is an Objective-C
1179/// instance variable.
1180bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1181 return isa<ObjCIvarDecl>(ND);
1182}
1183
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001184namespace {
1185 /// \brief Visible declaration consumer that adds a code-completion result
1186 /// for each visible declaration.
1187 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1188 ResultBuilder &Results;
1189 DeclContext *CurContext;
1190
1191 public:
1192 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1193 : Results(Results), CurContext(CurContext) { }
1194
Erik Verbruggend1205962011-10-06 07:27:49 +00001195 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1196 bool InBaseClass) {
1197 bool Accessible = true;
Douglas Gregor17015ef2011-11-03 16:51:37 +00001198 if (Ctx)
1199 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1200
Erik Verbruggend1205962011-10-06 07:27:49 +00001201 ResultBuilder::Result Result(ND, 0, false, Accessible);
1202 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001203 }
1204 };
1205}
1206
Douglas Gregor86d9a522009-09-21 16:56:56 +00001207/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001208static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001209 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001210 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001211 Results.AddResult(Result("short", CCP_Type));
1212 Results.AddResult(Result("long", CCP_Type));
1213 Results.AddResult(Result("signed", CCP_Type));
1214 Results.AddResult(Result("unsigned", CCP_Type));
1215 Results.AddResult(Result("void", CCP_Type));
1216 Results.AddResult(Result("char", CCP_Type));
1217 Results.AddResult(Result("int", CCP_Type));
1218 Results.AddResult(Result("float", CCP_Type));
1219 Results.AddResult(Result("double", CCP_Type));
1220 Results.AddResult(Result("enum", CCP_Type));
1221 Results.AddResult(Result("struct", CCP_Type));
1222 Results.AddResult(Result("union", CCP_Type));
1223 Results.AddResult(Result("const", CCP_Type));
1224 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001225
Douglas Gregor86d9a522009-09-21 16:56:56 +00001226 if (LangOpts.C99) {
1227 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001228 Results.AddResult(Result("_Complex", CCP_Type));
1229 Results.AddResult(Result("_Imaginary", CCP_Type));
1230 Results.AddResult(Result("_Bool", CCP_Type));
1231 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001232 }
1233
Douglas Gregor218937c2011-02-01 19:23:04 +00001234 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001235 if (LangOpts.CPlusPlus) {
1236 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001237 Results.AddResult(Result("bool", CCP_Type +
1238 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001239 Results.AddResult(Result("class", CCP_Type));
1240 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001241
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001242 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001243 Builder.AddTypedTextChunk("typename");
1244 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1245 Builder.AddPlaceholderChunk("qualifier");
1246 Builder.AddTextChunk("::");
1247 Builder.AddPlaceholderChunk("name");
1248 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001249
Douglas Gregor86d9a522009-09-21 16:56:56 +00001250 if (LangOpts.CPlusPlus0x) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001251 Results.AddResult(Result("auto", CCP_Type));
1252 Results.AddResult(Result("char16_t", CCP_Type));
1253 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001254
Douglas Gregor218937c2011-02-01 19:23:04 +00001255 Builder.AddTypedTextChunk("decltype");
1256 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1257 Builder.AddPlaceholderChunk("expression");
1258 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1259 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001260 }
1261 }
1262
1263 // GNU extensions
1264 if (LangOpts.GNUMode) {
1265 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001266 // Results.AddResult(Result("_Decimal32"));
1267 // Results.AddResult(Result("_Decimal64"));
1268 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001269
Douglas Gregor218937c2011-02-01 19:23:04 +00001270 Builder.AddTypedTextChunk("typeof");
1271 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1272 Builder.AddPlaceholderChunk("expression");
1273 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001274
Douglas Gregor218937c2011-02-01 19:23:04 +00001275 Builder.AddTypedTextChunk("typeof");
1276 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1277 Builder.AddPlaceholderChunk("type");
1278 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1279 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001280 }
1281}
1282
John McCallf312b1e2010-08-26 23:41:50 +00001283static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001284 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001285 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001286 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001287 // Note: we don't suggest either "auto" or "register", because both
1288 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1289 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001290 Results.AddResult(Result("extern"));
1291 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001292}
1293
John McCallf312b1e2010-08-26 23:41:50 +00001294static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001295 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001296 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001297 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001298 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001299 case Sema::PCC_Class:
1300 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001301 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001302 Results.AddResult(Result("explicit"));
1303 Results.AddResult(Result("friend"));
1304 Results.AddResult(Result("mutable"));
1305 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001306 }
1307 // Fall through
1308
John McCallf312b1e2010-08-26 23:41:50 +00001309 case Sema::PCC_ObjCInterface:
1310 case Sema::PCC_ObjCImplementation:
1311 case Sema::PCC_Namespace:
1312 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001313 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001314 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001315 break;
1316
John McCallf312b1e2010-08-26 23:41:50 +00001317 case Sema::PCC_ObjCInstanceVariableList:
1318 case Sema::PCC_Expression:
1319 case Sema::PCC_Statement:
1320 case Sema::PCC_ForInit:
1321 case Sema::PCC_Condition:
1322 case Sema::PCC_RecoveryInFunction:
1323 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001324 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001325 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001326 break;
1327 }
1328}
1329
Douglas Gregorbca403c2010-01-13 23:51:12 +00001330static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1331static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1332static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001333 ResultBuilder &Results,
1334 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001335static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001336 ResultBuilder &Results,
1337 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001338static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001339 ResultBuilder &Results,
1340 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001341static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001342
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001343static void AddTypedefResult(ResultBuilder &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001344 CodeCompletionBuilder Builder(Results.getAllocator());
1345 Builder.AddTypedTextChunk("typedef");
1346 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1347 Builder.AddPlaceholderChunk("type");
1348 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1349 Builder.AddPlaceholderChunk("name");
1350 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001351}
1352
John McCallf312b1e2010-08-26 23:41:50 +00001353static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001354 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001355 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001356 case Sema::PCC_Namespace:
1357 case Sema::PCC_Class:
1358 case Sema::PCC_ObjCInstanceVariableList:
1359 case Sema::PCC_Template:
1360 case Sema::PCC_MemberTemplate:
1361 case Sema::PCC_Statement:
1362 case Sema::PCC_RecoveryInFunction:
1363 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001364 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001365 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001366 return true;
1367
John McCallf312b1e2010-08-26 23:41:50 +00001368 case Sema::PCC_Expression:
1369 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001370 return LangOpts.CPlusPlus;
1371
1372 case Sema::PCC_ObjCInterface:
1373 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001374 return false;
1375
John McCallf312b1e2010-08-26 23:41:50 +00001376 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001377 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001378 }
David Blaikie7530c032012-01-17 06:56:22 +00001379
1380 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001381}
1382
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001383static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1384 const Preprocessor &PP) {
1385 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001386 Policy.AnonymousTagLocations = false;
1387 Policy.SuppressStrongLifetime = true;
Douglas Gregor25270b62011-11-03 00:16:13 +00001388 Policy.SuppressUnwrittenScope = true;
Douglas Gregor8ca72082011-10-18 21:20:17 +00001389 return Policy;
1390}
1391
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001392/// \brief Retrieve a printing policy suitable for code completion.
1393static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1394 return getCompletionPrintingPolicy(S.Context, S.PP);
1395}
1396
Douglas Gregor8ca72082011-10-18 21:20:17 +00001397/// \brief Retrieve the string representation of the given type as a string
1398/// that has the appropriate lifetime for code completion.
1399///
1400/// This routine provides a fast path where we provide constant strings for
1401/// common type names.
1402static const char *GetCompletionTypeString(QualType T,
1403 ASTContext &Context,
1404 const PrintingPolicy &Policy,
1405 CodeCompletionAllocator &Allocator) {
1406 if (!T.getLocalQualifiers()) {
1407 // Built-in type names are constant strings.
1408 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
1409 return BT->getName(Policy);
1410
1411 // Anonymous tag types are constant strings.
1412 if (const TagType *TagT = dyn_cast<TagType>(T))
1413 if (TagDecl *Tag = TagT->getDecl())
1414 if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
1415 switch (Tag->getTagKind()) {
1416 case TTK_Struct: return "struct <anonymous>";
1417 case TTK_Class: return "class <anonymous>";
1418 case TTK_Union: return "union <anonymous>";
1419 case TTK_Enum: return "enum <anonymous>";
1420 }
1421 }
1422 }
1423
1424 // Slow path: format the type as a string.
1425 std::string Result;
1426 T.getAsStringInternal(Result, Policy);
1427 return Allocator.CopyString(Result);
1428}
1429
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001430/// \brief Add a completion for "this", if we're in a member function.
1431static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1432 QualType ThisTy = S.getCurrentThisType();
1433 if (ThisTy.isNull())
1434 return;
1435
1436 CodeCompletionAllocator &Allocator = Results.getAllocator();
1437 CodeCompletionBuilder Builder(Allocator);
1438 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1439 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1440 S.Context,
1441 Policy,
1442 Allocator));
1443 Builder.AddTypedTextChunk("this");
1444 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1445}
1446
Douglas Gregor01dfea02010-01-10 23:08:15 +00001447/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001448static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001449 Scope *S,
1450 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001451 ResultBuilder &Results) {
Douglas Gregor8ca72082011-10-18 21:20:17 +00001452 CodeCompletionAllocator &Allocator = Results.getAllocator();
1453 CodeCompletionBuilder Builder(Allocator);
1454 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregor218937c2011-02-01 19:23:04 +00001455
John McCall0a2c5e22010-08-25 06:19:51 +00001456 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001457 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001458 case Sema::PCC_Namespace:
David Blaikie4e4d0842012-03-11 07:00:24 +00001459 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001460 if (Results.includeCodePatterns()) {
1461 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001462 Builder.AddTypedTextChunk("namespace");
1463 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1464 Builder.AddPlaceholderChunk("identifier");
1465 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1466 Builder.AddPlaceholderChunk("declarations");
1467 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1468 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1469 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001470 }
1471
Douglas Gregor01dfea02010-01-10 23:08:15 +00001472 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001473 Builder.AddTypedTextChunk("namespace");
1474 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1475 Builder.AddPlaceholderChunk("name");
1476 Builder.AddChunk(CodeCompletionString::CK_Equal);
1477 Builder.AddPlaceholderChunk("namespace");
1478 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001479
1480 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001481 Builder.AddTypedTextChunk("using");
1482 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1483 Builder.AddTextChunk("namespace");
1484 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1485 Builder.AddPlaceholderChunk("identifier");
1486 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001487
1488 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001489 Builder.AddTypedTextChunk("asm");
1490 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1491 Builder.AddPlaceholderChunk("string-literal");
1492 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1493 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001494
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001495 if (Results.includeCodePatterns()) {
1496 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001497 Builder.AddTypedTextChunk("template");
1498 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1499 Builder.AddPlaceholderChunk("declaration");
1500 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001501 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001502 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001503
David Blaikie4e4d0842012-03-11 07:00:24 +00001504 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001505 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001506
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001507 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001508 // Fall through
1509
John McCallf312b1e2010-08-26 23:41:50 +00001510 case Sema::PCC_Class:
David Blaikie4e4d0842012-03-11 07:00:24 +00001511 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001512 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001513 Builder.AddTypedTextChunk("using");
1514 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1515 Builder.AddPlaceholderChunk("qualifier");
1516 Builder.AddTextChunk("::");
1517 Builder.AddPlaceholderChunk("name");
1518 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001519
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001520 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001521 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001522 Builder.AddTypedTextChunk("using");
1523 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1524 Builder.AddTextChunk("typename");
1525 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1526 Builder.AddPlaceholderChunk("qualifier");
1527 Builder.AddTextChunk("::");
1528 Builder.AddPlaceholderChunk("name");
1529 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001530 }
1531
John McCallf312b1e2010-08-26 23:41:50 +00001532 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001533 AddTypedefResult(Results);
1534
Douglas Gregor01dfea02010-01-10 23:08:15 +00001535 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001536 Builder.AddTypedTextChunk("public");
1537 Builder.AddChunk(CodeCompletionString::CK_Colon);
1538 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001539
1540 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001541 Builder.AddTypedTextChunk("protected");
1542 Builder.AddChunk(CodeCompletionString::CK_Colon);
1543 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001544
1545 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001546 Builder.AddTypedTextChunk("private");
1547 Builder.AddChunk(CodeCompletionString::CK_Colon);
1548 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001549 }
1550 }
1551 // Fall through
1552
John McCallf312b1e2010-08-26 23:41:50 +00001553 case Sema::PCC_Template:
1554 case Sema::PCC_MemberTemplate:
David Blaikie4e4d0842012-03-11 07:00:24 +00001555 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001556 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001557 Builder.AddTypedTextChunk("template");
1558 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1559 Builder.AddPlaceholderChunk("parameters");
1560 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1561 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001562 }
1563
David Blaikie4e4d0842012-03-11 07:00:24 +00001564 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1565 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001566 break;
1567
John McCallf312b1e2010-08-26 23:41:50 +00001568 case Sema::PCC_ObjCInterface:
David Blaikie4e4d0842012-03-11 07:00:24 +00001569 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1570 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1571 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001572 break;
1573
John McCallf312b1e2010-08-26 23:41:50 +00001574 case Sema::PCC_ObjCImplementation:
David Blaikie4e4d0842012-03-11 07:00:24 +00001575 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1576 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1577 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001578 break;
1579
John McCallf312b1e2010-08-26 23:41:50 +00001580 case Sema::PCC_ObjCInstanceVariableList:
David Blaikie4e4d0842012-03-11 07:00:24 +00001581 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001582 break;
1583
John McCallf312b1e2010-08-26 23:41:50 +00001584 case Sema::PCC_RecoveryInFunction:
1585 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001586 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001587
David Blaikie4e4d0842012-03-11 07:00:24 +00001588 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1589 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001590 Builder.AddTypedTextChunk("try");
1591 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1592 Builder.AddPlaceholderChunk("statements");
1593 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1594 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1595 Builder.AddTextChunk("catch");
1596 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1597 Builder.AddPlaceholderChunk("declaration");
1598 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1599 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1600 Builder.AddPlaceholderChunk("statements");
1601 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1602 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1603 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001604 }
David Blaikie4e4d0842012-03-11 07:00:24 +00001605 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001606 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001607
Douglas Gregord8e8a582010-05-25 21:41:55 +00001608 if (Results.includeCodePatterns()) {
1609 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001610 Builder.AddTypedTextChunk("if");
1611 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001612 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001613 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001614 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001615 Builder.AddPlaceholderChunk("expression");
1616 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1617 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1618 Builder.AddPlaceholderChunk("statements");
1619 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1620 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1621 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001622
Douglas Gregord8e8a582010-05-25 21:41:55 +00001623 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001624 Builder.AddTypedTextChunk("switch");
1625 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001626 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001627 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001628 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001629 Builder.AddPlaceholderChunk("expression");
1630 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1631 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1632 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1633 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1634 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001635 }
1636
Douglas Gregor01dfea02010-01-10 23:08:15 +00001637 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001638 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001639 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001640 Builder.AddTypedTextChunk("case");
1641 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1642 Builder.AddPlaceholderChunk("expression");
1643 Builder.AddChunk(CodeCompletionString::CK_Colon);
1644 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001645
1646 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001647 Builder.AddTypedTextChunk("default");
1648 Builder.AddChunk(CodeCompletionString::CK_Colon);
1649 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001650 }
1651
Douglas Gregord8e8a582010-05-25 21:41:55 +00001652 if (Results.includeCodePatterns()) {
1653 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001654 Builder.AddTypedTextChunk("while");
1655 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001656 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001657 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001658 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001659 Builder.AddPlaceholderChunk("expression");
1660 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1661 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1662 Builder.AddPlaceholderChunk("statements");
1663 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1664 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1665 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001666
1667 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001668 Builder.AddTypedTextChunk("do");
1669 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1670 Builder.AddPlaceholderChunk("statements");
1671 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1672 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1673 Builder.AddTextChunk("while");
1674 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1675 Builder.AddPlaceholderChunk("expression");
1676 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1677 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001678
Douglas Gregord8e8a582010-05-25 21:41:55 +00001679 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001680 Builder.AddTypedTextChunk("for");
1681 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001682 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001683 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001684 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001685 Builder.AddPlaceholderChunk("init-expression");
1686 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1687 Builder.AddPlaceholderChunk("condition");
1688 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1689 Builder.AddPlaceholderChunk("inc-expression");
1690 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1691 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1692 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1693 Builder.AddPlaceholderChunk("statements");
1694 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1695 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1696 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001697 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001698
1699 if (S->getContinueParent()) {
1700 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001701 Builder.AddTypedTextChunk("continue");
1702 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001703 }
1704
1705 if (S->getBreakParent()) {
1706 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001707 Builder.AddTypedTextChunk("break");
1708 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001709 }
1710
1711 // "return expression ;" or "return ;", depending on whether we
1712 // know the function is void or not.
1713 bool isVoid = false;
1714 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1715 isVoid = Function->getResultType()->isVoidType();
1716 else if (ObjCMethodDecl *Method
1717 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1718 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001719 else if (SemaRef.getCurBlock() &&
1720 !SemaRef.getCurBlock()->ReturnType.isNull())
1721 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001722 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001723 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001724 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1725 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001726 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001727 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001728
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001729 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001730 Builder.AddTypedTextChunk("goto");
1731 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1732 Builder.AddPlaceholderChunk("label");
1733 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001734
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001735 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001736 Builder.AddTypedTextChunk("using");
1737 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1738 Builder.AddTextChunk("namespace");
1739 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1740 Builder.AddPlaceholderChunk("identifier");
1741 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001742 }
1743
1744 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001745 case Sema::PCC_ForInit:
1746 case Sema::PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00001747 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001748 // Fall through: conditions and statements can have expressions.
1749
Douglas Gregor02688102010-09-14 23:59:36 +00001750 case Sema::PCC_ParenthesizedExpression:
David Blaikie4e4d0842012-03-11 07:00:24 +00001751 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCallf85e1932011-06-15 23:02:42 +00001752 CCC == Sema::PCC_ParenthesizedExpression) {
1753 // (__bridge <type>)<expression>
1754 Builder.AddTypedTextChunk("__bridge");
1755 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1756 Builder.AddPlaceholderChunk("type");
1757 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1758 Builder.AddPlaceholderChunk("expression");
1759 Results.AddResult(Result(Builder.TakeString()));
1760
1761 // (__bridge_transfer <Objective-C type>)<expression>
1762 Builder.AddTypedTextChunk("__bridge_transfer");
1763 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1764 Builder.AddPlaceholderChunk("Objective-C type");
1765 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1766 Builder.AddPlaceholderChunk("expression");
1767 Results.AddResult(Result(Builder.TakeString()));
1768
1769 // (__bridge_retained <CF type>)<expression>
1770 Builder.AddTypedTextChunk("__bridge_retained");
1771 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1772 Builder.AddPlaceholderChunk("CF type");
1773 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1774 Builder.AddPlaceholderChunk("expression");
1775 Results.AddResult(Result(Builder.TakeString()));
1776 }
1777 // Fall through
1778
John McCallf312b1e2010-08-26 23:41:50 +00001779 case Sema::PCC_Expression: {
David Blaikie4e4d0842012-03-11 07:00:24 +00001780 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001781 // 'this', if we're in a non-static member function.
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001782 addThisCompletion(SemaRef, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001783
Douglas Gregor8ca72082011-10-18 21:20:17 +00001784 // true
1785 Builder.AddResultTypeChunk("bool");
1786 Builder.AddTypedTextChunk("true");
1787 Results.AddResult(Result(Builder.TakeString()));
1788
1789 // false
1790 Builder.AddResultTypeChunk("bool");
1791 Builder.AddTypedTextChunk("false");
1792 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001793
David Blaikie4e4d0842012-03-11 07:00:24 +00001794 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001795 // dynamic_cast < type-id > ( expression )
1796 Builder.AddTypedTextChunk("dynamic_cast");
1797 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1798 Builder.AddPlaceholderChunk("type");
1799 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1800 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1801 Builder.AddPlaceholderChunk("expression");
1802 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1803 Results.AddResult(Result(Builder.TakeString()));
1804 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001805
1806 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001807 Builder.AddTypedTextChunk("static_cast");
1808 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1809 Builder.AddPlaceholderChunk("type");
1810 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1811 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1812 Builder.AddPlaceholderChunk("expression");
1813 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1814 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001815
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001816 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001817 Builder.AddTypedTextChunk("reinterpret_cast");
1818 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1819 Builder.AddPlaceholderChunk("type");
1820 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1821 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1822 Builder.AddPlaceholderChunk("expression");
1823 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1824 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001825
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001826 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001827 Builder.AddTypedTextChunk("const_cast");
1828 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1829 Builder.AddPlaceholderChunk("type");
1830 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1831 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1832 Builder.AddPlaceholderChunk("expression");
1833 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1834 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001835
David Blaikie4e4d0842012-03-11 07:00:24 +00001836 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001837 // typeid ( expression-or-type )
Douglas Gregor8ca72082011-10-18 21:20:17 +00001838 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001839 Builder.AddTypedTextChunk("typeid");
1840 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1841 Builder.AddPlaceholderChunk("expression-or-type");
1842 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1843 Results.AddResult(Result(Builder.TakeString()));
1844 }
1845
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001846 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001847 Builder.AddTypedTextChunk("new");
1848 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1849 Builder.AddPlaceholderChunk("type");
1850 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1851 Builder.AddPlaceholderChunk("expressions");
1852 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1853 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001854
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001855 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001856 Builder.AddTypedTextChunk("new");
1857 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1858 Builder.AddPlaceholderChunk("type");
1859 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1860 Builder.AddPlaceholderChunk("size");
1861 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1862 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1863 Builder.AddPlaceholderChunk("expressions");
1864 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1865 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001866
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001867 // delete expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001868 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001869 Builder.AddTypedTextChunk("delete");
1870 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1871 Builder.AddPlaceholderChunk("expression");
1872 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001873
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001874 // delete [] expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001875 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001876 Builder.AddTypedTextChunk("delete");
1877 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1878 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1879 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1880 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1881 Builder.AddPlaceholderChunk("expression");
1882 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001883
David Blaikie4e4d0842012-03-11 07:00:24 +00001884 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001885 // throw expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001886 Builder.AddResultTypeChunk("void");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001887 Builder.AddTypedTextChunk("throw");
1888 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1889 Builder.AddPlaceholderChunk("expression");
1890 Results.AddResult(Result(Builder.TakeString()));
1891 }
Douglas Gregora50216c2011-10-18 16:29:03 +00001892
Douglas Gregor12e13132010-05-26 22:00:08 +00001893 // FIXME: Rethrow?
Douglas Gregora50216c2011-10-18 16:29:03 +00001894
David Blaikie4e4d0842012-03-11 07:00:24 +00001895 if (SemaRef.getLangOpts().CPlusPlus0x) {
Douglas Gregora50216c2011-10-18 16:29:03 +00001896 // nullptr
Douglas Gregor8ca72082011-10-18 21:20:17 +00001897 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001898 Builder.AddTypedTextChunk("nullptr");
1899 Results.AddResult(Result(Builder.TakeString()));
1900
1901 // alignof
Douglas Gregor8ca72082011-10-18 21:20:17 +00001902 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001903 Builder.AddTypedTextChunk("alignof");
1904 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1905 Builder.AddPlaceholderChunk("type");
1906 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1907 Results.AddResult(Result(Builder.TakeString()));
1908
1909 // noexcept
Douglas Gregor8ca72082011-10-18 21:20:17 +00001910 Builder.AddResultTypeChunk("bool");
Douglas Gregora50216c2011-10-18 16:29:03 +00001911 Builder.AddTypedTextChunk("noexcept");
1912 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1913 Builder.AddPlaceholderChunk("expression");
1914 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1915 Results.AddResult(Result(Builder.TakeString()));
1916
1917 // sizeof... expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001918 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001919 Builder.AddTypedTextChunk("sizeof...");
1920 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1921 Builder.AddPlaceholderChunk("parameter-pack");
1922 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1923 Results.AddResult(Result(Builder.TakeString()));
1924 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001925 }
1926
David Blaikie4e4d0842012-03-11 07:00:24 +00001927 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001928 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001929 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1930 // The interface can be NULL.
1931 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregor8ca72082011-10-18 21:20:17 +00001932 if (ID->getSuperClass()) {
1933 std::string SuperType;
1934 SuperType = ID->getSuperClass()->getNameAsString();
1935 if (Method->isInstanceMethod())
1936 SuperType += " *";
1937
1938 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1939 Builder.AddTypedTextChunk("super");
1940 Results.AddResult(Result(Builder.TakeString()));
1941 }
Ted Kremenek681e2562010-05-31 21:43:10 +00001942 }
1943
Douglas Gregorbca403c2010-01-13 23:51:12 +00001944 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001945 }
1946
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001947 // sizeof expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001948 Builder.AddResultTypeChunk("size_t");
Douglas Gregor218937c2011-02-01 19:23:04 +00001949 Builder.AddTypedTextChunk("sizeof");
1950 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1951 Builder.AddPlaceholderChunk("expression-or-type");
1952 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1953 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001954 break;
1955 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001956
John McCallf312b1e2010-08-26 23:41:50 +00001957 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001958 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00001959 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001960 }
1961
David Blaikie4e4d0842012-03-11 07:00:24 +00001962 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
1963 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001964
David Blaikie4e4d0842012-03-11 07:00:24 +00001965 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00001966 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001967}
1968
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001969/// \brief If the given declaration has an associated type, add it as a result
1970/// type chunk.
1971static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00001972 const PrintingPolicy &Policy,
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001973 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00001974 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001975 if (!ND)
1976 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00001977
1978 // Skip constructors and conversion functions, which have their return types
1979 // built into their names.
1980 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
1981 return;
1982
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001983 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00001984 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001985 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
1986 T = Function->getResultType();
1987 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
1988 T = Method->getResultType();
1989 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
1990 T = FunTmpl->getTemplatedDecl()->getResultType();
1991 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
1992 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
1993 else if (isa<UnresolvedUsingValueDecl>(ND)) {
1994 /* Do nothing: ignore unresolved using declarations*/
John McCallf85e1932011-06-15 23:02:42 +00001995 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001996 T = Value->getType();
John McCallf85e1932011-06-15 23:02:42 +00001997 } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001998 T = Property->getType();
1999
2000 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2001 return;
2002
Douglas Gregor8987b232011-09-27 23:30:47 +00002003 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002004 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002005}
2006
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002007static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00002008 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002009 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2010 if (Sentinel->getSentinel() == 0) {
David Blaikie4e4d0842012-03-11 07:00:24 +00002011 if (Context.getLangOpts().ObjC1 &&
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002012 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002013 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002014 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002015 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002016 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002017 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002018 }
2019}
2020
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002021static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2022 std::string Result;
2023 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002024 Result += "in ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002025 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002026 Result += "inout ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002027 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002028 Result += "out ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002029 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002030 Result += "bycopy ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002031 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002032 Result += "byref ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002033 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002034 Result += "oneway ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002035 return Result;
2036}
2037
Douglas Gregor83482d12010-08-24 16:15:59 +00002038static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002039 const PrintingPolicy &Policy,
Douglas Gregoraba48082010-08-29 19:47:46 +00002040 ParmVarDecl *Param,
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002041 bool SuppressName = false,
2042 bool SuppressBlock = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00002043 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2044 if (Param->getType()->isDependentType() ||
2045 !Param->getType()->isBlockPointerType()) {
2046 // The argument for a dependent or non-block parameter is a placeholder
2047 // containing that parameter's type.
2048 std::string Result;
2049
Douglas Gregoraba48082010-08-29 19:47:46 +00002050 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002051 Result = Param->getIdentifier()->getName();
2052
John McCallf85e1932011-06-15 23:02:42 +00002053 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002054
2055 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002056 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2057 + Result + ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00002058 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002059 Result += Param->getIdentifier()->getName();
2060 }
2061 return Result;
2062 }
2063
2064 // The argument for a block pointer parameter is a block literal with
2065 // the appropriate type.
Douglas Gregor830072c2011-02-15 22:37:09 +00002066 FunctionTypeLoc *Block = 0;
2067 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregor83482d12010-08-24 16:15:59 +00002068 TypeLoc TL;
2069 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2070 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2071 while (true) {
2072 // Look through typedefs.
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002073 if (!SuppressBlock) {
2074 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2075 if (TypeSourceInfo *InnerTSInfo
2076 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2077 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2078 continue;
2079 }
2080 }
2081
2082 // Look through qualified types
2083 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2084 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregor83482d12010-08-24 16:15:59 +00002085 continue;
2086 }
2087 }
2088
Douglas Gregor83482d12010-08-24 16:15:59 +00002089 // Try to get the function prototype behind the block pointer type,
2090 // then we're done.
2091 if (BlockPointerTypeLoc *BlockPtr
2092 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00002093 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor830072c2011-02-15 22:37:09 +00002094 Block = dyn_cast<FunctionTypeLoc>(&TL);
2095 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregor83482d12010-08-24 16:15:59 +00002096 }
2097 break;
2098 }
2099 }
2100
2101 if (!Block) {
2102 // We were unable to find a FunctionProtoTypeLoc with parameter names
2103 // for the block; just use the parameter type as a placeholder.
2104 std::string Result;
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002105 if (!ObjCMethodParam && Param->getIdentifier())
2106 Result = Param->getIdentifier()->getName();
2107
John McCallf85e1932011-06-15 23:02:42 +00002108 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002109
2110 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002111 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2112 + Result + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002113 if (Param->getIdentifier())
2114 Result += Param->getIdentifier()->getName();
2115 }
2116
2117 return Result;
2118 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002119
Douglas Gregor83482d12010-08-24 16:15:59 +00002120 // We have the function prototype behind the block pointer type, as it was
2121 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00002122 std::string Result;
2123 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002124 if (!ResultType->isVoidType() || SuppressBlock)
John McCallf85e1932011-06-15 23:02:42 +00002125 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002126
2127 // Format the parameter list.
2128 std::string Params;
Douglas Gregor830072c2011-02-15 22:37:09 +00002129 if (!BlockProto || Block->getNumArgs() == 0) {
2130 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002131 Params = "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00002132 else
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002133 Params = "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00002134 } else {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002135 Params += "(";
Douglas Gregor38276252010-09-08 22:47:51 +00002136 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2137 if (I)
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002138 Params += ", ";
2139 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2140 /*SuppressName=*/false,
2141 /*SuppressBlock=*/true);
Douglas Gregor38276252010-09-08 22:47:51 +00002142
Douglas Gregor830072c2011-02-15 22:37:09 +00002143 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002144 Params += ", ...";
Douglas Gregor38276252010-09-08 22:47:51 +00002145 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002146 Params += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00002147 }
Douglas Gregor38276252010-09-08 22:47:51 +00002148
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002149 if (SuppressBlock) {
2150 // Format as a parameter.
2151 Result = Result + " (^";
2152 if (Param->getIdentifier())
2153 Result += Param->getIdentifier()->getName();
2154 Result += ")";
2155 Result += Params;
2156 } else {
2157 // Format as a block literal argument.
2158 Result = '^' + Result;
2159 Result += Params;
2160
2161 if (Param->getIdentifier())
2162 Result += Param->getIdentifier()->getName();
2163 }
2164
Douglas Gregor83482d12010-08-24 16:15:59 +00002165 return Result;
2166}
2167
Douglas Gregor86d9a522009-09-21 16:56:56 +00002168/// \brief Add function parameter chunks to the given code completion string.
2169static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002170 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002171 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00002172 CodeCompletionBuilder &Result,
2173 unsigned Start = 0,
2174 bool InOptional = false) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002175 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002176
Douglas Gregor218937c2011-02-01 19:23:04 +00002177 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002178 ParmVarDecl *Param = Function->getParamDecl(P);
2179
Douglas Gregor218937c2011-02-01 19:23:04 +00002180 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002181 // When we see an optional default argument, put that argument and
2182 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002183 CodeCompletionBuilder Opt(Result.getAllocator());
2184 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002185 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002186 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregor218937c2011-02-01 19:23:04 +00002187 Result.AddOptionalChunk(Opt.TakeString());
2188 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002189 }
2190
Douglas Gregor218937c2011-02-01 19:23:04 +00002191 if (FirstParameter)
2192 FirstParameter = false;
2193 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002194 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor218937c2011-02-01 19:23:04 +00002195
2196 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002197
2198 // Format the placeholder string.
Douglas Gregor8987b232011-09-27 23:30:47 +00002199 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2200 Param);
Douglas Gregor83482d12010-08-24 16:15:59 +00002201
Douglas Gregore17794f2010-08-31 05:13:43 +00002202 if (Function->isVariadic() && P == N - 1)
2203 PlaceholderStr += ", ...";
2204
Douglas Gregor86d9a522009-09-21 16:56:56 +00002205 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002206 Result.AddPlaceholderChunk(
2207 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002208 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002209
2210 if (const FunctionProtoType *Proto
2211 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002212 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002213 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002214 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002215
Douglas Gregor218937c2011-02-01 19:23:04 +00002216 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002217 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002218}
2219
2220/// \brief Add template parameter chunks to the given code completion string.
2221static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002222 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002223 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002224 CodeCompletionBuilder &Result,
2225 unsigned MaxParameters = 0,
2226 unsigned Start = 0,
2227 bool InDefaultArg = false) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002228 bool FirstParameter = true;
2229
2230 TemplateParameterList *Params = Template->getTemplateParameters();
2231 TemplateParameterList::iterator PEnd = Params->end();
2232 if (MaxParameters)
2233 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002234 for (TemplateParameterList::iterator P = Params->begin() + Start;
2235 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002236 bool HasDefaultArg = false;
2237 std::string PlaceholderStr;
2238 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2239 if (TTP->wasDeclaredWithTypename())
2240 PlaceholderStr = "typename";
2241 else
2242 PlaceholderStr = "class";
2243
2244 if (TTP->getIdentifier()) {
2245 PlaceholderStr += ' ';
2246 PlaceholderStr += TTP->getIdentifier()->getName();
2247 }
2248
2249 HasDefaultArg = TTP->hasDefaultArgument();
2250 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002251 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002252 if (NTTP->getIdentifier())
2253 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCallf85e1932011-06-15 23:02:42 +00002254 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002255 HasDefaultArg = NTTP->hasDefaultArgument();
2256 } else {
2257 assert(isa<TemplateTemplateParmDecl>(*P));
2258 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2259
2260 // Since putting the template argument list into the placeholder would
2261 // be very, very long, we just use an abbreviation.
2262 PlaceholderStr = "template<...> class";
2263 if (TTP->getIdentifier()) {
2264 PlaceholderStr += ' ';
2265 PlaceholderStr += TTP->getIdentifier()->getName();
2266 }
2267
2268 HasDefaultArg = TTP->hasDefaultArgument();
2269 }
2270
Douglas Gregor218937c2011-02-01 19:23:04 +00002271 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002272 // When we see an optional default argument, put that argument and
2273 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002274 CodeCompletionBuilder Opt(Result.getAllocator());
2275 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002276 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002277 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregor218937c2011-02-01 19:23:04 +00002278 P - Params->begin(), true);
2279 Result.AddOptionalChunk(Opt.TakeString());
2280 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002281 }
2282
Douglas Gregor218937c2011-02-01 19:23:04 +00002283 InDefaultArg = false;
2284
Douglas Gregor86d9a522009-09-21 16:56:56 +00002285 if (FirstParameter)
2286 FirstParameter = false;
2287 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002288 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002289
2290 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002291 Result.AddPlaceholderChunk(
2292 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002293 }
2294}
2295
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002296/// \brief Add a qualifier to the given code-completion string, if the
2297/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002298static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002299AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002300 NestedNameSpecifier *Qualifier,
2301 bool QualifierIsInformative,
Douglas Gregor8987b232011-09-27 23:30:47 +00002302 ASTContext &Context,
2303 const PrintingPolicy &Policy) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002304 if (!Qualifier)
2305 return;
2306
2307 std::string PrintedNNS;
2308 {
2309 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor8987b232011-09-27 23:30:47 +00002310 Qualifier->print(OS, Policy);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002311 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002312 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002313 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002314 else
Douglas Gregordae68752011-02-01 22:57:45 +00002315 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002316}
2317
Douglas Gregor218937c2011-02-01 19:23:04 +00002318static void
2319AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2320 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002321 const FunctionProtoType *Proto
2322 = Function->getType()->getAs<FunctionProtoType>();
2323 if (!Proto || !Proto->getTypeQuals())
2324 return;
2325
Douglas Gregora63f6de2011-02-01 21:15:40 +00002326 // FIXME: Add ref-qualifier!
2327
2328 // Handle single qualifiers without copying
2329 if (Proto->getTypeQuals() == Qualifiers::Const) {
2330 Result.AddInformativeChunk(" const");
2331 return;
2332 }
2333
2334 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2335 Result.AddInformativeChunk(" volatile");
2336 return;
2337 }
2338
2339 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2340 Result.AddInformativeChunk(" restrict");
2341 return;
2342 }
2343
2344 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002345 std::string QualsStr;
2346 if (Proto->getTypeQuals() & Qualifiers::Const)
2347 QualsStr += " const";
2348 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2349 QualsStr += " volatile";
2350 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2351 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002352 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002353}
2354
Douglas Gregor6f942b22010-09-21 16:06:22 +00002355/// \brief Add the name of the given declaration
Douglas Gregor8987b232011-09-27 23:30:47 +00002356static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
2357 NamedDecl *ND, CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002358 DeclarationName Name = ND->getDeclName();
2359 if (!Name)
2360 return;
2361
2362 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002363 case DeclarationName::CXXOperatorName: {
2364 const char *OperatorName = 0;
2365 switch (Name.getCXXOverloadedOperator()) {
2366 case OO_None:
2367 case OO_Conditional:
2368 case NUM_OVERLOADED_OPERATORS:
2369 OperatorName = "operator";
2370 break;
2371
2372#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2373 case OO_##Name: OperatorName = "operator" Spelling; break;
2374#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2375#include "clang/Basic/OperatorKinds.def"
2376
2377 case OO_New: OperatorName = "operator new"; break;
2378 case OO_Delete: OperatorName = "operator delete"; break;
2379 case OO_Array_New: OperatorName = "operator new[]"; break;
2380 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2381 case OO_Call: OperatorName = "operator()"; break;
2382 case OO_Subscript: OperatorName = "operator[]"; break;
2383 }
2384 Result.AddTypedTextChunk(OperatorName);
2385 break;
2386 }
2387
Douglas Gregor6f942b22010-09-21 16:06:22 +00002388 case DeclarationName::Identifier:
2389 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002390 case DeclarationName::CXXDestructorName:
2391 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002392 Result.AddTypedTextChunk(
2393 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002394 break;
2395
2396 case DeclarationName::CXXUsingDirective:
2397 case DeclarationName::ObjCZeroArgSelector:
2398 case DeclarationName::ObjCOneArgSelector:
2399 case DeclarationName::ObjCMultiArgSelector:
2400 break;
2401
2402 case DeclarationName::CXXConstructorName: {
2403 CXXRecordDecl *Record = 0;
2404 QualType Ty = Name.getCXXNameType();
2405 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2406 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2407 else if (const InjectedClassNameType *InjectedTy
2408 = Ty->getAs<InjectedClassNameType>())
2409 Record = InjectedTy->getDecl();
2410 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002411 Result.AddTypedTextChunk(
2412 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002413 break;
2414 }
2415
Douglas Gregordae68752011-02-01 22:57:45 +00002416 Result.AddTypedTextChunk(
2417 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002418 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002419 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor8987b232011-09-27 23:30:47 +00002420 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002421 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002422 }
2423 break;
2424 }
2425 }
2426}
2427
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002428CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
2429 CodeCompletionAllocator &Allocator) {
2430 return CreateCodeCompletionString(S.Context, S.PP, Allocator);
2431}
2432
Douglas Gregor86d9a522009-09-21 16:56:56 +00002433/// \brief If possible, create a new code completion string for the given
2434/// result.
2435///
2436/// \returns Either a new, heap-allocated code completion string describing
2437/// how to use this result, or NULL to indicate that the string or name of the
2438/// result is all that is needed.
2439CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002440CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2441 Preprocessor &PP,
Douglas Gregordae68752011-02-01 22:57:45 +00002442 CodeCompletionAllocator &Allocator) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002443 CodeCompletionBuilder Result(Allocator, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002444
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002445 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002446 if (Kind == RK_Pattern) {
2447 Pattern->Priority = Priority;
2448 Pattern->Availability = Availability;
Douglas Gregorba103062012-03-27 23:34:16 +00002449
2450 if (Declaration) {
2451 Result.addParentContext(Declaration->getDeclContext());
2452 Pattern->ParentKind = Result.getParentKind();
2453 Pattern->ParentName = Result.getParentName();
2454 }
2455
Douglas Gregor218937c2011-02-01 19:23:04 +00002456 return Pattern;
2457 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002458
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002459 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002460 Result.AddTypedTextChunk(Keyword);
2461 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002462 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002463
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002464 if (Kind == RK_Macro) {
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002465 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002466 assert(MI && "Not a macro?");
2467
Douglas Gregordae68752011-02-01 22:57:45 +00002468 Result.AddTypedTextChunk(
2469 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002470
2471 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002472 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002473
2474 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002475 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregore4244702011-07-30 08:17:44 +00002476 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002477
2478 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2479 if (MI->isC99Varargs()) {
2480 --AEnd;
2481
2482 if (A == AEnd) {
2483 Result.AddPlaceholderChunk("...");
2484 }
Douglas Gregore4244702011-07-30 08:17:44 +00002485 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002486
Douglas Gregore4244702011-07-30 08:17:44 +00002487 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002488 if (A != MI->arg_begin())
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002489 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002490
2491 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002492 SmallString<32> Arg = (*A)->getName();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002493 if (MI->isC99Varargs())
2494 Arg += ", ...";
2495 else
2496 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002497 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002498 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002499 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002500
2501 // Non-variadic macros are simple.
2502 Result.AddPlaceholderChunk(
2503 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002504 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002505 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002506 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002507 }
2508
Douglas Gregord8e8a582010-05-25 21:41:55 +00002509 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002510 NamedDecl *ND = Declaration;
Douglas Gregorba103062012-03-27 23:34:16 +00002511 Result.addParentContext(ND->getDeclContext());
2512
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002513 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002514 Result.AddTypedTextChunk(
2515 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002516 Result.AddTextChunk("::");
2517 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002518 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002519
2520 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2521 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2522 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2523 }
2524 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002525
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002526 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002527
Douglas Gregor86d9a522009-09-21 16:56:56 +00002528 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002529 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002530 Ctx, Policy);
2531 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002532 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002533 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002534 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002535 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002536 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002537 }
2538
2539 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002540 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002541 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002542 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002543 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002544
Douglas Gregor86d9a522009-09-21 16:56:56 +00002545 // Figure out which template parameters are deduced (or have default
2546 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002547 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002548 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002549 unsigned LastDeducibleArgument;
2550 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2551 --LastDeducibleArgument) {
2552 if (!Deduced[LastDeducibleArgument - 1]) {
2553 // C++0x: Figure out if the template argument has a default. If so,
2554 // the user doesn't need to type this argument.
2555 // FIXME: We need to abstract template parameters better!
2556 bool HasDefaultArg = false;
2557 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002558 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002559 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2560 HasDefaultArg = TTP->hasDefaultArgument();
2561 else if (NonTypeTemplateParmDecl *NTTP
2562 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2563 HasDefaultArg = NTTP->hasDefaultArgument();
2564 else {
2565 assert(isa<TemplateTemplateParmDecl>(Param));
2566 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002567 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002568 }
2569
2570 if (!HasDefaultArg)
2571 break;
2572 }
2573 }
2574
2575 if (LastDeducibleArgument) {
2576 // Some of the function template arguments cannot be deduced from a
2577 // function call, so we introduce an explicit template argument list
2578 // containing all of the arguments up to the first deducible argument.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002579 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002580 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002581 LastDeducibleArgument);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002582 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002583 }
2584
2585 // Add the function parameters
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002586 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002587 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002588 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002589 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002590 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002591 }
2592
2593 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002594 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002595 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002596 Result.AddTypedTextChunk(
2597 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002598 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002599 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002600 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor218937c2011-02-01 19:23:04 +00002601 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002602 }
2603
Douglas Gregor9630eb62009-11-17 16:44:22 +00002604 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002605 Selector Sel = Method->getSelector();
2606 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002607 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002608 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002609 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002610 }
2611
Douglas Gregor813d8342011-02-18 22:29:55 +00002612 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002613 SelName += ':';
2614 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002615 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002616 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002617 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002618
2619 // If there is only one parameter, and we're past it, add an empty
2620 // typed-text chunk since there is nothing to type.
2621 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002622 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002623 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002624 unsigned Idx = 0;
2625 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2626 PEnd = Method->param_end();
2627 P != PEnd; (void)++P, ++Idx) {
2628 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002629 std::string Keyword;
2630 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002631 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002632 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002633 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002634 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002635 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002636 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002637 else
Douglas Gregordae68752011-02-01 22:57:45 +00002638 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002639 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002640
2641 // If we're before the starting parameter, skip the placeholder.
2642 if (Idx < StartParameter)
2643 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002644
2645 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002646
2647 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002648 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002649 else {
John McCallf85e1932011-06-15 23:02:42 +00002650 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002651 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2652 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002653 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002654 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002655 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002656 }
2657
Douglas Gregore17794f2010-08-31 05:13:43 +00002658 if (Method->isVariadic() && (P + 1) == PEnd)
2659 Arg += ", ...";
2660
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002661 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002662 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002663 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002664 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002665 else
Douglas Gregordae68752011-02-01 22:57:45 +00002666 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002667 }
2668
Douglas Gregor2a17af02009-12-23 00:21:46 +00002669 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002670 if (Method->param_size() == 0) {
2671 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002672 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002673 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002674 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002675 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002676 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002677 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002678
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002679 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002680 }
2681
Douglas Gregor218937c2011-02-01 19:23:04 +00002682 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002683 }
2684
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002685 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002686 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002687 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002688
Douglas Gregordae68752011-02-01 22:57:45 +00002689 Result.AddTypedTextChunk(
2690 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002691 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002692}
2693
Douglas Gregor86d802e2009-09-23 00:34:09 +00002694CodeCompletionString *
2695CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2696 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002697 Sema &S,
Douglas Gregordae68752011-02-01 22:57:45 +00002698 CodeCompletionAllocator &Allocator) const {
Douglas Gregor8987b232011-09-27 23:30:47 +00002699 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002700
Douglas Gregor218937c2011-02-01 19:23:04 +00002701 // FIXME: Set priority, availability appropriately.
2702 CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002703 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002704 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002705 const FunctionProtoType *Proto
2706 = dyn_cast<FunctionProtoType>(getFunctionType());
2707 if (!FDecl && !Proto) {
2708 // Function without a prototype. Just give the return type and a
2709 // highlighted ellipsis.
2710 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002711 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002712 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002713 Result.getAllocator()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002714 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2715 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2716 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002717 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002718 }
2719
2720 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002721 Result.AddTextChunk(
2722 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002723 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002724 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002725 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002726 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002727
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002728 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002729 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2730 for (unsigned I = 0; I != NumParams; ++I) {
2731 if (I)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002732 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002733
2734 std::string ArgString;
2735 QualType ArgType;
2736
2737 if (FDecl) {
2738 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2739 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2740 } else {
2741 ArgType = Proto->getArgType(I);
2742 }
2743
John McCallf85e1932011-06-15 23:02:42 +00002744 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002745
2746 if (I == CurrentArg)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002747 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2748 Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002749 else
Douglas Gregordae68752011-02-01 22:57:45 +00002750 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002751 }
2752
2753 if (Proto && Proto->isVariadic()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002754 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002755 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002756 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002757 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002758 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002759 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002760 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002761
Douglas Gregor218937c2011-02-01 19:23:04 +00002762 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002763}
2764
Chris Lattner5f9e2722011-07-23 10:55:15 +00002765unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002766 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002767 bool PreferredTypeIsPointer) {
2768 unsigned Priority = CCP_Macro;
2769
Douglas Gregorb05496d2010-09-20 21:11:48 +00002770 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2771 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2772 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002773 Priority = CCP_Constant;
2774 if (PreferredTypeIsPointer)
2775 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002776 }
2777 // Treat "YES", "NO", "true", and "false" as constants.
2778 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2779 MacroName.equals("true") || MacroName.equals("false"))
2780 Priority = CCP_Constant;
2781 // Treat "bool" as a type.
2782 else if (MacroName.equals("bool"))
2783 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2784
Douglas Gregor1827e102010-08-16 16:18:59 +00002785
2786 return Priority;
2787}
2788
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002789CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2790 if (!D)
2791 return CXCursor_UnexposedDecl;
2792
2793 switch (D->getKind()) {
2794 case Decl::Enum: return CXCursor_EnumDecl;
2795 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2796 case Decl::Field: return CXCursor_FieldDecl;
2797 case Decl::Function:
2798 return CXCursor_FunctionDecl;
2799 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2800 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002801 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002802
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002803 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002804 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2805 case Decl::ObjCMethod:
2806 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2807 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2808 case Decl::CXXMethod: return CXCursor_CXXMethod;
2809 case Decl::CXXConstructor: return CXCursor_Constructor;
2810 case Decl::CXXDestructor: return CXCursor_Destructor;
2811 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2812 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002813 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002814 case Decl::ParmVar: return CXCursor_ParmDecl;
2815 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002816 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002817 case Decl::Var: return CXCursor_VarDecl;
2818 case Decl::Namespace: return CXCursor_Namespace;
2819 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2820 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2821 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2822 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2823 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2824 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002825 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002826 case Decl::ClassTemplatePartialSpecialization:
2827 return CXCursor_ClassTemplatePartialSpecialization;
2828 case Decl::UsingDirective: return CXCursor_UsingDirective;
2829
2830 case Decl::Using:
2831 case Decl::UnresolvedUsingValue:
2832 case Decl::UnresolvedUsingTypename:
2833 return CXCursor_UsingDeclaration;
2834
Douglas Gregor352697a2011-06-03 23:08:58 +00002835 case Decl::ObjCPropertyImpl:
2836 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2837 case ObjCPropertyImplDecl::Dynamic:
2838 return CXCursor_ObjCDynamicDecl;
2839
2840 case ObjCPropertyImplDecl::Synthesize:
2841 return CXCursor_ObjCSynthesizeDecl;
2842 }
Douglas Gregor352697a2011-06-03 23:08:58 +00002843
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002844 default:
2845 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2846 switch (TD->getTagKind()) {
2847 case TTK_Struct: return CXCursor_StructDecl;
2848 case TTK_Class: return CXCursor_ClassDecl;
2849 case TTK_Union: return CXCursor_UnionDecl;
2850 case TTK_Enum: return CXCursor_EnumDecl;
2851 }
2852 }
2853 }
2854
2855 return CXCursor_UnexposedDecl;
2856}
2857
Douglas Gregor590c7d52010-07-08 20:55:51 +00002858static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2859 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002860 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002861
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002862 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002863
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002864 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2865 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002866 M != MEnd; ++M) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002867 Results.AddResult(Result(M->first,
2868 getMacroUsagePriority(M->first->getName(),
David Blaikie4e4d0842012-03-11 07:00:24 +00002869 PP.getLangOpts(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002870 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002871 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002872
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002873 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002874
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002875}
2876
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002877static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2878 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002879 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002880
2881 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002882
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002883 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2884 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2885 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2886 Results.AddResult(Result("__func__", CCP_Constant));
2887 Results.ExitScope();
2888}
2889
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002890static void HandleCodeCompleteResults(Sema *S,
2891 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002892 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002893 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002894 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002895 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002896 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002897}
2898
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002899static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2900 Sema::ParserCompletionContext PCC) {
2901 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002902 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002903 return CodeCompletionContext::CCC_TopLevel;
2904
John McCallf312b1e2010-08-26 23:41:50 +00002905 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002906 return CodeCompletionContext::CCC_ClassStructUnion;
2907
John McCallf312b1e2010-08-26 23:41:50 +00002908 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002909 return CodeCompletionContext::CCC_ObjCInterface;
2910
John McCallf312b1e2010-08-26 23:41:50 +00002911 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002912 return CodeCompletionContext::CCC_ObjCImplementation;
2913
John McCallf312b1e2010-08-26 23:41:50 +00002914 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002915 return CodeCompletionContext::CCC_ObjCIvarList;
2916
John McCallf312b1e2010-08-26 23:41:50 +00002917 case Sema::PCC_Template:
2918 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002919 if (S.CurContext->isFileContext())
2920 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002921 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002922 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002923 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002924
John McCallf312b1e2010-08-26 23:41:50 +00002925 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002926 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002927
John McCallf312b1e2010-08-26 23:41:50 +00002928 case Sema::PCC_ForInit:
David Blaikie4e4d0842012-03-11 07:00:24 +00002929 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2930 S.getLangOpts().ObjC1)
Douglas Gregora5450a02010-10-18 22:01:46 +00002931 return CodeCompletionContext::CCC_ParenthesizedExpression;
2932 else
2933 return CodeCompletionContext::CCC_Expression;
2934
2935 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002936 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002937 return CodeCompletionContext::CCC_Expression;
2938
John McCallf312b1e2010-08-26 23:41:50 +00002939 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002940 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002941
John McCallf312b1e2010-08-26 23:41:50 +00002942 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002943 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002944
2945 case Sema::PCC_ParenthesizedExpression:
2946 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002947
2948 case Sema::PCC_LocalDeclarationSpecifiers:
2949 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002950 }
David Blaikie7530c032012-01-17 06:56:22 +00002951
2952 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002953}
2954
Douglas Gregorf6961522010-08-27 21:18:54 +00002955/// \brief If we're in a C++ virtual member function, add completion results
2956/// that invoke the functions we override, since it's common to invoke the
2957/// overridden function as well as adding new functionality.
2958///
2959/// \param S The semantic analysis object for which we are generating results.
2960///
2961/// \param InContext This context in which the nested-name-specifier preceding
2962/// the code-completion point
2963static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2964 ResultBuilder &Results) {
2965 // Look through blocks.
2966 DeclContext *CurContext = S.CurContext;
2967 while (isa<BlockDecl>(CurContext))
2968 CurContext = CurContext->getParent();
2969
2970
2971 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2972 if (!Method || !Method->isVirtual())
2973 return;
2974
2975 // We need to have names for all of the parameters, if we're going to
2976 // generate a forwarding call.
2977 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2978 PEnd = Method->param_end();
2979 P != PEnd;
2980 ++P) {
2981 if (!(*P)->getDeclName())
2982 return;
2983 }
2984
Douglas Gregor8987b232011-09-27 23:30:47 +00002985 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00002986 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
2987 MEnd = Method->end_overridden_methods();
2988 M != MEnd; ++M) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002989 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf6961522010-08-27 21:18:54 +00002990 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
2991 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
2992 continue;
2993
2994 // If we need a nested-name-specifier, add one now.
2995 if (!InContext) {
2996 NestedNameSpecifier *NNS
2997 = getRequiredQualification(S.Context, CurContext,
2998 Overridden->getDeclContext());
2999 if (NNS) {
3000 std::string Str;
3001 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00003002 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00003003 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003004 }
3005 } else if (!InContext->Equals(Overridden->getDeclContext()))
3006 continue;
3007
Douglas Gregordae68752011-02-01 22:57:45 +00003008 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003009 Overridden->getNameAsString()));
3010 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00003011 bool FirstParam = true;
3012 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3013 PEnd = Method->param_end();
3014 P != PEnd; ++P) {
3015 if (FirstParam)
3016 FirstParam = false;
3017 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003018 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003019
Douglas Gregordae68752011-02-01 22:57:45 +00003020 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003021 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003022 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003023 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3024 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003025 CCP_SuperCompletion,
Douglas Gregorba103062012-03-27 23:34:16 +00003026 CXCursor_CXXMethod,
3027 CXAvailability_Available,
3028 Overridden));
Douglas Gregorf6961522010-08-27 21:18:54 +00003029 Results.Ignore(Overridden);
3030 }
3031}
3032
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003033void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3034 ModuleIdPath Path) {
3035 typedef CodeCompletionResult Result;
3036 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3037 CodeCompletionContext::CCC_Other);
3038 Results.EnterNewScope();
3039
3040 CodeCompletionAllocator &Allocator = Results.getAllocator();
3041 CodeCompletionBuilder Builder(Allocator);
3042 typedef CodeCompletionResult Result;
3043 if (Path.empty()) {
3044 // Enumerate all top-level modules.
3045 llvm::SmallVector<Module *, 8> Modules;
3046 PP.getHeaderSearchInfo().collectAllModules(Modules);
3047 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3048 Builder.AddTypedTextChunk(
3049 Builder.getAllocator().CopyString(Modules[I]->Name));
3050 Results.AddResult(Result(Builder.TakeString(),
3051 CCP_Declaration,
3052 CXCursor_NotImplemented,
3053 Modules[I]->isAvailable()
3054 ? CXAvailability_Available
3055 : CXAvailability_NotAvailable));
3056 }
3057 } else {
3058 // Load the named module.
3059 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3060 Module::AllVisible,
3061 /*IsInclusionDirective=*/false);
3062 // Enumerate submodules.
3063 if (Mod) {
3064 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3065 SubEnd = Mod->submodule_end();
3066 Sub != SubEnd; ++Sub) {
3067
3068 Builder.AddTypedTextChunk(
3069 Builder.getAllocator().CopyString((*Sub)->Name));
3070 Results.AddResult(Result(Builder.TakeString(),
3071 CCP_Declaration,
3072 CXCursor_NotImplemented,
3073 (*Sub)->isAvailable()
3074 ? CXAvailability_Available
3075 : CXAvailability_NotAvailable));
3076 }
3077 }
3078 }
3079 Results.ExitScope();
3080 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3081 Results.data(),Results.size());
3082}
3083
Douglas Gregor01dfea02010-01-10 23:08:15 +00003084void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003085 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00003086 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003087 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003088 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003089 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003090
Douglas Gregor01dfea02010-01-10 23:08:15 +00003091 // Determine how to filter results, e.g., so that the names of
3092 // values (functions, enumerators, function templates, etc.) are
3093 // only allowed where we can have an expression.
3094 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003095 case PCC_Namespace:
3096 case PCC_Class:
3097 case PCC_ObjCInterface:
3098 case PCC_ObjCImplementation:
3099 case PCC_ObjCInstanceVariableList:
3100 case PCC_Template:
3101 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003102 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003103 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003104 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3105 break;
3106
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003107 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003108 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003109 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003110 case PCC_ForInit:
3111 case PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00003112 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003113 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3114 else
3115 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003116
David Blaikie4e4d0842012-03-11 07:00:24 +00003117 if (getLangOpts().CPlusPlus)
Douglas Gregorf6961522010-08-27 21:18:54 +00003118 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003119 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003120
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003121 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003122 // Unfiltered
3123 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003124 }
3125
Douglas Gregor3cdee122010-08-26 16:36:48 +00003126 // If we are in a C++ non-static member function, check the qualifiers on
3127 // the member function to filter/prioritize the results list.
3128 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3129 if (CurMethod->isInstance())
3130 Results.setObjectTypeQualifiers(
3131 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3132
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003133 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003134 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3135 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003136
Douglas Gregorbca403c2010-01-13 23:51:12 +00003137 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003138 Results.ExitScope();
3139
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003140 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003141 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003142 case PCC_Expression:
3143 case PCC_Statement:
3144 case PCC_RecoveryInFunction:
3145 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003146 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor72db1082010-08-24 01:11:00 +00003147 break;
3148
3149 case PCC_Namespace:
3150 case PCC_Class:
3151 case PCC_ObjCInterface:
3152 case PCC_ObjCImplementation:
3153 case PCC_ObjCInstanceVariableList:
3154 case PCC_Template:
3155 case PCC_MemberTemplate:
3156 case PCC_ForInit:
3157 case PCC_Condition:
3158 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003159 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003160 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003161 }
3162
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003163 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003164 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003165
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003166 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003167 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003168}
3169
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003170static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3171 ParsedType Receiver,
3172 IdentifierInfo **SelIdents,
3173 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003174 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003175 bool IsSuper,
3176 ResultBuilder &Results);
3177
3178void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3179 bool AllowNonIdentifiers,
3180 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003181 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003182 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003183 AllowNestedNameSpecifiers
3184 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3185 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003186 Results.EnterNewScope();
3187
3188 // Type qualifiers can come after names.
3189 Results.AddResult(Result("const"));
3190 Results.AddResult(Result("volatile"));
David Blaikie4e4d0842012-03-11 07:00:24 +00003191 if (getLangOpts().C99)
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003192 Results.AddResult(Result("restrict"));
3193
David Blaikie4e4d0842012-03-11 07:00:24 +00003194 if (getLangOpts().CPlusPlus) {
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003195 if (AllowNonIdentifiers) {
3196 Results.AddResult(Result("operator"));
3197 }
3198
3199 // Add nested-name-specifiers.
3200 if (AllowNestedNameSpecifiers) {
3201 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003202 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003203 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3204 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3205 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003206 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003207 }
3208 }
3209 Results.ExitScope();
3210
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003211 // If we're in a context where we might have an expression (rather than a
3212 // declaration), and what we've seen so far is an Objective-C type that could
3213 // be a receiver of a class message, this may be a class message send with
3214 // the initial opening bracket '[' missing. Add appropriate completions.
3215 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3216 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3217 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3218 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3219 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3220 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3221 DS.getTypeQualifiers() == 0 &&
3222 S &&
3223 (S->getFlags() & Scope::DeclScope) != 0 &&
3224 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3225 Scope::FunctionPrototypeScope |
3226 Scope::AtCatchScope)) == 0) {
3227 ParsedType T = DS.getRepAsType();
3228 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003229 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003230 }
3231
Douglas Gregor4497dd42010-08-24 04:59:56 +00003232 // Note that we intentionally suppress macro results here, since we do not
3233 // encourage using macros to produce the names of entities.
3234
Douglas Gregor52779fb2010-09-23 23:01:17 +00003235 HandleCodeCompleteResults(this, CodeCompleter,
3236 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003237 Results.data(), Results.size());
3238}
3239
Douglas Gregorfb629412010-08-23 21:17:50 +00003240struct Sema::CodeCompleteExpressionData {
3241 CodeCompleteExpressionData(QualType PreferredType = QualType())
3242 : PreferredType(PreferredType), IntegralConstantExpression(false),
3243 ObjCCollection(false) { }
3244
3245 QualType PreferredType;
3246 bool IntegralConstantExpression;
3247 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003248 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003249};
3250
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003251/// \brief Perform code-completion in an expression context when we know what
3252/// type we're looking for.
Douglas Gregorf9578432010-07-28 21:50:18 +00003253///
3254/// \param IntegralConstantExpression Only permit integral constant
3255/// expressions.
Douglas Gregorfb629412010-08-23 21:17:50 +00003256void Sema::CodeCompleteExpression(Scope *S,
3257 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00003258 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003259 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3260 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003261 if (Data.ObjCCollection)
3262 Results.setFilter(&ResultBuilder::IsObjCCollection);
3263 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003264 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikie4e4d0842012-03-11 07:00:24 +00003265 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003266 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3267 else
3268 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003269
3270 if (!Data.PreferredType.isNull())
3271 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3272
3273 // Ignore any declarations that we were told that we don't care about.
3274 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3275 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003276
3277 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003278 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3279 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003280
3281 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003282 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003283 Results.ExitScope();
3284
Douglas Gregor590c7d52010-07-08 20:55:51 +00003285 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003286 if (!Data.PreferredType.isNull())
3287 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3288 || Data.PreferredType->isMemberPointerType()
3289 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003290
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003291 if (S->getFnParent() &&
3292 !Data.ObjCCollection &&
3293 !Data.IntegralConstantExpression)
David Blaikie4e4d0842012-03-11 07:00:24 +00003294 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003295
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003296 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003297 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003298 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003299 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3300 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003301 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003302}
3303
Douglas Gregorac5fd842010-09-18 01:28:11 +00003304void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3305 if (E.isInvalid())
3306 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikie4e4d0842012-03-11 07:00:24 +00003307 else if (getLangOpts().ObjC1)
Douglas Gregorac5fd842010-09-18 01:28:11 +00003308 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003309}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003310
Douglas Gregor73449212010-12-09 23:01:55 +00003311/// \brief The set of properties that have already been added, referenced by
3312/// property name.
3313typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3314
Douglas Gregor95ac6552009-11-18 01:29:26 +00003315static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003316 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003317 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003318 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003319 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003320 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003321 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003322
3323 // Add properties in this container.
3324 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3325 PEnd = Container->prop_end();
3326 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003327 ++P) {
3328 if (AddedProperties.insert(P->getIdentifier()))
3329 Results.MaybeAddResult(Result(*P, 0), CurContext);
3330 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003331
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003332 // Add nullary methods
3333 if (AllowNullaryMethods) {
3334 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003335 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003336 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3337 MEnd = Container->meth_end();
3338 M != MEnd; ++M) {
3339 if (M->getSelector().isUnarySelector())
3340 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3341 if (AddedProperties.insert(Name)) {
3342 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor8987b232011-09-27 23:30:47 +00003343 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003344 Builder.AddTypedTextChunk(
3345 Results.getAllocator().CopyString(Name->getName()));
3346
Douglas Gregorba103062012-03-27 23:34:16 +00003347 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
3348 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003349 CurContext);
3350 }
3351 }
3352 }
3353
3354
Douglas Gregor95ac6552009-11-18 01:29:26 +00003355 // Add properties in referenced protocols.
3356 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3357 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3358 PEnd = Protocol->protocol_end();
3359 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003360 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3361 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003362 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003363 if (AllowCategories) {
3364 // Look through categories.
3365 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3366 Category; Category = Category->getNextClassCategory())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003367 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3368 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003369 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003370
3371 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003372 for (ObjCInterfaceDecl::all_protocol_iterator
3373 I = IFace->all_referenced_protocol_begin(),
3374 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003375 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3376 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003377
3378 // Look in the superclass.
3379 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003380 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3381 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003382 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003383 } else if (const ObjCCategoryDecl *Category
3384 = dyn_cast<ObjCCategoryDecl>(Container)) {
3385 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003386 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3387 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003388 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003389 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3390 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003391 }
3392}
3393
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003394void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003395 SourceLocation OpLoc,
3396 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003397 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003398 return;
3399
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003400 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3401 if (ConvertedBase.isInvalid())
3402 return;
3403 Base = ConvertedBase.get();
3404
John McCall0a2c5e22010-08-25 06:19:51 +00003405 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003406
Douglas Gregor81b747b2009-09-17 21:32:03 +00003407 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003408
3409 if (IsArrow) {
3410 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3411 BaseType = Ptr->getPointeeType();
3412 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003413 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003414 else
3415 return;
3416 }
3417
Douglas Gregor3da626b2011-07-07 16:03:39 +00003418 enum CodeCompletionContext::Kind contextKind;
3419
3420 if (IsArrow) {
3421 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3422 }
3423 else {
3424 if (BaseType->isObjCObjectPointerType() ||
3425 BaseType->isObjCObjectOrInterfaceType()) {
3426 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3427 }
3428 else {
3429 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3430 }
3431 }
3432
Douglas Gregor218937c2011-02-01 19:23:04 +00003433 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003434 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003435 BaseType),
3436 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003437 Results.EnterNewScope();
3438 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003439 // Indicate that we are performing a member access, and the cv-qualifiers
3440 // for the base object type.
3441 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3442
Douglas Gregor95ac6552009-11-18 01:29:26 +00003443 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003444 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003445 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003446 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3447 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003448
David Blaikie4e4d0842012-03-11 07:00:24 +00003449 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003450 if (!Results.empty()) {
3451 // The "template" keyword can follow "->" or "." in the grammar.
3452 // However, we only want to suggest the template keyword if something
3453 // is dependent.
3454 bool IsDependent = BaseType->isDependentType();
3455 if (!IsDependent) {
3456 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3457 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3458 IsDependent = Ctx->isDependentContext();
3459 break;
3460 }
3461 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003462
Douglas Gregor95ac6552009-11-18 01:29:26 +00003463 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003464 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003465 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003466 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003467 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3468 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003469 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003470
3471 // Add property results based on our interface.
3472 const ObjCObjectPointerType *ObjCPtr
3473 = BaseType->getAsObjCInterfacePointerType();
3474 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003475 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3476 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003477 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003478
3479 // Add properties from the protocols in a qualified interface.
3480 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3481 E = ObjCPtr->qual_end();
3482 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003483 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3484 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003485 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003486 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003487 // Objective-C instance variable access.
3488 ObjCInterfaceDecl *Class = 0;
3489 if (const ObjCObjectPointerType *ObjCPtr
3490 = BaseType->getAs<ObjCObjectPointerType>())
3491 Class = ObjCPtr->getInterfaceDecl();
3492 else
John McCallc12c5bb2010-05-15 11:32:37 +00003493 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003494
3495 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003496 if (Class) {
3497 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3498 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003499 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3500 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003501 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003502 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003503
3504 // FIXME: How do we cope with isa?
3505
3506 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003507
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003508 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003509 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003510 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003511 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003512}
3513
Douglas Gregor374929f2009-09-18 15:37:17 +00003514void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3515 if (!CodeCompleter)
3516 return;
3517
John McCall0a2c5e22010-08-25 06:19:51 +00003518 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003519 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003520 enum CodeCompletionContext::Kind ContextKind
3521 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003522 switch ((DeclSpec::TST)TagSpec) {
3523 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003524 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003525 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003526 break;
3527
3528 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003529 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003530 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003531 break;
3532
3533 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003534 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003535 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003536 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003537 break;
3538
3539 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003540 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003541 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003542
Douglas Gregor218937c2011-02-01 19:23:04 +00003543 ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003544 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003545
3546 // First pass: look for tags.
3547 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003548 LookupVisibleDecls(S, LookupTagName, Consumer,
3549 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003550
Douglas Gregor8071e422010-08-15 06:18:01 +00003551 if (CodeCompleter->includeGlobals()) {
3552 // Second pass: look for nested name specifiers.
3553 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3554 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3555 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003556
Douglas Gregor52779fb2010-09-23 23:01:17 +00003557 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003558 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003559}
3560
Douglas Gregor1a480c42010-08-27 17:35:51 +00003561void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003562 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3563 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003564 Results.EnterNewScope();
3565 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3566 Results.AddResult("const");
3567 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3568 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003569 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003570 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3571 Results.AddResult("restrict");
3572 Results.ExitScope();
3573 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003574 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003575 Results.data(), Results.size());
3576}
3577
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003578void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003579 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003580 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003581
John McCall781472f2010-08-25 08:40:02 +00003582 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003583 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3584 if (!type->isEnumeralType()) {
3585 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003586 Data.IntegralConstantExpression = true;
3587 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003588 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003589 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003590
3591 // Code-complete the cases of a switch statement over an enumeration type
3592 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003593 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003594
3595 // Determine which enumerators we have already seen in the switch statement.
3596 // FIXME: Ideally, we would also be able to look *past* the code-completion
3597 // token, in case we are code-completing in the middle of the switch and not
3598 // at the end. However, we aren't able to do so at the moment.
3599 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003600 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003601 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3602 SC = SC->getNextSwitchCase()) {
3603 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3604 if (!Case)
3605 continue;
3606
3607 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3608 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3609 if (EnumConstantDecl *Enumerator
3610 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3611 // We look into the AST of the case statement to determine which
3612 // enumerator was named. Alternatively, we could compute the value of
3613 // the integral constant expression, then compare it against the
3614 // values of each enumerator. However, value-based approach would not
3615 // work as well with C++ templates where enumerators declared within a
3616 // template are type- and value-dependent.
3617 EnumeratorsSeen.insert(Enumerator);
3618
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003619 // If this is a qualified-id, keep track of the nested-name-specifier
3620 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003621 //
3622 // switch (TagD.getKind()) {
3623 // case TagDecl::TK_enum:
3624 // break;
3625 // case XXX
3626 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003627 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003628 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3629 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003630 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003631 }
3632 }
3633
David Blaikie4e4d0842012-03-11 07:00:24 +00003634 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003635 // If there are no prior enumerators in C++, check whether we have to
3636 // qualify the names of the enumerators that we suggest, because they
3637 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003638 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003639 }
3640
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003641 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003642 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3643 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003644 Results.EnterNewScope();
3645 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3646 EEnd = Enum->enumerator_end();
3647 E != EEnd; ++E) {
3648 if (EnumeratorsSeen.count(*E))
3649 continue;
3650
Douglas Gregor5c722c702011-02-18 23:30:37 +00003651 CodeCompletionResult R(*E, Qualifier);
3652 R.Priority = CCP_EnumInCase;
3653 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003654 }
3655 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003656
Douglas Gregor3da626b2011-07-07 16:03:39 +00003657 //We need to make sure we're setting the right context,
3658 //so only say we include macros if the code completer says we do
3659 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3660 if (CodeCompleter->includeMacros()) {
Douglas Gregorbca403c2010-01-13 23:51:12 +00003661 AddMacroResults(PP, Results);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003662 kind = CodeCompletionContext::CCC_OtherWithMacros;
3663 }
3664
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003665 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003666 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003667 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003668}
3669
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003670namespace {
3671 struct IsBetterOverloadCandidate {
3672 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003673 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003674
3675 public:
John McCall5769d612010-02-08 23:07:23 +00003676 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3677 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003678
3679 bool
3680 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003681 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003682 }
3683 };
3684}
3685
Ahmed Charles13a140c2012-02-25 11:00:22 +00003686static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3687 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003688 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003689
3690 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003691 if (!Args[I])
3692 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003693
Douglas Gregord28dcd72010-05-30 06:10:08 +00003694 return false;
3695}
3696
Richard Trieuf81e5a92011-09-09 02:00:50 +00003697void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charles13a140c2012-02-25 11:00:22 +00003698 llvm::ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003699 if (!CodeCompleter)
3700 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003701
3702 // When we're code-completing for a call, we fall back to ordinary
3703 // name code-completion whenever we can't produce specific
3704 // results. We may want to revisit this strategy in the future,
3705 // e.g., by merging the two kinds of results.
3706
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003707 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003708
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003709 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003710 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3711 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003712 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003713 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003714 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003715
John McCall3b4294e2009-12-16 12:17:52 +00003716 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003717 SourceLocation Loc = Fn->getExprLoc();
3718 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003719
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003720 // FIXME: What if we're calling something that isn't a function declaration?
3721 // FIXME: What if we're calling a pseudo-destructor?
3722 // FIXME: What if we're calling a member function?
3723
Douglas Gregorc0265402010-01-21 15:46:19 +00003724 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003725 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003726
John McCall3b4294e2009-12-16 12:17:52 +00003727 Expr *NakedFn = Fn->IgnoreParenCasts();
3728 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003729 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003730 /*PartialOverloading=*/ true);
3731 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3732 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003733 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003734 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003735 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003736 Results.push_back(ResultCandidate(FDecl));
3737 else
John McCall86820f52010-01-26 01:37:31 +00003738 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003739 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3740 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003741 }
John McCall3b4294e2009-12-16 12:17:52 +00003742 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003743
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003744 QualType ParamType;
3745
Douglas Gregorc0265402010-01-21 15:46:19 +00003746 if (!CandidateSet.empty()) {
3747 // Sort the overload candidate set by placing the best overloads first.
3748 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003749 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003750
Douglas Gregorc0265402010-01-21 15:46:19 +00003751 // Add the remaining viable overload candidates as code-completion reslults.
3752 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3753 CandEnd = CandidateSet.end();
3754 Cand != CandEnd; ++Cand) {
3755 if (Cand->Viable)
3756 Results.push_back(ResultCandidate(Cand->Function));
3757 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003758
3759 // From the viable candidates, try to determine the type of this parameter.
3760 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3761 if (const FunctionType *FType = Results[I].getFunctionType())
3762 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003763 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003764 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003765 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003766 else if (!Context.hasSameUnqualifiedType(
3767 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003768 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003769 ParamType = QualType();
3770 break;
3771 }
3772 }
3773 }
3774 } else {
3775 // Try to determine the parameter type from the type of the expression
3776 // being called.
3777 QualType FunctionType = Fn->getType();
3778 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3779 FunctionType = Ptr->getPointeeType();
3780 else if (const BlockPointerType *BlockPtr
3781 = FunctionType->getAs<BlockPointerType>())
3782 FunctionType = BlockPtr->getPointeeType();
3783 else if (const MemberPointerType *MemPtr
3784 = FunctionType->getAs<MemberPointerType>())
3785 FunctionType = MemPtr->getPointeeType();
3786
3787 if (const FunctionProtoType *Proto
3788 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003789 if (Args.size() < Proto->getNumArgs())
3790 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003791 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003792 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003793
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003794 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003795 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003796 else
3797 CodeCompleteExpression(S, ParamType);
3798
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003799 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003800 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003801 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003802}
3803
John McCalld226f652010-08-21 09:40:31 +00003804void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3805 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003806 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003807 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003808 return;
3809 }
3810
3811 CodeCompleteExpression(S, VD->getType());
3812}
3813
3814void Sema::CodeCompleteReturn(Scope *S) {
3815 QualType ResultType;
3816 if (isa<BlockDecl>(CurContext)) {
3817 if (BlockScopeInfo *BSI = getCurBlock())
3818 ResultType = BSI->ReturnType;
3819 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3820 ResultType = Function->getResultType();
3821 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3822 ResultType = Method->getResultType();
3823
3824 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003825 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003826 else
3827 CodeCompleteExpression(S, ResultType);
3828}
3829
Douglas Gregord2d8be62011-07-30 08:36:53 +00003830void Sema::CodeCompleteAfterIf(Scope *S) {
3831 typedef CodeCompletionResult Result;
3832 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3833 mapCodeCompletionContext(*this, PCC_Statement));
3834 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3835 Results.EnterNewScope();
3836
3837 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3838 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3839 CodeCompleter->includeGlobals());
3840
3841 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3842
3843 // "else" block
3844 CodeCompletionBuilder Builder(Results.getAllocator());
3845 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00003846 if (Results.includeCodePatterns()) {
3847 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3848 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3849 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3850 Builder.AddPlaceholderChunk("statements");
3851 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3852 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3853 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003854 Results.AddResult(Builder.TakeString());
3855
3856 // "else if" block
3857 Builder.AddTypedTextChunk("else");
3858 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3859 Builder.AddTextChunk("if");
3860 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3861 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00003862 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00003863 Builder.AddPlaceholderChunk("condition");
3864 else
3865 Builder.AddPlaceholderChunk("expression");
3866 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00003867 if (Results.includeCodePatterns()) {
3868 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3869 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3870 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3871 Builder.AddPlaceholderChunk("statements");
3872 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3873 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3874 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003875 Results.AddResult(Builder.TakeString());
3876
3877 Results.ExitScope();
3878
3879 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003880 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003881
3882 if (CodeCompleter->includeMacros())
3883 AddMacroResults(PP, Results);
3884
3885 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3886 Results.data(),Results.size());
3887}
3888
Richard Trieuf81e5a92011-09-09 02:00:50 +00003889void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003890 if (LHS)
3891 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3892 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003893 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003894}
3895
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003896void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003897 bool EnteringContext) {
3898 if (!SS.getScopeRep() || !CodeCompleter)
3899 return;
3900
Douglas Gregor86d9a522009-09-21 16:56:56 +00003901 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3902 if (!Ctx)
3903 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003904
3905 // Try to instantiate any non-dependent declaration contexts before
3906 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003907 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003908 return;
3909
Douglas Gregor218937c2011-02-01 19:23:04 +00003910 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3911 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003912 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003913
Douglas Gregor86d9a522009-09-21 16:56:56 +00003914 // The "template" keyword can follow "::" in the grammar, but only
3915 // put it into the grammar if the nested-name-specifier is dependent.
3916 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3917 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003918 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003919
3920 // Add calls to overridden virtual functions, if there are any.
3921 //
3922 // FIXME: This isn't wonderful, because we don't know whether we're actually
3923 // in a context that permits expressions. This is a general issue with
3924 // qualified-id completions.
3925 if (!EnteringContext)
3926 MaybeAddOverrideCalls(*this, Ctx, Results);
3927 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003928
Douglas Gregorf6961522010-08-27 21:18:54 +00003929 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3930 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3931
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003932 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00003933 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003934 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003935}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003936
3937void Sema::CodeCompleteUsing(Scope *S) {
3938 if (!CodeCompleter)
3939 return;
3940
Douglas Gregor218937c2011-02-01 19:23:04 +00003941 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003942 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3943 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003944 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003945
3946 // If we aren't in class scope, we could see the "namespace" keyword.
3947 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00003948 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003949
3950 // After "using", we can see anything that would start a
3951 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003952 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003953 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3954 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003955 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003956
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003957 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003958 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003959 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003960}
3961
3962void Sema::CodeCompleteUsingDirective(Scope *S) {
3963 if (!CodeCompleter)
3964 return;
3965
Douglas Gregor86d9a522009-09-21 16:56:56 +00003966 // After "using namespace", we expect to see a namespace name or namespace
3967 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003968 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3969 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003970 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003971 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003972 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003973 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3974 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003975 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003976 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003977 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003978 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003979}
3980
3981void Sema::CodeCompleteNamespaceDecl(Scope *S) {
3982 if (!CodeCompleter)
3983 return;
3984
Douglas Gregor86d9a522009-09-21 16:56:56 +00003985 DeclContext *Ctx = (DeclContext *)S->getEntity();
3986 if (!S->getParent())
3987 Ctx = Context.getTranslationUnitDecl();
3988
Douglas Gregor52779fb2010-09-23 23:01:17 +00003989 bool SuppressedGlobalResults
3990 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
3991
Douglas Gregor218937c2011-02-01 19:23:04 +00003992 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003993 SuppressedGlobalResults
3994 ? CodeCompletionContext::CCC_Namespace
3995 : CodeCompletionContext::CCC_Other,
3996 &ResultBuilder::IsNamespace);
3997
3998 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00003999 // We only want to see those namespaces that have already been defined
4000 // within this scope, because its likely that the user is creating an
4001 // extended namespace declaration. Keep track of the most recent
4002 // definition of each namespace.
4003 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4004 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4005 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4006 NS != NSEnd; ++NS)
4007 OrigToLatest[NS->getOriginalNamespace()] = *NS;
4008
4009 // Add the most recent definition (or extended definition) of each
4010 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004011 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004012 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregorba103062012-03-27 23:34:16 +00004013 NS = OrigToLatest.begin(),
4014 NSEnd = OrigToLatest.end();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004015 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004016 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004017 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004018 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004019 }
4020
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004021 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004022 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004023 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004024}
4025
4026void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4027 if (!CodeCompleter)
4028 return;
4029
Douglas Gregor86d9a522009-09-21 16:56:56 +00004030 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004031 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4032 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004033 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004034 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004035 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4036 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004037 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004038 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004039 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004040}
4041
Douglas Gregored8d3222009-09-18 20:05:18 +00004042void Sema::CodeCompleteOperatorName(Scope *S) {
4043 if (!CodeCompleter)
4044 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004045
John McCall0a2c5e22010-08-25 06:19:51 +00004046 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004047 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4048 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004049 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004050 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004051
Douglas Gregor86d9a522009-09-21 16:56:56 +00004052 // Add the names of overloadable operators.
4053#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4054 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004055 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004056#include "clang/Basic/OperatorKinds.def"
4057
4058 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004059 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004060 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004061 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4062 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004063
4064 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004065 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004066 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004067
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004068 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004069 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004070 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004071}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004072
Douglas Gregor0133f522010-08-28 00:00:50 +00004073void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004074 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004075 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004076 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004077 CXXConstructorDecl *Constructor
4078 = static_cast<CXXConstructorDecl *>(ConstructorD);
4079 if (!Constructor)
4080 return;
4081
Douglas Gregor218937c2011-02-01 19:23:04 +00004082 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004083 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004084 Results.EnterNewScope();
4085
4086 // Fill in any already-initialized fields or base classes.
4087 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4088 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4089 for (unsigned I = 0; I != NumInitializers; ++I) {
4090 if (Initializers[I]->isBaseInitializer())
4091 InitializedBases.insert(
4092 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4093 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004094 InitializedFields.insert(cast<FieldDecl>(
4095 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004096 }
4097
4098 // Add completions for base classes.
Douglas Gregor218937c2011-02-01 19:23:04 +00004099 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004100 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004101 CXXRecordDecl *ClassDecl = Constructor->getParent();
4102 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4103 BaseEnd = ClassDecl->bases_end();
4104 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004105 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4106 SawLastInitializer
4107 = NumInitializers > 0 &&
4108 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4109 Context.hasSameUnqualifiedType(Base->getType(),
4110 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004111 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004112 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004113
Douglas Gregor218937c2011-02-01 19:23:04 +00004114 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004115 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004116 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004117 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4118 Builder.AddPlaceholderChunk("args");
4119 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4120 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004121 SawLastInitializer? CCP_NextInitializer
4122 : CCP_MemberDeclaration));
4123 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004124 }
4125
4126 // Add completions for virtual base classes.
4127 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4128 BaseEnd = ClassDecl->vbases_end();
4129 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004130 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4131 SawLastInitializer
4132 = NumInitializers > 0 &&
4133 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4134 Context.hasSameUnqualifiedType(Base->getType(),
4135 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004136 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004137 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004138
Douglas Gregor218937c2011-02-01 19:23:04 +00004139 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004140 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004141 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004142 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4143 Builder.AddPlaceholderChunk("args");
4144 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4145 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004146 SawLastInitializer? CCP_NextInitializer
4147 : CCP_MemberDeclaration));
4148 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004149 }
4150
4151 // Add completions for members.
4152 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4153 FieldEnd = ClassDecl->field_end();
4154 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004155 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4156 SawLastInitializer
4157 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004158 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
4159 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004160 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004161 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004162
4163 if (!Field->getDeclName())
4164 continue;
4165
Douglas Gregordae68752011-02-01 22:57:45 +00004166 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004167 Field->getIdentifier()->getName()));
4168 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4169 Builder.AddPlaceholderChunk("args");
4170 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4171 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004172 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004173 : CCP_MemberDeclaration,
Douglas Gregorba103062012-03-27 23:34:16 +00004174 CXCursor_MemberRef,
4175 CXAvailability_Available,
4176 *Field));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004177 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004178 }
4179 Results.ExitScope();
4180
Douglas Gregor52779fb2010-09-23 23:01:17 +00004181 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004182 Results.data(), Results.size());
4183}
4184
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004185/// \brief Determine whether this scope denotes a namespace.
4186static bool isNamespaceScope(Scope *S) {
4187 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4188 if (!DC)
4189 return false;
4190
4191 return DC->isFileContext();
4192}
4193
4194void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4195 bool AfterAmpersand) {
4196 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4197 CodeCompletionContext::CCC_Other);
4198 Results.EnterNewScope();
4199
4200 // Note what has already been captured.
4201 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4202 bool IncludedThis = false;
4203 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4204 CEnd = Intro.Captures.end();
4205 C != CEnd; ++C) {
4206 if (C->Kind == LCK_This) {
4207 IncludedThis = true;
4208 continue;
4209 }
4210
4211 Known.insert(C->Id);
4212 }
4213
4214 // Look for other capturable variables.
4215 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4216 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4217 D != DEnd; ++D) {
4218 VarDecl *Var = dyn_cast<VarDecl>(*D);
4219 if (!Var ||
4220 !Var->hasLocalStorage() ||
4221 Var->hasAttr<BlocksAttr>())
4222 continue;
4223
4224 if (Known.insert(Var->getIdentifier()))
4225 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4226 }
4227 }
4228
4229 // Add 'this', if it would be valid.
4230 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4231 addThisCompletion(*this, Results);
4232
4233 Results.ExitScope();
4234
4235 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4236 Results.data(), Results.size());
4237}
4238
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004239// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
4240// true or false.
4241#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorbca403c2010-01-13 23:51:12 +00004242static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004243 ResultBuilder &Results,
4244 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004245 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004246 // Since we have an implementation, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004247 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004248
Douglas Gregor218937c2011-02-01 19:23:04 +00004249 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004250 if (LangOpts.ObjC2) {
4251 // @dynamic
Douglas Gregor218937c2011-02-01 19:23:04 +00004252 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
4253 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4254 Builder.AddPlaceholderChunk("property");
4255 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004256
4257 // @synthesize
Douglas Gregor218937c2011-02-01 19:23:04 +00004258 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
4259 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4260 Builder.AddPlaceholderChunk("property");
4261 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004262 }
4263}
4264
Douglas Gregorbca403c2010-01-13 23:51:12 +00004265static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004266 ResultBuilder &Results,
4267 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004268 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004269
4270 // Since we have an interface or protocol, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004271 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004272
4273 if (LangOpts.ObjC2) {
4274 // @property
Douglas Gregora4477812010-01-14 16:01:26 +00004275 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004276
4277 // @required
Douglas Gregora4477812010-01-14 16:01:26 +00004278 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004279
4280 // @optional
Douglas Gregora4477812010-01-14 16:01:26 +00004281 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004282 }
4283}
4284
Douglas Gregorbca403c2010-01-13 23:51:12 +00004285static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004286 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004287 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004288
4289 // @class name ;
Douglas Gregor218937c2011-02-01 19:23:04 +00004290 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
4291 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4292 Builder.AddPlaceholderChunk("name");
4293 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004294
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004295 if (Results.includeCodePatterns()) {
4296 // @interface name
4297 // FIXME: Could introduce the whole pattern, including superclasses and
4298 // such.
Douglas Gregor218937c2011-02-01 19:23:04 +00004299 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
4300 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4301 Builder.AddPlaceholderChunk("class");
4302 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004303
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004304 // @protocol name
Douglas Gregor218937c2011-02-01 19:23:04 +00004305 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4306 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4307 Builder.AddPlaceholderChunk("protocol");
4308 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004309
4310 // @implementation name
Douglas Gregor218937c2011-02-01 19:23:04 +00004311 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
4312 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4313 Builder.AddPlaceholderChunk("class");
4314 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004315 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004316
4317 // @compatibility_alias name
Douglas Gregor218937c2011-02-01 19:23:04 +00004318 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
4319 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4320 Builder.AddPlaceholderChunk("alias");
4321 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4322 Builder.AddPlaceholderChunk("class");
4323 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004324}
4325
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004326void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004327 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004328 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4329 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004330 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004331 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004332 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004333 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004334 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004335 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004336 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004337 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004338 HandleCodeCompleteResults(this, CodeCompleter,
4339 CodeCompletionContext::CCC_Other,
4340 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004341}
4342
Douglas Gregorbca403c2010-01-13 23:51:12 +00004343static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004344 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004345 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004346
4347 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004348 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004349 if (Results.getSema().getLangOpts().CPlusPlus ||
4350 Results.getSema().getLangOpts().ConstStrings)
Douglas Gregor8ca72082011-10-18 21:20:17 +00004351 EncodeType = " const char[]";
4352 Builder.AddResultTypeChunk(EncodeType);
Douglas Gregor218937c2011-02-01 19:23:04 +00004353 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
4354 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4355 Builder.AddPlaceholderChunk("type-name");
4356 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4357 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004358
4359 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004360 Builder.AddResultTypeChunk("Protocol *");
Douglas Gregor218937c2011-02-01 19:23:04 +00004361 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4362 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4363 Builder.AddPlaceholderChunk("protocol-name");
4364 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4365 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004366
4367 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004368 Builder.AddResultTypeChunk("SEL");
Douglas Gregor218937c2011-02-01 19:23:04 +00004369 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
4370 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4371 Builder.AddPlaceholderChunk("selector");
4372 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4373 Results.AddResult(Result(Builder.TakeString()));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004374
4375 // @[ objects, ... ]
4376 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,[));
4377 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4378 Builder.AddPlaceholderChunk("objects, ...");
4379 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4380 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4381 Results.AddResult(Result(Builder.TakeString()));
4382
4383 // @{ key : object, ... }
4384 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,{));
4385 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4386 Builder.AddPlaceholderChunk("key");
4387 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4388 Builder.AddChunk(CodeCompletionString::CK_Colon);
4389 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4390 Builder.AddPlaceholderChunk("object, ...");
4391 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4392 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4393 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004394}
4395
Douglas Gregorbca403c2010-01-13 23:51:12 +00004396static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004397 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004398 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004399
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004400 if (Results.includeCodePatterns()) {
4401 // @try { statements } @catch ( declaration ) { statements } @finally
4402 // { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004403 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
4404 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4405 Builder.AddPlaceholderChunk("statements");
4406 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4407 Builder.AddTextChunk("@catch");
4408 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4409 Builder.AddPlaceholderChunk("parameter");
4410 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4411 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4412 Builder.AddPlaceholderChunk("statements");
4413 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4414 Builder.AddTextChunk("@finally");
4415 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4416 Builder.AddPlaceholderChunk("statements");
4417 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4418 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004419 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004420
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004421 // @throw
Douglas Gregor218937c2011-02-01 19:23:04 +00004422 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
4423 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4424 Builder.AddPlaceholderChunk("expression");
4425 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004426
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004427 if (Results.includeCodePatterns()) {
4428 // @synchronized ( expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004429 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
4430 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4431 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4432 Builder.AddPlaceholderChunk("expression");
4433 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4434 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4435 Builder.AddPlaceholderChunk("statements");
4436 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4437 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004438 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004439}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004440
Douglas Gregorbca403c2010-01-13 23:51:12 +00004441static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004442 ResultBuilder &Results,
4443 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004444 typedef CodeCompletionResult Result;
Douglas Gregora4477812010-01-14 16:01:26 +00004445 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
4446 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
4447 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004448 if (LangOpts.ObjC2)
Douglas Gregora4477812010-01-14 16:01:26 +00004449 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004450}
4451
4452void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004453 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4454 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004455 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004456 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004457 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004458 HandleCodeCompleteResults(this, CodeCompleter,
4459 CodeCompletionContext::CCC_Other,
4460 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004461}
4462
4463void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004464 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4465 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004466 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004467 AddObjCStatementResults(Results, false);
4468 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004469 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004470 HandleCodeCompleteResults(this, CodeCompleter,
4471 CodeCompletionContext::CCC_Other,
4472 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004473}
4474
4475void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004476 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4477 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004478 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004479 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004480 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004481 HandleCodeCompleteResults(this, CodeCompleter,
4482 CodeCompletionContext::CCC_Other,
4483 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004484}
4485
Douglas Gregor988358f2009-11-19 00:14:45 +00004486/// \brief Determine whether the addition of the given flag to an Objective-C
4487/// property's attributes will cause a conflict.
4488static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4489 // Check if we've already added this flag.
4490 if (Attributes & NewFlag)
4491 return true;
4492
4493 Attributes |= NewFlag;
4494
4495 // Check for collisions with "readonly".
4496 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4497 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4498 ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004499 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004500 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004501 ObjCDeclSpec::DQ_PR_retain |
4502 ObjCDeclSpec::DQ_PR_strong)))
Douglas Gregor988358f2009-11-19 00:14:45 +00004503 return true;
4504
John McCallf85e1932011-06-15 23:02:42 +00004505 // Check for more than one of { assign, copy, retain, strong }.
Douglas Gregor988358f2009-11-19 00:14:45 +00004506 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004507 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004508 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004509 ObjCDeclSpec::DQ_PR_retain|
4510 ObjCDeclSpec::DQ_PR_strong);
Douglas Gregor988358f2009-11-19 00:14:45 +00004511 if (AssignCopyRetMask &&
4512 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004513 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004514 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004515 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
4516 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
Douglas Gregor988358f2009-11-19 00:14:45 +00004517 return true;
4518
4519 return false;
4520}
4521
Douglas Gregora93b1082009-11-18 23:08:07 +00004522void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004523 if (!CodeCompleter)
4524 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004525
Steve Naroffece8e712009-10-08 21:55:05 +00004526 unsigned Attributes = ODS.getPropertyAttributes();
4527
John McCall0a2c5e22010-08-25 06:19:51 +00004528 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004529 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4530 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004531 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004532 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004533 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004534 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004535 Results.AddResult(CodeCompletionResult("assign"));
John McCallf85e1932011-06-15 23:02:42 +00004536 if (!ObjCPropertyFlagConflicts(Attributes,
4537 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4538 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004539 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004540 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004541 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004542 Results.AddResult(CodeCompletionResult("retain"));
John McCallf85e1932011-06-15 23:02:42 +00004543 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4544 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004545 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004546 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004547 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004548 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004549 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4550 Results.AddResult(CodeCompletionResult("atomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004551 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004552 CodeCompletionBuilder Setter(Results.getAllocator());
4553 Setter.AddTypedTextChunk("setter");
4554 Setter.AddTextChunk(" = ");
4555 Setter.AddPlaceholderChunk("method");
4556 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004557 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004558 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004559 CodeCompletionBuilder Getter(Results.getAllocator());
4560 Getter.AddTypedTextChunk("getter");
4561 Getter.AddTextChunk(" = ");
4562 Getter.AddPlaceholderChunk("method");
4563 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004564 }
Steve Naroffece8e712009-10-08 21:55:05 +00004565 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004566 HandleCodeCompleteResults(this, CodeCompleter,
4567 CodeCompletionContext::CCC_Other,
4568 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004569}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004570
Douglas Gregor4ad96852009-11-19 07:41:15 +00004571/// \brief Descripts the kind of Objective-C method that we want to find
4572/// via code completion.
4573enum ObjCMethodKind {
4574 MK_Any, //< Any kind of method, provided it means other specified criteria.
4575 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4576 MK_OneArgSelector //< One-argument selector.
4577};
4578
Douglas Gregor458433d2010-08-26 15:07:07 +00004579static bool isAcceptableObjCSelector(Selector Sel,
4580 ObjCMethodKind WantKind,
4581 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004582 unsigned NumSelIdents,
4583 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004584 if (NumSelIdents > Sel.getNumArgs())
4585 return false;
4586
4587 switch (WantKind) {
4588 case MK_Any: break;
4589 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4590 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4591 }
4592
Douglas Gregorcf544262010-11-17 21:36:08 +00004593 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4594 return false;
4595
Douglas Gregor458433d2010-08-26 15:07:07 +00004596 for (unsigned I = 0; I != NumSelIdents; ++I)
4597 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4598 return false;
4599
4600 return true;
4601}
4602
Douglas Gregor4ad96852009-11-19 07:41:15 +00004603static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4604 ObjCMethodKind WantKind,
4605 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004606 unsigned NumSelIdents,
4607 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004608 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004609 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004610}
Douglas Gregord36adf52010-09-16 16:06:31 +00004611
4612namespace {
4613 /// \brief A set of selectors, which is used to avoid introducing multiple
4614 /// completions with the same selector into the result set.
4615 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4616}
4617
Douglas Gregor36ecb042009-11-17 23:22:23 +00004618/// \brief Add all of the Objective-C methods in the given Objective-C
4619/// container to the set of results.
4620///
4621/// The container will be a class, protocol, category, or implementation of
4622/// any of the above. This mether will recurse to include methods from
4623/// the superclasses of classes along with their categories, protocols, and
4624/// implementations.
4625///
4626/// \param Container the container in which we'll look to find methods.
4627///
4628/// \param WantInstance whether to add instance methods (only); if false, this
4629/// routine will add factory methods (only).
4630///
4631/// \param CurContext the context in which we're performing the lookup that
4632/// finds methods.
4633///
Douglas Gregorcf544262010-11-17 21:36:08 +00004634/// \param AllowSameLength Whether we allow a method to be added to the list
4635/// when it has the same number of parameters as we have selector identifiers.
4636///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004637/// \param Results the structure into which we'll add results.
4638static void AddObjCMethods(ObjCContainerDecl *Container,
4639 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004640 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004641 IdentifierInfo **SelIdents,
4642 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004643 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004644 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004645 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004646 ResultBuilder &Results,
4647 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004648 typedef CodeCompletionResult Result;
Douglas Gregor36ecb042009-11-17 23:22:23 +00004649 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4650 MEnd = Container->meth_end();
4651 M != MEnd; ++M) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004652 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4653 // Check whether the selector identifiers we've been given are a
4654 // subset of the identifiers for this particular method.
Douglas Gregorcf544262010-11-17 21:36:08 +00004655 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4656 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004657 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004658
Douglas Gregord36adf52010-09-16 16:06:31 +00004659 if (!Selectors.insert((*M)->getSelector()))
4660 continue;
4661
Douglas Gregord3c68542009-11-19 01:08:35 +00004662 Result R = Result(*M, 0);
4663 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004664 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004665 if (!InOriginalClass)
4666 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004667 Results.MaybeAddResult(R, CurContext);
4668 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004669 }
4670
Douglas Gregore396c7b2010-09-16 15:34:59 +00004671 // Visit the protocols of protocols.
4672 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004673 if (Protocol->hasDefinition()) {
4674 const ObjCList<ObjCProtocolDecl> &Protocols
4675 = Protocol->getReferencedProtocols();
4676 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4677 E = Protocols.end();
4678 I != E; ++I)
4679 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4680 NumSelIdents, CurContext, Selectors, AllowSameLength,
4681 Results, false);
4682 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004683 }
4684
Douglas Gregor36ecb042009-11-17 23:22:23 +00004685 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004686 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004687 return;
4688
4689 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004690 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4691 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004692 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004693 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004694 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004695
4696 // Add methods in categories.
4697 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4698 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004699 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004700 NumSelIdents, CurContext, Selectors, AllowSameLength,
4701 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004702
4703 // Add a categories protocol methods.
4704 const ObjCList<ObjCProtocolDecl> &Protocols
4705 = CatDecl->getReferencedProtocols();
4706 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4707 E = Protocols.end();
4708 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004709 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004710 NumSelIdents, CurContext, Selectors, AllowSameLength,
4711 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004712
4713 // Add methods in category implementations.
4714 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004715 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004716 NumSelIdents, CurContext, Selectors, AllowSameLength,
4717 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004718 }
4719
4720 // Add methods in superclass.
4721 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004722 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004723 SelIdents, NumSelIdents, CurContext, Selectors,
4724 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004725
4726 // Add methods in our implementation, if any.
4727 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004728 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004729 NumSelIdents, CurContext, Selectors, AllowSameLength,
4730 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004731}
4732
4733
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004734void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004735 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004736
4737 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004738 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004739 if (!Class) {
4740 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004741 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004742 Class = Category->getClassInterface();
4743
4744 if (!Class)
4745 return;
4746 }
4747
4748 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004749 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4750 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004751 Results.EnterNewScope();
4752
Douglas Gregord36adf52010-09-16 16:06:31 +00004753 VisitedSelectorSet Selectors;
4754 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004755 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004756 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004757 HandleCodeCompleteResults(this, CodeCompleter,
4758 CodeCompletionContext::CCC_Other,
4759 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004760}
4761
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004762void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004763 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004764
4765 // Try to find the interface where setters might live.
4766 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004767 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004768 if (!Class) {
4769 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004770 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004771 Class = Category->getClassInterface();
4772
4773 if (!Class)
4774 return;
4775 }
4776
4777 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004778 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4779 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004780 Results.EnterNewScope();
4781
Douglas Gregord36adf52010-09-16 16:06:31 +00004782 VisitedSelectorSet Selectors;
4783 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004784 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004785
4786 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004787 HandleCodeCompleteResults(this, CodeCompleter,
4788 CodeCompletionContext::CCC_Other,
4789 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004790}
4791
Douglas Gregorafc45782011-02-15 22:19:42 +00004792void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4793 bool IsParameter) {
John McCall0a2c5e22010-08-25 06:19:51 +00004794 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004795 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4796 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004797 Results.EnterNewScope();
4798
4799 // Add context-sensitive, Objective-C parameter-passing keywords.
4800 bool AddedInOut = false;
4801 if ((DS.getObjCDeclQualifier() &
4802 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4803 Results.AddResult("in");
4804 Results.AddResult("inout");
4805 AddedInOut = true;
4806 }
4807 if ((DS.getObjCDeclQualifier() &
4808 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4809 Results.AddResult("out");
4810 if (!AddedInOut)
4811 Results.AddResult("inout");
4812 }
4813 if ((DS.getObjCDeclQualifier() &
4814 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4815 ObjCDeclSpec::DQ_Oneway)) == 0) {
4816 Results.AddResult("bycopy");
4817 Results.AddResult("byref");
4818 Results.AddResult("oneway");
4819 }
4820
Douglas Gregorafc45782011-02-15 22:19:42 +00004821 // If we're completing the return type of an Objective-C method and the
4822 // identifier IBAction refers to a macro, provide a completion item for
4823 // an action, e.g.,
4824 // IBAction)<#selector#>:(id)sender
4825 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4826 Context.Idents.get("IBAction").hasMacroDefinition()) {
Douglas Gregorafc45782011-02-15 22:19:42 +00004827 CodeCompletionBuilder Builder(Results.getAllocator(), CCP_CodePattern,
4828 CXAvailability_Available);
4829 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004830 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004831 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004832 Builder.AddChunk(CodeCompletionString::CK_Colon);
4833 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004834 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004835 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004836 Builder.AddTextChunk("sender");
4837 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4838 }
4839
Douglas Gregord32b0222010-08-24 01:06:58 +00004840 // Add various builtin type names and specifiers.
4841 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4842 Results.ExitScope();
4843
4844 // Add the various type names
4845 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4846 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4847 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4848 CodeCompleter->includeGlobals());
4849
4850 if (CodeCompleter->includeMacros())
4851 AddMacroResults(PP, Results);
4852
4853 HandleCodeCompleteResults(this, CodeCompleter,
4854 CodeCompletionContext::CCC_Type,
4855 Results.data(), Results.size());
4856}
4857
Douglas Gregor22f56992010-04-06 19:22:33 +00004858/// \brief When we have an expression with type "id", we may assume
4859/// that it has some more-specific class type based on knowledge of
4860/// common uses of Objective-C. This routine returns that class type,
4861/// or NULL if no better result could be determined.
4862static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004863 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004864 if (!Msg)
4865 return 0;
4866
4867 Selector Sel = Msg->getSelector();
4868 if (Sel.isNull())
4869 return 0;
4870
4871 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4872 if (!Id)
4873 return 0;
4874
4875 ObjCMethodDecl *Method = Msg->getMethodDecl();
4876 if (!Method)
4877 return 0;
4878
4879 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004880 ObjCInterfaceDecl *IFace = 0;
4881 switch (Msg->getReceiverKind()) {
4882 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004883 if (const ObjCObjectType *ObjType
4884 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4885 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004886 break;
4887
4888 case ObjCMessageExpr::Instance: {
4889 QualType T = Msg->getInstanceReceiver()->getType();
4890 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4891 IFace = Ptr->getInterfaceDecl();
4892 break;
4893 }
4894
4895 case ObjCMessageExpr::SuperInstance:
4896 case ObjCMessageExpr::SuperClass:
4897 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00004898 }
4899
4900 if (!IFace)
4901 return 0;
4902
4903 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4904 if (Method->isInstanceMethod())
4905 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4906 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00004907 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00004908 .Case("autorelease", IFace)
4909 .Case("copy", IFace)
4910 .Case("copyWithZone", IFace)
4911 .Case("mutableCopy", IFace)
4912 .Case("mutableCopyWithZone", IFace)
4913 .Case("awakeFromCoder", IFace)
4914 .Case("replacementObjectFromCoder", IFace)
4915 .Case("class", IFace)
4916 .Case("classForCoder", IFace)
4917 .Case("superclass", Super)
4918 .Default(0);
4919
4920 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4921 .Case("new", IFace)
4922 .Case("alloc", IFace)
4923 .Case("allocWithZone", IFace)
4924 .Case("class", IFace)
4925 .Case("superclass", Super)
4926 .Default(0);
4927}
4928
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004929// Add a special completion for a message send to "super", which fills in the
4930// most likely case of forwarding all of our arguments to the superclass
4931// function.
4932///
4933/// \param S The semantic analysis object.
4934///
4935/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4936/// the "super" keyword. Otherwise, we just need to provide the arguments.
4937///
4938/// \param SelIdents The identifiers in the selector that have already been
4939/// provided as arguments for a send to "super".
4940///
4941/// \param NumSelIdents The number of identifiers in \p SelIdents.
4942///
4943/// \param Results The set of results to augment.
4944///
4945/// \returns the Objective-C method declaration that would be invoked by
4946/// this "super" completion. If NULL, no completion was added.
4947static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4948 IdentifierInfo **SelIdents,
4949 unsigned NumSelIdents,
4950 ResultBuilder &Results) {
4951 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
4952 if (!CurMethod)
4953 return 0;
4954
4955 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
4956 if (!Class)
4957 return 0;
4958
4959 // Try to find a superclass method with the same selector.
4960 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00004961 while ((Class = Class->getSuperClass()) && !SuperMethod) {
4962 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004963 SuperMethod = Class->getMethod(CurMethod->getSelector(),
4964 CurMethod->isInstanceMethod());
4965
Douglas Gregor78bcd912011-02-16 00:51:18 +00004966 // Check in categories or class extensions.
4967 if (!SuperMethod) {
4968 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
4969 Category = Category->getNextClassCategory())
4970 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
4971 CurMethod->isInstanceMethod())))
4972 break;
4973 }
4974 }
4975
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004976 if (!SuperMethod)
4977 return 0;
4978
4979 // Check whether the superclass method has the same signature.
4980 if (CurMethod->param_size() != SuperMethod->param_size() ||
4981 CurMethod->isVariadic() != SuperMethod->isVariadic())
4982 return 0;
4983
4984 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
4985 CurPEnd = CurMethod->param_end(),
4986 SuperP = SuperMethod->param_begin();
4987 CurP != CurPEnd; ++CurP, ++SuperP) {
4988 // Make sure the parameter types are compatible.
4989 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
4990 (*SuperP)->getType()))
4991 return 0;
4992
4993 // Make sure we have a parameter name to forward!
4994 if (!(*CurP)->getIdentifier())
4995 return 0;
4996 }
4997
4998 // We have a superclass method. Now, form the send-to-super completion.
Douglas Gregor218937c2011-02-01 19:23:04 +00004999 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005000
5001 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005002 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5003 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005004
5005 // If we need the "super" keyword, add it (plus some spacing).
5006 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005007 Builder.AddTypedTextChunk("super");
5008 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005009 }
5010
5011 Selector Sel = CurMethod->getSelector();
5012 if (Sel.isUnarySelector()) {
5013 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005014 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005015 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005016 else
Douglas Gregordae68752011-02-01 22:57:45 +00005017 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005018 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005019 } else {
5020 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5021 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5022 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005023 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005024
5025 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005026 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005027 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005028 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005029 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005030 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005031 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005032 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005033 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005034 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005035 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005036 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005037 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005038 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005039 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005040 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005041 }
5042 }
5043 }
5044
Douglas Gregorba103062012-03-27 23:34:16 +00005045 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5046 CCP_SuperCompletion));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005047 return SuperMethod;
5048}
5049
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005050void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005051 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005052 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5053 CodeCompletionContext::CCC_ObjCMessageReceiver,
David Blaikie4e4d0842012-03-11 07:00:24 +00005054 getLangOpts().CPlusPlus0x
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005055 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5056 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005057
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005058 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5059 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005060 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5061 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005062
5063 // If we are in an Objective-C method inside a class that has a superclass,
5064 // add "super" as an option.
5065 if (ObjCMethodDecl *Method = getCurMethodDecl())
5066 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005067 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005068 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005069
5070 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5071 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005072
David Blaikie4e4d0842012-03-11 07:00:24 +00005073 if (getLangOpts().CPlusPlus0x)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005074 addThisCompletion(*this, Results);
5075
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005076 Results.ExitScope();
5077
5078 if (CodeCompleter->includeMacros())
5079 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005080 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005081 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005082
5083}
5084
Douglas Gregor2725ca82010-04-21 19:57:20 +00005085void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5086 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005087 unsigned NumSelIdents,
5088 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005089 ObjCInterfaceDecl *CDecl = 0;
5090 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5091 // Figure out which interface we're in.
5092 CDecl = CurMethod->getClassInterface();
5093 if (!CDecl)
5094 return;
5095
5096 // Find the superclass of this class.
5097 CDecl = CDecl->getSuperClass();
5098 if (!CDecl)
5099 return;
5100
5101 if (CurMethod->isInstanceMethod()) {
5102 // We are inside an instance method, which means that the message
5103 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005104 // current object.
5105 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005106 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005107 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005108 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005109 }
5110
5111 // Fall through to send to the superclass in CDecl.
5112 } else {
5113 // "super" may be the name of a type or variable. Figure out which
5114 // it is.
5115 IdentifierInfo *Super = &Context.Idents.get("super");
5116 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5117 LookupOrdinaryName);
5118 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5119 // "super" names an interface. Use it.
5120 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005121 if (const ObjCObjectType *Iface
5122 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5123 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005124 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5125 // "super" names an unresolved type; we can't be more specific.
5126 } else {
5127 // Assume that "super" names some kind of value and parse that way.
5128 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005129 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005130 UnqualifiedId id;
5131 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005132 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5133 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005134 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005135 SelIdents, NumSelIdents,
5136 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005137 }
5138
5139 // Fall through
5140 }
5141
John McCallb3d87482010-08-24 05:47:05 +00005142 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005143 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005144 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005145 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005146 NumSelIdents, AtArgumentExpression,
5147 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005148}
5149
Douglas Gregorb9d77572010-09-21 00:03:25 +00005150/// \brief Given a set of code-completion results for the argument of a message
5151/// send, determine the preferred type (if any) for that argument expression.
5152static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5153 unsigned NumSelIdents) {
5154 typedef CodeCompletionResult Result;
5155 ASTContext &Context = Results.getSema().Context;
5156
5157 QualType PreferredType;
5158 unsigned BestPriority = CCP_Unlikely * 2;
5159 Result *ResultsData = Results.data();
5160 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5161 Result &R = ResultsData[I];
5162 if (R.Kind == Result::RK_Declaration &&
5163 isa<ObjCMethodDecl>(R.Declaration)) {
5164 if (R.Priority <= BestPriority) {
5165 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5166 if (NumSelIdents <= Method->param_size()) {
5167 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5168 ->getType();
5169 if (R.Priority < BestPriority || PreferredType.isNull()) {
5170 BestPriority = R.Priority;
5171 PreferredType = MyPreferredType;
5172 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5173 MyPreferredType)) {
5174 PreferredType = QualType();
5175 }
5176 }
5177 }
5178 }
5179 }
5180
5181 return PreferredType;
5182}
5183
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005184static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5185 ParsedType Receiver,
5186 IdentifierInfo **SelIdents,
5187 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005188 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005189 bool IsSuper,
5190 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005191 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005192 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005193
Douglas Gregor24a069f2009-11-17 17:59:40 +00005194 // If the given name refers to an interface type, retrieve the
5195 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005196 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005197 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005198 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005199 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5200 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005201 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005202
Douglas Gregor36ecb042009-11-17 23:22:23 +00005203 // Add all of the factory methods in this Objective-C class, its protocols,
5204 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005205 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005206
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005207 // If this is a send-to-super, try to add the special "super" send
5208 // completion.
5209 if (IsSuper) {
5210 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005211 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5212 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005213 Results.Ignore(SuperMethod);
5214 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005215
Douglas Gregor265f7492010-08-27 15:29:55 +00005216 // If we're inside an Objective-C method definition, prefer its selector to
5217 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005218 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005219 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005220
Douglas Gregord36adf52010-09-16 16:06:31 +00005221 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005222 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005223 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005224 SemaRef.CurContext, Selectors, AtArgumentExpression,
5225 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005226 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005227 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005228
Douglas Gregor719770d2010-04-06 17:30:22 +00005229 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005230 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005231 if (SemaRef.ExternalSource) {
5232 for (uint32_t I = 0,
5233 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005234 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005235 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5236 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005237 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005238
5239 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005240 }
5241 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005242
5243 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5244 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005245 M != MEnd; ++M) {
5246 for (ObjCMethodList *MethList = &M->second.second;
5247 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005248 MethList = MethList->Next) {
5249 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5250 NumSelIdents))
5251 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005252
Douglas Gregor13438f92010-04-06 16:40:00 +00005253 Result R(MethList->Method, 0);
5254 R.StartParameter = NumSelIdents;
5255 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005256 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005257 }
5258 }
5259 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005260
5261 Results.ExitScope();
5262}
Douglas Gregor13438f92010-04-06 16:40:00 +00005263
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005264void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5265 IdentifierInfo **SelIdents,
5266 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005267 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005268 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005269
5270 QualType T = this->GetTypeFromParser(Receiver);
5271
Douglas Gregor218937c2011-02-01 19:23:04 +00005272 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005273 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005274 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005275
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005276 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5277 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005278
5279 // If we're actually at the argument expression (rather than prior to the
5280 // selector), we're actually performing code completion for an expression.
5281 // Determine whether we have a single, best method. If so, we can
5282 // code-complete the expression using the corresponding parameter type as
5283 // our preferred type, improving completion results.
5284 if (AtArgumentExpression) {
5285 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005286 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005287 if (PreferredType.isNull())
5288 CodeCompleteOrdinaryName(S, PCC_Expression);
5289 else
5290 CodeCompleteExpression(S, PreferredType);
5291 return;
5292 }
5293
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005294 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005295 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005296 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005297}
5298
Richard Trieuf81e5a92011-09-09 02:00:50 +00005299void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005300 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005301 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005302 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005303 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005304 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005305
5306 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005307
Douglas Gregor36ecb042009-11-17 23:22:23 +00005308 // If necessary, apply function/array conversion to the receiver.
5309 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005310 if (RecExpr) {
5311 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5312 if (Conv.isInvalid()) // conversion failed. bail.
5313 return;
5314 RecExpr = Conv.take();
5315 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005316 QualType ReceiverType = RecExpr? RecExpr->getType()
5317 : Super? Context.getObjCObjectPointerType(
5318 Context.getObjCInterfaceType(Super))
5319 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005320
Douglas Gregorda892642010-11-08 21:12:30 +00005321 // If we're messaging an expression with type "id" or "Class", check
5322 // whether we know something special about the receiver that allows
5323 // us to assume a more-specific receiver type.
5324 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5325 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5326 if (ReceiverType->isObjCClassType())
5327 return CodeCompleteObjCClassMessage(S,
5328 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5329 SelIdents, NumSelIdents,
5330 AtArgumentExpression, Super);
5331
5332 ReceiverType = Context.getObjCObjectPointerType(
5333 Context.getObjCInterfaceType(IFace));
5334 }
5335
Douglas Gregor36ecb042009-11-17 23:22:23 +00005336 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005337 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005338 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005339 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005340
Douglas Gregor36ecb042009-11-17 23:22:23 +00005341 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005342
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005343 // If this is a send-to-super, try to add the special "super" send
5344 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005345 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005346 if (ObjCMethodDecl *SuperMethod
5347 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5348 Results))
5349 Results.Ignore(SuperMethod);
5350 }
5351
Douglas Gregor265f7492010-08-27 15:29:55 +00005352 // If we're inside an Objective-C method definition, prefer its selector to
5353 // others.
5354 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5355 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005356
Douglas Gregord36adf52010-09-16 16:06:31 +00005357 // Keep track of the selectors we've already added.
5358 VisitedSelectorSet Selectors;
5359
Douglas Gregorf74a4192009-11-18 00:06:18 +00005360 // Handle messages to Class. This really isn't a message to an instance
5361 // method, so we treat it the same way we would treat a message send to a
5362 // class method.
5363 if (ReceiverType->isObjCClassType() ||
5364 ReceiverType->isObjCQualifiedClassType()) {
5365 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5366 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005367 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005368 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005369 }
5370 }
5371 // Handle messages to a qualified ID ("id<foo>").
5372 else if (const ObjCObjectPointerType *QualID
5373 = ReceiverType->getAsObjCQualifiedIdType()) {
5374 // Search protocols for instance methods.
5375 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5376 E = QualID->qual_end();
5377 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005378 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005379 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005380 }
5381 // Handle messages to a pointer to interface type.
5382 else if (const ObjCObjectPointerType *IFacePtr
5383 = ReceiverType->getAsObjCInterfacePointerType()) {
5384 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005385 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005386 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5387 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005388
5389 // Search protocols for instance methods.
5390 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5391 E = IFacePtr->qual_end();
5392 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005393 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005394 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005395 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005396 // Handle messages to "id".
5397 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005398 // We're messaging "id", so provide all instance methods we know
5399 // about as code-completion results.
5400
5401 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005402 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005403 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005404 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5405 I != N; ++I) {
5406 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005407 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005408 continue;
5409
Sebastian Redldb9d2142010-08-02 23:18:59 +00005410 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005411 }
5412 }
5413
Sebastian Redldb9d2142010-08-02 23:18:59 +00005414 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5415 MEnd = MethodPool.end();
5416 M != MEnd; ++M) {
5417 for (ObjCMethodList *MethList = &M->second.first;
5418 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005419 MethList = MethList->Next) {
5420 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5421 NumSelIdents))
5422 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005423
5424 if (!Selectors.insert(MethList->Method->getSelector()))
5425 continue;
5426
Douglas Gregor13438f92010-04-06 16:40:00 +00005427 Result R(MethList->Method, 0);
5428 R.StartParameter = NumSelIdents;
5429 R.AllParametersAreInformative = false;
5430 Results.MaybeAddResult(R, CurContext);
5431 }
5432 }
5433 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005434 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005435
5436
5437 // If we're actually at the argument expression (rather than prior to the
5438 // selector), we're actually performing code completion for an expression.
5439 // Determine whether we have a single, best method. If so, we can
5440 // code-complete the expression using the corresponding parameter type as
5441 // our preferred type, improving completion results.
5442 if (AtArgumentExpression) {
5443 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5444 NumSelIdents);
5445 if (PreferredType.isNull())
5446 CodeCompleteOrdinaryName(S, PCC_Expression);
5447 else
5448 CodeCompleteExpression(S, PreferredType);
5449 return;
5450 }
5451
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005452 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005453 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005454 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005455}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005456
Douglas Gregorfb629412010-08-23 21:17:50 +00005457void Sema::CodeCompleteObjCForCollection(Scope *S,
5458 DeclGroupPtrTy IterationVar) {
5459 CodeCompleteExpressionData Data;
5460 Data.ObjCCollection = true;
5461
5462 if (IterationVar.getAsOpaquePtr()) {
5463 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5464 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5465 if (*I)
5466 Data.IgnoreDecls.push_back(*I);
5467 }
5468 }
5469
5470 CodeCompleteExpression(S, Data);
5471}
5472
Douglas Gregor458433d2010-08-26 15:07:07 +00005473void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5474 unsigned NumSelIdents) {
5475 // If we have an external source, load the entire class method
5476 // pool from the AST file.
5477 if (ExternalSource) {
5478 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5479 I != N; ++I) {
5480 Selector Sel = ExternalSource->GetExternalSelector(I);
5481 if (Sel.isNull() || MethodPool.count(Sel))
5482 continue;
5483
5484 ReadMethodPool(Sel);
5485 }
5486 }
5487
Douglas Gregor218937c2011-02-01 19:23:04 +00005488 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5489 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005490 Results.EnterNewScope();
5491 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5492 MEnd = MethodPool.end();
5493 M != MEnd; ++M) {
5494
5495 Selector Sel = M->first;
5496 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5497 continue;
5498
Douglas Gregor218937c2011-02-01 19:23:04 +00005499 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor458433d2010-08-26 15:07:07 +00005500 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005501 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005502 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005503 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005504 continue;
5505 }
5506
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005507 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005508 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005509 if (I == NumSelIdents) {
5510 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005511 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005512 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005513 Accumulator.clear();
5514 }
5515 }
5516
Benjamin Kramera0651c52011-07-26 16:59:25 +00005517 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005518 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005519 }
Douglas Gregordae68752011-02-01 22:57:45 +00005520 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005521 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005522 }
5523 Results.ExitScope();
5524
5525 HandleCodeCompleteResults(this, CodeCompleter,
5526 CodeCompletionContext::CCC_SelectorName,
5527 Results.data(), Results.size());
5528}
5529
Douglas Gregor55385fe2009-11-18 04:19:12 +00005530/// \brief Add all of the protocol declarations that we find in the given
5531/// (translation unit) context.
5532static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005533 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005534 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005535 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005536
5537 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5538 DEnd = Ctx->decls_end();
5539 D != DEnd; ++D) {
5540 // Record any protocols we find.
5541 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005542 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005543 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005544 }
5545}
5546
5547void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5548 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005549 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5550 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005551
Douglas Gregor70c23352010-12-09 21:44:02 +00005552 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5553 Results.EnterNewScope();
5554
5555 // Tell the result set to ignore all of the protocols we have
5556 // already seen.
5557 // FIXME: This doesn't work when caching code-completion results.
5558 for (unsigned I = 0; I != NumProtocols; ++I)
5559 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5560 Protocols[I].second))
5561 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005562
Douglas Gregor70c23352010-12-09 21:44:02 +00005563 // Add all protocols.
5564 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5565 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005566
Douglas Gregor70c23352010-12-09 21:44:02 +00005567 Results.ExitScope();
5568 }
5569
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005570 HandleCodeCompleteResults(this, CodeCompleter,
5571 CodeCompletionContext::CCC_ObjCProtocolName,
5572 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005573}
5574
5575void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005576 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5577 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005578
Douglas Gregor70c23352010-12-09 21:44:02 +00005579 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5580 Results.EnterNewScope();
5581
5582 // Add all protocols.
5583 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5584 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005585
Douglas Gregor70c23352010-12-09 21:44:02 +00005586 Results.ExitScope();
5587 }
5588
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005589 HandleCodeCompleteResults(this, CodeCompleter,
5590 CodeCompletionContext::CCC_ObjCProtocolName,
5591 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005592}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005593
5594/// \brief Add all of the Objective-C interface declarations that we find in
5595/// the given (translation unit) context.
5596static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5597 bool OnlyForwardDeclarations,
5598 bool OnlyUnimplemented,
5599 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005600 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005601
5602 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5603 DEnd = Ctx->decls_end();
5604 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005605 // Record any interfaces we find.
5606 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005607 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005608 (!OnlyUnimplemented || !Class->getImplementation()))
5609 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005610 }
5611}
5612
5613void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005614 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5615 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005616 Results.EnterNewScope();
5617
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005618 if (CodeCompleter->includeGlobals()) {
5619 // Add all classes.
5620 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5621 false, Results);
5622 }
5623
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005624 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005625
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005626 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005627 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005628 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005629}
5630
Douglas Gregorc83c6872010-04-15 22:33:43 +00005631void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5632 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005633 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005634 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005635 Results.EnterNewScope();
5636
5637 // Make sure that we ignore the class we're currently defining.
5638 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005639 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005640 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005641 Results.Ignore(CurClass);
5642
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005643 if (CodeCompleter->includeGlobals()) {
5644 // Add all classes.
5645 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5646 false, Results);
5647 }
5648
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005649 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005650
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005651 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005652 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005653 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005654}
5655
5656void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005657 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5658 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005659 Results.EnterNewScope();
5660
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005661 if (CodeCompleter->includeGlobals()) {
5662 // Add all unimplemented classes.
5663 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5664 true, Results);
5665 }
5666
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005667 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005668
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005669 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005670 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005671 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005672}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005673
5674void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005675 IdentifierInfo *ClassName,
5676 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005677 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005678
Douglas Gregor218937c2011-02-01 19:23:04 +00005679 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005680 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005681
5682 // Ignore any categories we find that have already been implemented by this
5683 // interface.
5684 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5685 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005686 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005687 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5688 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5689 Category = Category->getNextClassCategory())
5690 CategoryNames.insert(Category->getIdentifier());
5691
5692 // Add all of the categories we know about.
5693 Results.EnterNewScope();
5694 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5695 for (DeclContext::decl_iterator D = TU->decls_begin(),
5696 DEnd = TU->decls_end();
5697 D != DEnd; ++D)
5698 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5699 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005700 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005701 Results.ExitScope();
5702
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005703 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005704 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005705 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005706}
5707
5708void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005709 IdentifierInfo *ClassName,
5710 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005711 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005712
5713 // Find the corresponding interface. If we couldn't find the interface, the
5714 // program itself is ill-formed. However, we'll try to be helpful still by
5715 // providing the list of all of the categories we know about.
5716 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005717 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005718 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5719 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005720 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005721
Douglas Gregor218937c2011-02-01 19:23:04 +00005722 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005723 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005724
5725 // Add all of the categories that have have corresponding interface
5726 // declarations in this class and any of its superclasses, except for
5727 // already-implemented categories in the class itself.
5728 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5729 Results.EnterNewScope();
5730 bool IgnoreImplemented = true;
5731 while (Class) {
5732 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5733 Category = Category->getNextClassCategory())
5734 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5735 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005736 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005737
5738 Class = Class->getSuperClass();
5739 IgnoreImplemented = false;
5740 }
5741 Results.ExitScope();
5742
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005743 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005744 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005745 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005746}
Douglas Gregor322328b2009-11-18 22:32:06 +00005747
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005748void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005749 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005750 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5751 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005752
5753 // Figure out where this @synthesize lives.
5754 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005755 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005756 if (!Container ||
5757 (!isa<ObjCImplementationDecl>(Container) &&
5758 !isa<ObjCCategoryImplDecl>(Container)))
5759 return;
5760
5761 // Ignore any properties that have already been implemented.
5762 for (DeclContext::decl_iterator D = Container->decls_begin(),
5763 DEnd = Container->decls_end();
5764 D != DEnd; ++D)
5765 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5766 Results.Ignore(PropertyImpl->getPropertyDecl());
5767
5768 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005769 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005770 Results.EnterNewScope();
5771 if (ObjCImplementationDecl *ClassImpl
5772 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005773 AddObjCProperties(ClassImpl->getClassInterface(), false,
5774 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005775 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005776 else
5777 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005778 false, /*AllowNullaryMethods=*/false, CurContext,
5779 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005780 Results.ExitScope();
5781
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005782 HandleCodeCompleteResults(this, CodeCompleter,
5783 CodeCompletionContext::CCC_Other,
5784 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005785}
5786
5787void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005788 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005789 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005790 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5791 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005792
5793 // Figure out where this @synthesize lives.
5794 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005795 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005796 if (!Container ||
5797 (!isa<ObjCImplementationDecl>(Container) &&
5798 !isa<ObjCCategoryImplDecl>(Container)))
5799 return;
5800
5801 // Figure out which interface we're looking into.
5802 ObjCInterfaceDecl *Class = 0;
5803 if (ObjCImplementationDecl *ClassImpl
5804 = dyn_cast<ObjCImplementationDecl>(Container))
5805 Class = ClassImpl->getClassInterface();
5806 else
5807 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5808 ->getClassInterface();
5809
Douglas Gregore8426052011-04-18 14:40:46 +00005810 // Determine the type of the property we're synthesizing.
5811 QualType PropertyType = Context.getObjCIdType();
5812 if (Class) {
5813 if (ObjCPropertyDecl *Property
5814 = Class->FindPropertyDeclaration(PropertyName)) {
5815 PropertyType
5816 = Property->getType().getNonReferenceType().getUnqualifiedType();
5817
5818 // Give preference to ivars
5819 Results.setPreferredType(PropertyType);
5820 }
5821 }
5822
Douglas Gregor322328b2009-11-18 22:32:06 +00005823 // Add all of the instance variables in this class and its superclasses.
5824 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005825 bool SawSimilarlyNamedIvar = false;
5826 std::string NameWithPrefix;
5827 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005828 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005829 std::string NameWithSuffix = PropertyName->getName().str();
5830 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005831 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005832 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5833 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005834 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5835
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005836 // Determine whether we've seen an ivar with a name similar to the
5837 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005838 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005839 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005840 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005841 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005842
5843 // Reduce the priority of this result by one, to give it a slight
5844 // advantage over other results whose names don't match so closely.
5845 if (Results.size() &&
5846 Results.data()[Results.size() - 1].Kind
5847 == CodeCompletionResult::RK_Declaration &&
5848 Results.data()[Results.size() - 1].Declaration == Ivar)
5849 Results.data()[Results.size() - 1].Priority--;
5850 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005851 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005852 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005853
5854 if (!SawSimilarlyNamedIvar) {
5855 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005856 // an ivar of the appropriate type.
5857 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005858 typedef CodeCompletionResult Result;
5859 CodeCompletionAllocator &Allocator = Results.getAllocator();
5860 CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available);
5861
Douglas Gregor8987b232011-09-27 23:30:47 +00005862 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00005863 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005864 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005865 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5866 Results.AddResult(Result(Builder.TakeString(), Priority,
5867 CXCursor_ObjCIvarDecl));
5868 }
5869
Douglas Gregor322328b2009-11-18 22:32:06 +00005870 Results.ExitScope();
5871
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005872 HandleCodeCompleteResults(this, CodeCompleter,
5873 CodeCompletionContext::CCC_Other,
5874 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005875}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005876
Douglas Gregor408be5a2010-08-25 01:08:01 +00005877// Mapping from selectors to the methods that implement that selector, along
5878// with the "in original class" flag.
5879typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5880 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005881
5882/// \brief Find all of the methods that reside in the given container
5883/// (and its superclasses, protocols, etc.) that meet the given
5884/// criteria. Insert those methods into the map of known methods,
5885/// indexed by selector so they can be easily found.
5886static void FindImplementableMethods(ASTContext &Context,
5887 ObjCContainerDecl *Container,
5888 bool WantInstanceMethods,
5889 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00005890 KnownMethodsMap &KnownMethods,
5891 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005892 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5893 // Recurse into protocols.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00005894 if (!IFace->hasDefinition())
5895 return;
5896
Douglas Gregore8f5a172010-04-07 00:21:17 +00005897 const ObjCList<ObjCProtocolDecl> &Protocols
5898 = IFace->getReferencedProtocols();
5899 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005900 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005901 I != E; ++I)
5902 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005903 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005904
Douglas Gregorea766182010-10-18 18:21:28 +00005905 // Add methods from any class extensions and categories.
5906 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5907 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00005908 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5909 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005910 KnownMethods, false);
5911
5912 // Visit the superclass.
5913 if (IFace->getSuperClass())
5914 FindImplementableMethods(Context, IFace->getSuperClass(),
5915 WantInstanceMethods, ReturnType,
5916 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005917 }
5918
5919 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5920 // Recurse into protocols.
5921 const ObjCList<ObjCProtocolDecl> &Protocols
5922 = Category->getReferencedProtocols();
5923 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005924 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005925 I != E; ++I)
5926 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005927 KnownMethods, InOriginalClass);
5928
5929 // If this category is the original class, jump to the interface.
5930 if (InOriginalClass && Category->getClassInterface())
5931 FindImplementableMethods(Context, Category->getClassInterface(),
5932 WantInstanceMethods, ReturnType, KnownMethods,
5933 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005934 }
5935
5936 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005937 if (Protocol->hasDefinition()) {
5938 // Recurse into protocols.
5939 const ObjCList<ObjCProtocolDecl> &Protocols
5940 = Protocol->getReferencedProtocols();
5941 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5942 E = Protocols.end();
5943 I != E; ++I)
5944 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
5945 KnownMethods, false);
5946 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00005947 }
5948
5949 // Add methods in this container. This operation occurs last because
5950 // we want the methods from this container to override any methods
5951 // we've previously seen with the same selector.
5952 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
5953 MEnd = Container->meth_end();
5954 M != MEnd; ++M) {
5955 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
5956 if (!ReturnType.isNull() &&
5957 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
5958 continue;
5959
Douglas Gregor408be5a2010-08-25 01:08:01 +00005960 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005961 }
5962 }
5963}
5964
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005965/// \brief Add the parenthesized return or parameter type chunk to a code
5966/// completion string.
5967static void AddObjCPassingTypeChunk(QualType Type,
5968 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005969 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005970 CodeCompletionBuilder &Builder) {
5971 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor8987b232011-09-27 23:30:47 +00005972 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005973 Builder.getAllocator()));
5974 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5975}
5976
5977/// \brief Determine whether the given class is or inherits from a class by
5978/// the given name.
5979static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00005980 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005981 if (!Class)
5982 return false;
5983
5984 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
5985 return true;
5986
5987 return InheritsFromClassNamed(Class->getSuperClass(), Name);
5988}
5989
5990/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
5991/// Key-Value Observing (KVO).
5992static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
5993 bool IsInstanceMethod,
5994 QualType ReturnType,
5995 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00005996 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005997 ResultBuilder &Results) {
5998 IdentifierInfo *PropName = Property->getIdentifier();
5999 if (!PropName || PropName->getLength() == 0)
6000 return;
6001
Douglas Gregor8987b232011-09-27 23:30:47 +00006002 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6003
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006004 // Builder that will create each code completion.
6005 typedef CodeCompletionResult Result;
6006 CodeCompletionAllocator &Allocator = Results.getAllocator();
6007 CodeCompletionBuilder Builder(Allocator);
6008
6009 // The selector table.
6010 SelectorTable &Selectors = Context.Selectors;
6011
6012 // The property name, copied into the code completion allocation region
6013 // on demand.
6014 struct KeyHolder {
6015 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006016 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006017 const char *CopiedKey;
6018
Chris Lattner5f9e2722011-07-23 10:55:15 +00006019 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006020 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6021
6022 operator const char *() {
6023 if (CopiedKey)
6024 return CopiedKey;
6025
6026 return CopiedKey = Allocator.CopyString(Key);
6027 }
6028 } Key(Allocator, PropName->getName());
6029
6030 // The uppercased name of the property name.
6031 std::string UpperKey = PropName->getName();
6032 if (!UpperKey.empty())
6033 UpperKey[0] = toupper(UpperKey[0]);
6034
6035 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6036 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6037 Property->getType());
6038 bool ReturnTypeMatchesVoid
6039 = ReturnType.isNull() || ReturnType->isVoidType();
6040
6041 // Add the normal accessor -(type)key.
6042 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006043 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006044 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6045 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00006046 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006047
6048 Builder.AddTypedTextChunk(Key);
6049 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6050 CXCursor_ObjCInstanceMethodDecl));
6051 }
6052
6053 // If we have an integral or boolean property (or the user has provided
6054 // an integral or boolean return type), add the accessor -(type)isKey.
6055 if (IsInstanceMethod &&
6056 ((!ReturnType.isNull() &&
6057 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6058 (ReturnType.isNull() &&
6059 (Property->getType()->isIntegerType() ||
6060 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006061 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006062 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006063 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006064 if (ReturnType.isNull()) {
6065 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6066 Builder.AddTextChunk("BOOL");
6067 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6068 }
6069
6070 Builder.AddTypedTextChunk(
6071 Allocator.CopyString(SelectorId->getName()));
6072 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6073 CXCursor_ObjCInstanceMethodDecl));
6074 }
6075 }
6076
6077 // Add the normal mutator.
6078 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6079 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006080 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006081 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006082 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006083 if (ReturnType.isNull()) {
6084 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6085 Builder.AddTextChunk("void");
6086 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6087 }
6088
6089 Builder.AddTypedTextChunk(
6090 Allocator.CopyString(SelectorId->getName()));
6091 Builder.AddTypedTextChunk(":");
Douglas Gregor8987b232011-09-27 23:30:47 +00006092 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006093 Builder.AddTextChunk(Key);
6094 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6095 CXCursor_ObjCInstanceMethodDecl));
6096 }
6097 }
6098
6099 // Indexed and unordered accessors
6100 unsigned IndexedGetterPriority = CCP_CodePattern;
6101 unsigned IndexedSetterPriority = CCP_CodePattern;
6102 unsigned UnorderedGetterPriority = CCP_CodePattern;
6103 unsigned UnorderedSetterPriority = CCP_CodePattern;
6104 if (const ObjCObjectPointerType *ObjCPointer
6105 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6106 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6107 // If this interface type is not provably derived from a known
6108 // collection, penalize the corresponding completions.
6109 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6110 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6111 if (!InheritsFromClassNamed(IFace, "NSArray"))
6112 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6113 }
6114
6115 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6116 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6117 if (!InheritsFromClassNamed(IFace, "NSSet"))
6118 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6119 }
6120 }
6121 } else {
6122 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6123 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6124 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6125 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6126 }
6127
6128 // Add -(NSUInteger)countOf<key>
6129 if (IsInstanceMethod &&
6130 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006131 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006132 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006133 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006134 if (ReturnType.isNull()) {
6135 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6136 Builder.AddTextChunk("NSUInteger");
6137 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6138 }
6139
6140 Builder.AddTypedTextChunk(
6141 Allocator.CopyString(SelectorId->getName()));
6142 Results.AddResult(Result(Builder.TakeString(),
6143 std::min(IndexedGetterPriority,
6144 UnorderedGetterPriority),
6145 CXCursor_ObjCInstanceMethodDecl));
6146 }
6147 }
6148
6149 // Indexed getters
6150 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6151 if (IsInstanceMethod &&
6152 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006153 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006154 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006155 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006156 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006157 if (ReturnType.isNull()) {
6158 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6159 Builder.AddTextChunk("id");
6160 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6161 }
6162
6163 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6164 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6165 Builder.AddTextChunk("NSUInteger");
6166 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6167 Builder.AddTextChunk("index");
6168 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6169 CXCursor_ObjCInstanceMethodDecl));
6170 }
6171 }
6172
6173 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6174 if (IsInstanceMethod &&
6175 (ReturnType.isNull() ||
6176 (ReturnType->isObjCObjectPointerType() &&
6177 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6178 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6179 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006180 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006181 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006182 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006183 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006184 if (ReturnType.isNull()) {
6185 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6186 Builder.AddTextChunk("NSArray *");
6187 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6188 }
6189
6190 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6191 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6192 Builder.AddTextChunk("NSIndexSet *");
6193 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6194 Builder.AddTextChunk("indexes");
6195 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6196 CXCursor_ObjCInstanceMethodDecl));
6197 }
6198 }
6199
6200 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6201 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006202 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006203 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006204 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006205 &Context.Idents.get("range")
6206 };
6207
Douglas Gregore74c25c2011-05-04 23:50:46 +00006208 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006209 if (ReturnType.isNull()) {
6210 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6211 Builder.AddTextChunk("void");
6212 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6213 }
6214
6215 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6216 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6217 Builder.AddPlaceholderChunk("object-type");
6218 Builder.AddTextChunk(" **");
6219 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6220 Builder.AddTextChunk("buffer");
6221 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6222 Builder.AddTypedTextChunk("range:");
6223 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6224 Builder.AddTextChunk("NSRange");
6225 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6226 Builder.AddTextChunk("inRange");
6227 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6228 CXCursor_ObjCInstanceMethodDecl));
6229 }
6230 }
6231
6232 // Mutable indexed accessors
6233
6234 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6235 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006236 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006237 IdentifierInfo *SelectorIds[2] = {
6238 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006239 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006240 };
6241
Douglas Gregore74c25c2011-05-04 23:50:46 +00006242 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006243 if (ReturnType.isNull()) {
6244 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6245 Builder.AddTextChunk("void");
6246 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6247 }
6248
6249 Builder.AddTypedTextChunk("insertObject:");
6250 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6251 Builder.AddPlaceholderChunk("object-type");
6252 Builder.AddTextChunk(" *");
6253 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6254 Builder.AddTextChunk("object");
6255 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6256 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6257 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6258 Builder.AddPlaceholderChunk("NSUInteger");
6259 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6260 Builder.AddTextChunk("index");
6261 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6262 CXCursor_ObjCInstanceMethodDecl));
6263 }
6264 }
6265
6266 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6267 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006268 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006269 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006270 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006271 &Context.Idents.get("atIndexes")
6272 };
6273
Douglas Gregore74c25c2011-05-04 23:50:46 +00006274 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006275 if (ReturnType.isNull()) {
6276 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6277 Builder.AddTextChunk("void");
6278 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6279 }
6280
6281 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6282 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6283 Builder.AddTextChunk("NSArray *");
6284 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6285 Builder.AddTextChunk("array");
6286 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6287 Builder.AddTypedTextChunk("atIndexes:");
6288 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6289 Builder.AddPlaceholderChunk("NSIndexSet *");
6290 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6291 Builder.AddTextChunk("indexes");
6292 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6293 CXCursor_ObjCInstanceMethodDecl));
6294 }
6295 }
6296
6297 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6298 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006299 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006300 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006301 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006302 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006303 if (ReturnType.isNull()) {
6304 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6305 Builder.AddTextChunk("void");
6306 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6307 }
6308
6309 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6310 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6311 Builder.AddTextChunk("NSUInteger");
6312 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6313 Builder.AddTextChunk("index");
6314 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6315 CXCursor_ObjCInstanceMethodDecl));
6316 }
6317 }
6318
6319 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6320 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006321 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006322 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006323 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006324 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006325 if (ReturnType.isNull()) {
6326 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6327 Builder.AddTextChunk("void");
6328 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6329 }
6330
6331 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6332 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6333 Builder.AddTextChunk("NSIndexSet *");
6334 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6335 Builder.AddTextChunk("indexes");
6336 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6337 CXCursor_ObjCInstanceMethodDecl));
6338 }
6339 }
6340
6341 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6342 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006343 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006344 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006345 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006346 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006347 &Context.Idents.get("withObject")
6348 };
6349
Douglas Gregore74c25c2011-05-04 23:50:46 +00006350 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006351 if (ReturnType.isNull()) {
6352 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6353 Builder.AddTextChunk("void");
6354 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6355 }
6356
6357 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6358 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6359 Builder.AddPlaceholderChunk("NSUInteger");
6360 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6361 Builder.AddTextChunk("index");
6362 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6363 Builder.AddTypedTextChunk("withObject:");
6364 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6365 Builder.AddTextChunk("id");
6366 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6367 Builder.AddTextChunk("object");
6368 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6369 CXCursor_ObjCInstanceMethodDecl));
6370 }
6371 }
6372
6373 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6374 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006375 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006376 = (Twine("replace") + UpperKey + "AtIndexes").str();
6377 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006378 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006379 &Context.Idents.get(SelectorName1),
6380 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006381 };
6382
Douglas Gregore74c25c2011-05-04 23:50:46 +00006383 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006384 if (ReturnType.isNull()) {
6385 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6386 Builder.AddTextChunk("void");
6387 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6388 }
6389
6390 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6391 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6392 Builder.AddPlaceholderChunk("NSIndexSet *");
6393 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6394 Builder.AddTextChunk("indexes");
6395 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6396 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6397 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6398 Builder.AddTextChunk("NSArray *");
6399 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6400 Builder.AddTextChunk("array");
6401 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6402 CXCursor_ObjCInstanceMethodDecl));
6403 }
6404 }
6405
6406 // Unordered getters
6407 // - (NSEnumerator *)enumeratorOfKey
6408 if (IsInstanceMethod &&
6409 (ReturnType.isNull() ||
6410 (ReturnType->isObjCObjectPointerType() &&
6411 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6412 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6413 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006414 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006415 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006416 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006417 if (ReturnType.isNull()) {
6418 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6419 Builder.AddTextChunk("NSEnumerator *");
6420 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6421 }
6422
6423 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6424 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6425 CXCursor_ObjCInstanceMethodDecl));
6426 }
6427 }
6428
6429 // - (type *)memberOfKey:(type *)object
6430 if (IsInstanceMethod &&
6431 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006432 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006433 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006434 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006435 if (ReturnType.isNull()) {
6436 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6437 Builder.AddPlaceholderChunk("object-type");
6438 Builder.AddTextChunk(" *");
6439 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6440 }
6441
6442 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6443 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6444 if (ReturnType.isNull()) {
6445 Builder.AddPlaceholderChunk("object-type");
6446 Builder.AddTextChunk(" *");
6447 } else {
6448 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006449 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006450 Builder.getAllocator()));
6451 }
6452 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6453 Builder.AddTextChunk("object");
6454 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6455 CXCursor_ObjCInstanceMethodDecl));
6456 }
6457 }
6458
6459 // Mutable unordered accessors
6460 // - (void)addKeyObject:(type *)object
6461 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006462 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006463 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006464 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006465 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006466 if (ReturnType.isNull()) {
6467 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6468 Builder.AddTextChunk("void");
6469 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6470 }
6471
6472 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6473 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6474 Builder.AddPlaceholderChunk("object-type");
6475 Builder.AddTextChunk(" *");
6476 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6477 Builder.AddTextChunk("object");
6478 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6479 CXCursor_ObjCInstanceMethodDecl));
6480 }
6481 }
6482
6483 // - (void)addKey:(NSSet *)objects
6484 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006485 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006486 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006487 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006488 if (ReturnType.isNull()) {
6489 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6490 Builder.AddTextChunk("void");
6491 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6492 }
6493
6494 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6495 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6496 Builder.AddTextChunk("NSSet *");
6497 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6498 Builder.AddTextChunk("objects");
6499 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6500 CXCursor_ObjCInstanceMethodDecl));
6501 }
6502 }
6503
6504 // - (void)removeKeyObject:(type *)object
6505 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006506 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006507 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006508 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006509 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006510 if (ReturnType.isNull()) {
6511 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6512 Builder.AddTextChunk("void");
6513 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6514 }
6515
6516 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6517 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6518 Builder.AddPlaceholderChunk("object-type");
6519 Builder.AddTextChunk(" *");
6520 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6521 Builder.AddTextChunk("object");
6522 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6523 CXCursor_ObjCInstanceMethodDecl));
6524 }
6525 }
6526
6527 // - (void)removeKey:(NSSet *)objects
6528 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006529 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006530 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006531 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006532 if (ReturnType.isNull()) {
6533 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6534 Builder.AddTextChunk("void");
6535 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6536 }
6537
6538 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6539 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6540 Builder.AddTextChunk("NSSet *");
6541 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6542 Builder.AddTextChunk("objects");
6543 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6544 CXCursor_ObjCInstanceMethodDecl));
6545 }
6546 }
6547
6548 // - (void)intersectKey:(NSSet *)objects
6549 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006550 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006551 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006552 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006553 if (ReturnType.isNull()) {
6554 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6555 Builder.AddTextChunk("void");
6556 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6557 }
6558
6559 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6560 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6561 Builder.AddTextChunk("NSSet *");
6562 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6563 Builder.AddTextChunk("objects");
6564 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6565 CXCursor_ObjCInstanceMethodDecl));
6566 }
6567 }
6568
6569 // Key-Value Observing
6570 // + (NSSet *)keyPathsForValuesAffectingKey
6571 if (!IsInstanceMethod &&
6572 (ReturnType.isNull() ||
6573 (ReturnType->isObjCObjectPointerType() &&
6574 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6575 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6576 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006577 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006578 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006579 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006580 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006581 if (ReturnType.isNull()) {
6582 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6583 Builder.AddTextChunk("NSSet *");
6584 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6585 }
6586
6587 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6588 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006589 CXCursor_ObjCClassMethodDecl));
6590 }
6591 }
6592
6593 // + (BOOL)automaticallyNotifiesObserversForKey
6594 if (!IsInstanceMethod &&
6595 (ReturnType.isNull() ||
6596 ReturnType->isIntegerType() ||
6597 ReturnType->isBooleanType())) {
6598 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006599 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006600 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6601 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6602 if (ReturnType.isNull()) {
6603 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6604 Builder.AddTextChunk("BOOL");
6605 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6606 }
6607
6608 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6609 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6610 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006611 }
6612 }
6613}
6614
Douglas Gregore8f5a172010-04-07 00:21:17 +00006615void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6616 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006617 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006618 // Determine the return type of the method we're declaring, if
6619 // provided.
6620 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006621 Decl *IDecl = 0;
6622 if (CurContext->isObjCContainer()) {
6623 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6624 IDecl = cast<Decl>(OCD);
6625 }
Douglas Gregorea766182010-10-18 18:21:28 +00006626 // Determine where we should start searching for methods.
6627 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006628 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006629 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006630 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6631 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006632 IsInImplementation = true;
6633 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006634 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006635 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006636 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006637 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006638 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006639 }
6640
6641 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006642 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006643 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006644 }
6645
Douglas Gregorea766182010-10-18 18:21:28 +00006646 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006647 HandleCodeCompleteResults(this, CodeCompleter,
6648 CodeCompletionContext::CCC_Other,
6649 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006650 return;
6651 }
6652
6653 // Find all of the methods that we could declare/implement here.
6654 KnownMethodsMap KnownMethods;
6655 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006656 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006657
Douglas Gregore8f5a172010-04-07 00:21:17 +00006658 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006659 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006660 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6661 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006662 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006663 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006664 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6665 MEnd = KnownMethods.end();
6666 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006667 ObjCMethodDecl *Method = M->second.first;
Douglas Gregor218937c2011-02-01 19:23:04 +00006668 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006669
6670 // If the result type was not already provided, add it to the
6671 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006672 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00006673 AddObjCPassingTypeChunk(Method->getResultType(), Context, Policy,
6674 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006675
6676 Selector Sel = Method->getSelector();
6677
6678 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006679 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006680 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006681
6682 // Add parameters to the pattern.
6683 unsigned I = 0;
6684 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6685 PEnd = Method->param_end();
6686 P != PEnd; (void)++P, ++I) {
6687 // Add the part of the selector name.
6688 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006689 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006690 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006691 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6692 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006693 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006694 } else
6695 break;
6696
6697 // Add the parameter type.
Douglas Gregor8987b232011-09-27 23:30:47 +00006698 AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Policy,
6699 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006700
6701 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006702 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006703 }
6704
6705 if (Method->isVariadic()) {
6706 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006707 Builder.AddChunk(CodeCompletionString::CK_Comma);
6708 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006709 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006710
Douglas Gregor447107d2010-05-28 00:57:46 +00006711 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006712 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006713 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6714 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6715 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006716 if (!Method->getResultType()->isVoidType()) {
6717 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006718 Builder.AddTextChunk("return");
6719 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6720 Builder.AddPlaceholderChunk("expression");
6721 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006722 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006723 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006724
Douglas Gregor218937c2011-02-01 19:23:04 +00006725 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6726 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006727 }
6728
Douglas Gregor408be5a2010-08-25 01:08:01 +00006729 unsigned Priority = CCP_CodePattern;
6730 if (!M->second.second)
6731 Priority += CCD_InBaseClass;
6732
Douglas Gregorba103062012-03-27 23:34:16 +00006733 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006734 }
6735
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006736 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6737 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006738 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006739 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006740 Containers.push_back(SearchDecl);
6741
Douglas Gregore74c25c2011-05-04 23:50:46 +00006742 VisitedSelectorSet KnownSelectors;
6743 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6744 MEnd = KnownMethods.end();
6745 M != MEnd; ++M)
6746 KnownSelectors.insert(M->first);
6747
6748
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006749 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6750 if (!IFace)
6751 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6752 IFace = Category->getClassInterface();
6753
6754 if (IFace) {
6755 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6756 Category = Category->getNextClassCategory())
6757 Containers.push_back(Category);
6758 }
6759
6760 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6761 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6762 PEnd = Containers[I]->prop_end();
6763 P != PEnd; ++P) {
6764 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006765 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006766 }
6767 }
6768 }
6769
Douglas Gregore8f5a172010-04-07 00:21:17 +00006770 Results.ExitScope();
6771
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006772 HandleCodeCompleteResults(this, CodeCompleter,
6773 CodeCompletionContext::CCC_Other,
6774 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006775}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006776
6777void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6778 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006779 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006780 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006781 IdentifierInfo **SelIdents,
6782 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006783 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006784 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006785 if (ExternalSource) {
6786 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6787 I != N; ++I) {
6788 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006789 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006790 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006791
6792 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006793 }
6794 }
6795
6796 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006797 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006798 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6799 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006800
6801 if (ReturnTy)
6802 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006803
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006804 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006805 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6806 MEnd = MethodPool.end();
6807 M != MEnd; ++M) {
6808 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6809 &M->second.second;
6810 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006811 MethList = MethList->Next) {
6812 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6813 NumSelIdents))
6814 continue;
6815
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006816 if (AtParameterName) {
6817 // Suggest parameter names we've seen before.
6818 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6819 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6820 if (Param->getIdentifier()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006821 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregordae68752011-02-01 22:57:45 +00006822 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006823 Param->getIdentifier()->getName()));
6824 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006825 }
6826 }
6827
6828 continue;
6829 }
6830
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006831 Result R(MethList->Method, 0);
6832 R.StartParameter = NumSelIdents;
6833 R.AllParametersAreInformative = false;
6834 R.DeclaringEntity = true;
6835 Results.MaybeAddResult(R, CurContext);
6836 }
6837 }
6838
6839 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006840 HandleCodeCompleteResults(this, CodeCompleter,
6841 CodeCompletionContext::CCC_Other,
6842 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006843}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006844
Douglas Gregorf29c5232010-08-24 22:20:20 +00006845void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006846 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006847 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006848 Results.EnterNewScope();
6849
6850 // #if <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006851 CodeCompletionBuilder Builder(Results.getAllocator());
6852 Builder.AddTypedTextChunk("if");
6853 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6854 Builder.AddPlaceholderChunk("condition");
6855 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006856
6857 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006858 Builder.AddTypedTextChunk("ifdef");
6859 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6860 Builder.AddPlaceholderChunk("macro");
6861 Results.AddResult(Builder.TakeString());
6862
Douglas Gregorf44e8542010-08-24 19:08:16 +00006863 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006864 Builder.AddTypedTextChunk("ifndef");
6865 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6866 Builder.AddPlaceholderChunk("macro");
6867 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006868
6869 if (InConditional) {
6870 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006871 Builder.AddTypedTextChunk("elif");
6872 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6873 Builder.AddPlaceholderChunk("condition");
6874 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006875
6876 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00006877 Builder.AddTypedTextChunk("else");
6878 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006879
6880 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00006881 Builder.AddTypedTextChunk("endif");
6882 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006883 }
6884
6885 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006886 Builder.AddTypedTextChunk("include");
6887 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6888 Builder.AddTextChunk("\"");
6889 Builder.AddPlaceholderChunk("header");
6890 Builder.AddTextChunk("\"");
6891 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006892
6893 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006894 Builder.AddTypedTextChunk("include");
6895 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6896 Builder.AddTextChunk("<");
6897 Builder.AddPlaceholderChunk("header");
6898 Builder.AddTextChunk(">");
6899 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006900
6901 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006902 Builder.AddTypedTextChunk("define");
6903 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6904 Builder.AddPlaceholderChunk("macro");
6905 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006906
6907 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00006908 Builder.AddTypedTextChunk("define");
6909 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6910 Builder.AddPlaceholderChunk("macro");
6911 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6912 Builder.AddPlaceholderChunk("args");
6913 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6914 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006915
6916 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006917 Builder.AddTypedTextChunk("undef");
6918 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6919 Builder.AddPlaceholderChunk("macro");
6920 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006921
6922 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00006923 Builder.AddTypedTextChunk("line");
6924 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6925 Builder.AddPlaceholderChunk("number");
6926 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006927
6928 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00006929 Builder.AddTypedTextChunk("line");
6930 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6931 Builder.AddPlaceholderChunk("number");
6932 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6933 Builder.AddTextChunk("\"");
6934 Builder.AddPlaceholderChunk("filename");
6935 Builder.AddTextChunk("\"");
6936 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006937
6938 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006939 Builder.AddTypedTextChunk("error");
6940 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6941 Builder.AddPlaceholderChunk("message");
6942 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006943
6944 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00006945 Builder.AddTypedTextChunk("pragma");
6946 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6947 Builder.AddPlaceholderChunk("arguments");
6948 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006949
David Blaikie4e4d0842012-03-11 07:00:24 +00006950 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00006951 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006952 Builder.AddTypedTextChunk("import");
6953 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6954 Builder.AddTextChunk("\"");
6955 Builder.AddPlaceholderChunk("header");
6956 Builder.AddTextChunk("\"");
6957 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006958
6959 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006960 Builder.AddTypedTextChunk("import");
6961 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6962 Builder.AddTextChunk("<");
6963 Builder.AddPlaceholderChunk("header");
6964 Builder.AddTextChunk(">");
6965 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006966 }
6967
6968 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006969 Builder.AddTypedTextChunk("include_next");
6970 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6971 Builder.AddTextChunk("\"");
6972 Builder.AddPlaceholderChunk("header");
6973 Builder.AddTextChunk("\"");
6974 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006975
6976 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006977 Builder.AddTypedTextChunk("include_next");
6978 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6979 Builder.AddTextChunk("<");
6980 Builder.AddPlaceholderChunk("header");
6981 Builder.AddTextChunk(">");
6982 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006983
6984 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006985 Builder.AddTypedTextChunk("warning");
6986 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6987 Builder.AddPlaceholderChunk("message");
6988 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006989
6990 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
6991 // completions for them. And __include_macros is a Clang-internal extension
6992 // that we don't want to encourage anyone to use.
6993
6994 // FIXME: we don't support #assert or #unassert, so don't suggest them.
6995 Results.ExitScope();
6996
Douglas Gregorf44e8542010-08-24 19:08:16 +00006997 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00006998 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00006999 Results.data(), Results.size());
7000}
7001
7002void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007003 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007004 S->getFnParent()? Sema::PCC_RecoveryInFunction
7005 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007006}
7007
Douglas Gregorf29c5232010-08-24 22:20:20 +00007008void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007009 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007010 IsDefinition? CodeCompletionContext::CCC_MacroName
7011 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007012 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7013 // Add just the names of macros, not their arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00007014 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007015 Results.EnterNewScope();
7016 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7017 MEnd = PP.macro_end();
7018 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007019 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007020 M->first->getName()));
7021 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007022 }
7023 Results.ExitScope();
7024 } else if (IsDefinition) {
7025 // FIXME: Can we detect when the user just wrote an include guard above?
7026 }
7027
Douglas Gregor52779fb2010-09-23 23:01:17 +00007028 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007029 Results.data(), Results.size());
7030}
7031
Douglas Gregorf29c5232010-08-24 22:20:20 +00007032void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007033 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007034 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007035
7036 if (!CodeCompleter || CodeCompleter->includeMacros())
7037 AddMacroResults(PP, Results);
7038
7039 // defined (<macro>)
7040 Results.EnterNewScope();
Douglas Gregor218937c2011-02-01 19:23:04 +00007041 CodeCompletionBuilder Builder(Results.getAllocator());
7042 Builder.AddTypedTextChunk("defined");
7043 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7044 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7045 Builder.AddPlaceholderChunk("macro");
7046 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7047 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007048 Results.ExitScope();
7049
7050 HandleCodeCompleteResults(this, CodeCompleter,
7051 CodeCompletionContext::CCC_PreprocessorExpression,
7052 Results.data(), Results.size());
7053}
7054
7055void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7056 IdentifierInfo *Macro,
7057 MacroInfo *MacroInfo,
7058 unsigned Argument) {
7059 // FIXME: In the future, we could provide "overload" results, much like we
7060 // do for function calls.
7061
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007062 // Now just ignore this. There will be another code-completion callback
7063 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007064}
7065
Douglas Gregor55817af2010-08-25 17:04:25 +00007066void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007067 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007068 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007069 0, 0);
7070}
7071
Douglas Gregordae68752011-02-01 22:57:45 +00007072void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007073 SmallVectorImpl<CodeCompletionResult> &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007074 ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007075 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7076 CodeCompletionDeclConsumer Consumer(Builder,
7077 Context.getTranslationUnitDecl());
7078 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7079 Consumer);
7080 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007081
7082 if (!CodeCompleter || CodeCompleter->includeMacros())
7083 AddMacroResults(PP, Builder);
7084
7085 Results.clear();
7086 Results.insert(Results.end(),
7087 Builder.data(), Builder.data() + Builder.size());
7088}