blob: ab8cac8944aa8d9f0e29993668141b344a6a2c5f [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"
John McCall7cd088e2010-08-24 07:21:54 +000014#include "clang/AST/DeclObjC.h"
Douglas Gregorb9d0ef72009-09-21 19:57:38 +000015#include "clang/AST/ExprCXX.h"
Douglas Gregor24a069f2009-11-17 17:59:40 +000016#include "clang/AST/ExprObjC.h"
Douglas Gregorc5b2e582012-01-29 18:15:03 +000017#include "clang/Lex/HeaderSearch.h"
Douglas Gregor3f7c7f42009-10-30 16:50:04 +000018#include "clang/Lex/MacroInfo.h"
19#include "clang/Lex/Preprocessor.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000020#include "clang/Sema/CodeCompleteConsumer.h"
21#include "clang/Sema/ExternalSemaSource.h"
22#include "clang/Sema/Lookup.h"
23#include "clang/Sema/Overload.h"
24#include "clang/Sema/Scope.h"
25#include "clang/Sema/ScopeInfo.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;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000126
127 CodeCompletionTUInfo &CCTUInfo;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000128
129 /// \brief If non-NULL, a filter function used to remove any code-completion
130 /// results that are not desirable.
131 LookupFilter Filter;
Douglas Gregor45bcd432010-01-14 03:21:49 +0000132
133 /// \brief Whether we should allow declarations as
134 /// nested-name-specifiers that would otherwise be filtered out.
135 bool AllowNestedNameSpecifiers;
136
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000137 /// \brief If set, the type that we would prefer our resulting value
138 /// declarations to have.
139 ///
140 /// Closely matching the preferred type gives a boost to a result's
141 /// priority.
142 CanQualType PreferredType;
143
Douglas Gregor86d9a522009-09-21 16:56:56 +0000144 /// \brief A list of shadow maps, which is used to model name hiding at
145 /// different levels of, e.g., the inheritance hierarchy.
146 std::list<ShadowMap> ShadowMaps;
147
Douglas Gregor3cdee122010-08-26 16:36:48 +0000148 /// \brief If we're potentially referring to a C++ member function, the set
149 /// of qualifiers applied to the object type.
150 Qualifiers ObjectTypeQualifiers;
151
152 /// \brief Whether the \p ObjectTypeQualifiers field is active.
153 bool HasObjectTypeQualifiers;
154
Douglas Gregor265f7492010-08-27 15:29:55 +0000155 /// \brief The selector that we prefer.
156 Selector PreferredSelector;
157
Douglas Gregorca45da02010-11-02 20:36:02 +0000158 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000159 CodeCompletionContext CompletionContext;
160
James Dennetta40f7922012-06-14 03:11:41 +0000161 /// \brief If we are in an instance method definition, the \@implementation
Douglas Gregorca45da02010-11-02 20:36:02 +0000162 /// object.
163 ObjCImplementationDecl *ObjCImplementation;
164
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000165 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000166
Douglas Gregor6f942b22010-09-21 16:06:22 +0000167 void MaybeAddConstructorResults(Result R);
168
Douglas Gregor86d9a522009-09-21 16:56:56 +0000169 public:
Douglas Gregordae68752011-02-01 22:57:45 +0000170 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000171 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000172 const CodeCompletionContext &CompletionContext,
173 LookupFilter Filter = 0)
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000174 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
175 Filter(Filter),
Douglas Gregor218937c2011-02-01 19:23:04 +0000176 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-11-02 20:36:02 +0000177 CompletionContext(CompletionContext),
178 ObjCImplementation(0)
179 {
180 // If this is an Objective-C instance method definition, dig out the
181 // corresponding implementation.
182 switch (CompletionContext.getKind()) {
183 case CodeCompletionContext::CCC_Expression:
184 case CodeCompletionContext::CCC_ObjCMessageReceiver:
185 case CodeCompletionContext::CCC_ParenthesizedExpression:
186 case CodeCompletionContext::CCC_Statement:
187 case CodeCompletionContext::CCC_Recovery:
188 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
189 if (Method->isInstanceMethod())
190 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
191 ObjCImplementation = Interface->getImplementation();
192 break;
193
194 default:
195 break;
196 }
197 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000198
Douglas Gregord8e8a582010-05-25 21:41:55 +0000199 /// \brief Whether we should include code patterns in the completion
200 /// results.
201 bool includeCodePatterns() const {
202 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000203 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000204 }
205
Douglas Gregor86d9a522009-09-21 16:56:56 +0000206 /// \brief Set the filter used for code-completion results.
207 void setFilter(LookupFilter Filter) {
208 this->Filter = Filter;
209 }
210
Douglas Gregor86d9a522009-09-21 16:56:56 +0000211 Result *data() { return Results.empty()? 0 : &Results.front(); }
212 unsigned size() const { return Results.size(); }
213 bool empty() const { return Results.empty(); }
214
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000215 /// \brief Specify the preferred type.
216 void setPreferredType(QualType T) {
217 PreferredType = SemaRef.Context.getCanonicalType(T);
218 }
219
Douglas Gregor3cdee122010-08-26 16:36:48 +0000220 /// \brief Set the cv-qualifiers on the object type, for us in filtering
221 /// calls to member functions.
222 ///
223 /// When there are qualifiers in this set, they will be used to filter
224 /// out member functions that aren't available (because there will be a
225 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
226 /// match.
227 void setObjectTypeQualifiers(Qualifiers Quals) {
228 ObjectTypeQualifiers = Quals;
229 HasObjectTypeQualifiers = true;
230 }
231
Douglas Gregor265f7492010-08-27 15:29:55 +0000232 /// \brief Set the preferred selector.
233 ///
234 /// When an Objective-C method declaration result is added, and that
235 /// method's selector matches this preferred selector, we give that method
236 /// a slight priority boost.
237 void setPreferredSelector(Selector Sel) {
238 PreferredSelector = Sel;
239 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000240
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000241 /// \brief Retrieve the code-completion context for which results are
242 /// being collected.
243 const CodeCompletionContext &getCompletionContext() const {
244 return CompletionContext;
245 }
246
Douglas Gregor45bcd432010-01-14 03:21:49 +0000247 /// \brief Specify whether nested-name-specifiers are allowed.
248 void allowNestedNameSpecifiers(bool Allow = true) {
249 AllowNestedNameSpecifiers = Allow;
250 }
251
Douglas Gregorb9d77572010-09-21 00:03:25 +0000252 /// \brief Return the semantic analysis object for which we are collecting
253 /// code completion results.
254 Sema &getSema() const { return SemaRef; }
255
Douglas Gregor218937c2011-02-01 19:23:04 +0000256 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000257 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000258
259 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Douglas Gregor218937c2011-02-01 19:23:04 +0000260
Douglas Gregore495b7f2010-01-14 00:20:49 +0000261 /// \brief Determine whether the given declaration is at all interesting
262 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000263 ///
264 /// \param ND the declaration that we are inspecting.
265 ///
266 /// \param AsNestedNameSpecifier will be set true if this declaration is
267 /// only interesting when it is a nested-name-specifier.
268 bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000269
270 /// \brief Check whether the result is hidden by the Hiding declaration.
271 ///
272 /// \returns true if the result is hidden and cannot be found, false if
273 /// the hidden result could still be found. When false, \p R may be
274 /// modified to describe how the result can be found (e.g., via extra
275 /// qualification).
276 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
277 NamedDecl *Hiding);
278
Douglas Gregor86d9a522009-09-21 16:56:56 +0000279 /// \brief Add a new result to this result set (if it isn't already in one
280 /// of the shadow maps), or replace an existing result (for, e.g., a
281 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000282 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000283 /// \param R the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000284 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000285 /// \param CurContext the context in which this result will be named.
Douglas Gregor456c4a12009-09-21 20:12:40 +0000286 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000287
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000288 /// \brief Add a new result to this result set, where we already know
289 /// the hiding declation (if any).
290 ///
291 /// \param R the result to add (if it is unique).
292 ///
293 /// \param CurContext the context in which this result will be named.
294 ///
295 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000296 ///
297 /// \param InBaseClass whether the result was found in a base
298 /// class of the searched context.
299 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
300 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000301
Douglas Gregora4477812010-01-14 16:01:26 +0000302 /// \brief Add a new non-declaration result to this result set.
303 void AddResult(Result R);
304
Douglas Gregor86d9a522009-09-21 16:56:56 +0000305 /// \brief Enter into a new scope.
306 void EnterNewScope();
307
308 /// \brief Exit from the current scope.
309 void ExitScope();
310
Douglas Gregor55385fe2009-11-18 04:19:12 +0000311 /// \brief Ignore this declaration, if it is seen again.
312 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
313
Douglas Gregor86d9a522009-09-21 16:56:56 +0000314 /// \name Name lookup predicates
315 ///
316 /// These predicates can be passed to the name lookup functions to filter the
317 /// results of name lookup. All of the predicates have the same type, so that
318 ///
319 //@{
Douglas Gregor791215b2009-09-21 20:51:25 +0000320 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000321 bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
Douglas Gregorf9578432010-07-28 21:50:18 +0000322 bool IsIntegralConstantValue(NamedDecl *ND) const;
Douglas Gregor01dfea02010-01-10 23:08:15 +0000323 bool IsOrdinaryNonValueName(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000324 bool IsNestedNameSpecifier(NamedDecl *ND) const;
325 bool IsEnum(NamedDecl *ND) const;
326 bool IsClassOrStruct(NamedDecl *ND) const;
327 bool IsUnion(NamedDecl *ND) const;
328 bool IsNamespace(NamedDecl *ND) const;
329 bool IsNamespaceOrAlias(NamedDecl *ND) const;
330 bool IsType(NamedDecl *ND) const;
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000331 bool IsMember(NamedDecl *ND) const;
Douglas Gregor80f4f4c2010-01-14 16:08:12 +0000332 bool IsObjCIvar(NamedDecl *ND) const;
Douglas Gregor8e254cf2010-05-27 23:06:34 +0000333 bool IsObjCMessageReceiver(NamedDecl *ND) const;
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000334 bool IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const;
Douglas Gregorfb629412010-08-23 21:17:50 +0000335 bool IsObjCCollection(NamedDecl *ND) const;
Douglas Gregor52779fb2010-09-23 23:01:17 +0000336 bool IsImpossibleToSatisfy(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000337 //@}
338 };
339}
340
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000341class ResultBuilder::ShadowMapEntry::iterator {
342 llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
343 unsigned SingleDeclIndex;
344
345public:
346 typedef DeclIndexPair value_type;
347 typedef value_type reference;
348 typedef std::ptrdiff_t difference_type;
349 typedef std::input_iterator_tag iterator_category;
350
351 class pointer {
352 DeclIndexPair Value;
353
354 public:
355 pointer(const DeclIndexPair &Value) : Value(Value) { }
356
357 const DeclIndexPair *operator->() const {
358 return &Value;
359 }
360 };
361
362 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
363
364 iterator(NamedDecl *SingleDecl, unsigned Index)
365 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
366
367 iterator(const DeclIndexPair *Iterator)
368 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
369
370 iterator &operator++() {
371 if (DeclOrIterator.is<NamedDecl *>()) {
372 DeclOrIterator = (NamedDecl *)0;
373 SingleDeclIndex = 0;
374 return *this;
375 }
376
377 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
378 ++I;
379 DeclOrIterator = I;
380 return *this;
381 }
382
Chris Lattner66392d42010-09-04 18:12:20 +0000383 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000384 iterator tmp(*this);
385 ++(*this);
386 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000387 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000388
389 reference operator*() const {
390 if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
391 return reference(ND, SingleDeclIndex);
392
Douglas Gregord490f952009-12-06 21:27:58 +0000393 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000394 }
395
396 pointer operator->() const {
397 return pointer(**this);
398 }
399
400 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000401 return X.DeclOrIterator.getOpaqueValue()
402 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000403 X.SingleDeclIndex == Y.SingleDeclIndex;
404 }
405
406 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000407 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000408 }
409};
410
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000411ResultBuilder::ShadowMapEntry::iterator
412ResultBuilder::ShadowMapEntry::begin() const {
413 if (DeclOrVector.isNull())
414 return iterator();
415
416 if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
417 return iterator(ND, SingleDeclIndex);
418
419 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
420}
421
422ResultBuilder::ShadowMapEntry::iterator
423ResultBuilder::ShadowMapEntry::end() const {
424 if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
425 return iterator();
426
427 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
428}
429
Douglas Gregor456c4a12009-09-21 20:12:40 +0000430/// \brief Compute the qualification required to get from the current context
431/// (\p CurContext) to the target context (\p TargetContext).
432///
433/// \param Context the AST context in which the qualification will be used.
434///
435/// \param CurContext the context where an entity is being named, which is
436/// typically based on the current scope.
437///
438/// \param TargetContext the context in which the named entity actually
439/// resides.
440///
441/// \returns a nested name specifier that refers into the target context, or
442/// NULL if no qualification is needed.
443static NestedNameSpecifier *
444getRequiredQualification(ASTContext &Context,
445 DeclContext *CurContext,
446 DeclContext *TargetContext) {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000447 SmallVector<DeclContext *, 4> TargetParents;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000448
449 for (DeclContext *CommonAncestor = TargetContext;
450 CommonAncestor && !CommonAncestor->Encloses(CurContext);
451 CommonAncestor = CommonAncestor->getLookupParent()) {
452 if (CommonAncestor->isTransparentContext() ||
453 CommonAncestor->isFunctionOrMethod())
454 continue;
455
456 TargetParents.push_back(CommonAncestor);
457 }
458
459 NestedNameSpecifier *Result = 0;
460 while (!TargetParents.empty()) {
461 DeclContext *Parent = TargetParents.back();
462 TargetParents.pop_back();
463
Douglas Gregorfb629412010-08-23 21:17:50 +0000464 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
465 if (!Namespace->getIdentifier())
466 continue;
467
Douglas Gregor456c4a12009-09-21 20:12:40 +0000468 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000469 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000470 else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
471 Result = NestedNameSpecifier::Create(Context, Result,
472 false,
473 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000474 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000475 return Result;
476}
477
Douglas Gregor45bcd432010-01-14 03:21:49 +0000478bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
479 bool &AsNestedNameSpecifier) const {
480 AsNestedNameSpecifier = false;
481
Douglas Gregore495b7f2010-01-14 00:20:49 +0000482 ND = ND->getUnderlyingDecl();
483 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000484
485 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000486 if (!ND->getDeclName())
487 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000488
489 // Friend declarations and declarations introduced due to friends are never
490 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000491 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000492 return false;
493
Douglas Gregor76282942009-12-11 17:31:05 +0000494 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000495 if (isa<ClassTemplateSpecializationDecl>(ND) ||
496 isa<ClassTemplatePartialSpecializationDecl>(ND))
497 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000498
Douglas Gregor76282942009-12-11 17:31:05 +0000499 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000500 if (isa<UsingDecl>(ND))
501 return false;
502
503 // Some declarations have reserved names that we don't want to ever show.
504 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000505 // __va_list_tag is a freak of nature. Find it and skip it.
506 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000507 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000508
Douglas Gregorf52cede2009-10-09 22:16:47 +0000509 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000510 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000511 //
512 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000513 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000514 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000515 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000516 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
517 (ND->getLocation().isInvalid() ||
518 SemaRef.SourceMgr.isInSystemHeader(
519 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000520 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000521 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000522 }
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000523
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000524 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
525 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
526 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000527 Filter != &ResultBuilder::IsNamespaceOrAlias &&
528 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000529 AsNestedNameSpecifier = true;
530
Douglas Gregor86d9a522009-09-21 16:56:56 +0000531 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000532 if (Filter && !(this->*Filter)(ND)) {
533 // Check whether it is interesting as a nested-name-specifier.
David Blaikie4e4d0842012-03-11 07:00:24 +0000534 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor45bcd432010-01-14 03:21:49 +0000535 IsNestedNameSpecifier(ND) &&
536 (Filter != &ResultBuilder::IsMember ||
537 (isa<CXXRecordDecl>(ND) &&
538 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
539 AsNestedNameSpecifier = true;
540 return true;
541 }
542
Douglas Gregore495b7f2010-01-14 00:20:49 +0000543 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000544 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000545 // ... then it must be interesting!
546 return true;
547}
548
Douglas Gregor6660d842010-01-14 00:41:07 +0000549bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
550 NamedDecl *Hiding) {
551 // In C, there is no way to refer to a hidden name.
552 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
553 // name if we introduce the tag type.
David Blaikie4e4d0842012-03-11 07:00:24 +0000554 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor6660d842010-01-14 00:41:07 +0000555 return true;
556
Sebastian Redl7a126a42010-08-31 00:36:30 +0000557 DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000558
559 // There is no way to qualify a name declared in a function or method.
560 if (HiddenCtx->isFunctionOrMethod())
561 return true;
562
Sebastian Redl7a126a42010-08-31 00:36:30 +0000563 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000564 return true;
565
566 // We can refer to the result with the appropriate qualification. Do it.
567 R.Hidden = true;
568 R.QualifierIsInformative = false;
569
570 if (!R.Qualifier)
571 R.Qualifier = getRequiredQualification(SemaRef.Context,
572 CurContext,
573 R.Declaration->getDeclContext());
574 return false;
575}
576
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000577/// \brief A simplified classification of types used to determine whether two
578/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000579SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000580 switch (T->getTypeClass()) {
581 case Type::Builtin:
582 switch (cast<BuiltinType>(T)->getKind()) {
583 case BuiltinType::Void:
584 return STC_Void;
585
586 case BuiltinType::NullPtr:
587 return STC_Pointer;
588
589 case BuiltinType::Overload:
590 case BuiltinType::Dependent:
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000591 return STC_Other;
592
593 case BuiltinType::ObjCId:
594 case BuiltinType::ObjCClass:
595 case BuiltinType::ObjCSel:
596 return STC_ObjectiveC;
597
598 default:
599 return STC_Arithmetic;
600 }
David Blaikie7530c032012-01-17 06:56:22 +0000601
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000602 case Type::Complex:
603 return STC_Arithmetic;
604
605 case Type::Pointer:
606 return STC_Pointer;
607
608 case Type::BlockPointer:
609 return STC_Block;
610
611 case Type::LValueReference:
612 case Type::RValueReference:
613 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
614
615 case Type::ConstantArray:
616 case Type::IncompleteArray:
617 case Type::VariableArray:
618 case Type::DependentSizedArray:
619 return STC_Array;
620
621 case Type::DependentSizedExtVector:
622 case Type::Vector:
623 case Type::ExtVector:
624 return STC_Arithmetic;
625
626 case Type::FunctionProto:
627 case Type::FunctionNoProto:
628 return STC_Function;
629
630 case Type::Record:
631 return STC_Record;
632
633 case Type::Enum:
634 return STC_Arithmetic;
635
636 case Type::ObjCObject:
637 case Type::ObjCInterface:
638 case Type::ObjCObjectPointer:
639 return STC_ObjectiveC;
640
641 default:
642 return STC_Other;
643 }
644}
645
646/// \brief Get the type that a given expression will have if this declaration
647/// is used as an expression in its "typical" code-completion form.
Douglas Gregor1827e102010-08-16 16:18:59 +0000648QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000649 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
650
651 if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
652 return C.getTypeDeclType(Type);
653 if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
654 return C.getObjCInterfaceType(Iface);
655
656 QualType T;
657 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000658 T = Function->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000659 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000660 T = Method->getSendResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000661 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000662 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000663 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
664 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
665 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
666 T = Property->getType();
667 else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
668 T = Value->getType();
669 else
670 return QualType();
Douglas Gregor3e64d562011-04-14 20:33:34 +0000671
672 // Dig through references, function pointers, and block pointers to
673 // get down to the likely type of an expression when the entity is
674 // used.
675 do {
676 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
677 T = Ref->getPointeeType();
678 continue;
679 }
680
681 if (const PointerType *Pointer = T->getAs<PointerType>()) {
682 if (Pointer->getPointeeType()->isFunctionType()) {
683 T = Pointer->getPointeeType();
684 continue;
685 }
686
687 break;
688 }
689
690 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
691 T = Block->getPointeeType();
692 continue;
693 }
694
695 if (const FunctionType *Function = T->getAs<FunctionType>()) {
696 T = Function->getResultType();
697 continue;
698 }
699
700 break;
701 } while (true);
702
703 return T;
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000704}
705
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000706void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
707 // If this is an Objective-C method declaration whose selector matches our
708 // preferred selector, give it a priority boost.
709 if (!PreferredSelector.isNull())
710 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
711 if (PreferredSelector == Method->getSelector())
712 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000713
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000714 // If we have a preferred type, adjust the priority for results with exactly-
715 // matching or nearly-matching types.
716 if (!PreferredType.isNull()) {
717 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
718 if (!T.isNull()) {
719 CanQualType TC = SemaRef.Context.getCanonicalType(T);
720 // Check for exactly-matching types (modulo qualifiers).
721 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
722 R.Priority /= CCF_ExactTypeMatch;
723 // Check for nearly-matching types, based on classification of each.
724 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000725 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000726 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
727 R.Priority /= CCF_SimilarTypeMatch;
728 }
729 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000730}
731
Douglas Gregor6f942b22010-09-21 16:06:22 +0000732void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikie4e4d0842012-03-11 07:00:24 +0000733 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor6f942b22010-09-21 16:06:22 +0000734 !CompletionContext.wantConstructorResults())
735 return;
736
737 ASTContext &Context = SemaRef.Context;
738 NamedDecl *D = R.Declaration;
739 CXXRecordDecl *Record = 0;
740 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
741 Record = ClassTemplate->getTemplatedDecl();
742 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
743 // Skip specializations and partial specializations.
744 if (isa<ClassTemplateSpecializationDecl>(Record))
745 return;
746 } else {
747 // There are no constructors here.
748 return;
749 }
750
751 Record = Record->getDefinition();
752 if (!Record)
753 return;
754
755
756 QualType RecordTy = Context.getTypeDeclType(Record);
757 DeclarationName ConstructorName
758 = Context.DeclarationNames.getCXXConstructorName(
759 Context.getCanonicalType(RecordTy));
David Blaikie3bc93e32012-12-19 00:45:41 +0000760 DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
761 for (DeclContext::lookup_iterator I = Ctors.begin(), E = Ctors.end(); I != E;
762 ++I) {
763 R.Declaration = *I;
Douglas Gregor6f942b22010-09-21 16:06:22 +0000764 R.CursorKind = getCursorKindForDecl(R.Declaration);
765 Results.push_back(R);
766 }
767}
768
Douglas Gregore495b7f2010-01-14 00:20:49 +0000769void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
770 assert(!ShadowMaps.empty() && "Must enter into a results scope");
771
772 if (R.Kind != Result::RK_Declaration) {
773 // For non-declaration results, just add the result.
774 Results.push_back(R);
775 return;
776 }
777
778 // Look through using declarations.
779 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
780 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
781 return;
782 }
783
784 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
785 unsigned IDNS = CanonDecl->getIdentifierNamespace();
786
Douglas Gregor45bcd432010-01-14 03:21:49 +0000787 bool AsNestedNameSpecifier = false;
788 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000789 return;
790
Douglas Gregor6f942b22010-09-21 16:06:22 +0000791 // C++ constructors are never found by name lookup.
792 if (isa<CXXConstructorDecl>(R.Declaration))
793 return;
794
Douglas Gregor86d9a522009-09-21 16:56:56 +0000795 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000796 ShadowMapEntry::iterator I, IEnd;
797 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
798 if (NamePos != SMap.end()) {
799 I = NamePos->second.begin();
800 IEnd = NamePos->second.end();
801 }
802
803 for (; I != IEnd; ++I) {
804 NamedDecl *ND = I->first;
805 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000806 if (ND->getCanonicalDecl() == CanonDecl) {
807 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000808 Results[Index].Declaration = R.Declaration;
809
Douglas Gregor86d9a522009-09-21 16:56:56 +0000810 // We're done.
811 return;
812 }
813 }
814
815 // This is a new declaration in this scope. However, check whether this
816 // declaration name is hidden by a similarly-named declaration in an outer
817 // scope.
818 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
819 --SMEnd;
820 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000821 ShadowMapEntry::iterator I, IEnd;
822 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
823 if (NamePos != SM->end()) {
824 I = NamePos->second.begin();
825 IEnd = NamePos->second.end();
826 }
827 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000828 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000829 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000830 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
831 Decl::IDNS_ObjCProtocol)))
832 continue;
833
834 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000835 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000836 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000837 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000838 continue;
839
840 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000841 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000842 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000843
844 break;
845 }
846 }
847
848 // Make sure that any given declaration only shows up in the result set once.
849 if (!AllDeclsFound.insert(CanonDecl))
850 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000851
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000852 // If the filter is for nested-name-specifiers, then this result starts a
853 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000854 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000855 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000856 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000857 } else
858 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000859
Douglas Gregor0563c262009-09-22 23:15:58 +0000860 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000861 if (R.QualifierIsInformative && !R.Qualifier &&
862 !R.StartsNestedNameSpecifier) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000863 DeclContext *Ctx = R.Declaration->getDeclContext();
864 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
865 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
866 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
867 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
868 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
869 else
870 R.QualifierIsInformative = false;
871 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000872
Douglas Gregor86d9a522009-09-21 16:56:56 +0000873 // Insert this result into the set of results and into the current shadow
874 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000875 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000876 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000877
878 if (!AsNestedNameSpecifier)
879 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000880}
881
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000882void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000883 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000884 if (R.Kind != Result::RK_Declaration) {
885 // For non-declaration results, just add the result.
886 Results.push_back(R);
887 return;
888 }
889
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000890 // Look through using declarations.
891 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
892 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
893 return;
894 }
895
Douglas Gregor45bcd432010-01-14 03:21:49 +0000896 bool AsNestedNameSpecifier = false;
897 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000898 return;
899
Douglas Gregor6f942b22010-09-21 16:06:22 +0000900 // C++ constructors are never found by name lookup.
901 if (isa<CXXConstructorDecl>(R.Declaration))
902 return;
903
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000904 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
905 return;
Nick Lewycky173a37a2012-04-03 21:44:08 +0000906
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000907 // Make sure that any given declaration only shows up in the result set once.
908 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
909 return;
910
911 // If the filter is for nested-name-specifiers, then this result starts a
912 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000913 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000914 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000915 R.Priority = CCP_NestedNameSpecifier;
916 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000917 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
918 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000919 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000920 R.QualifierIsInformative = true;
921
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000922 // If this result is supposed to have an informative qualifier, add one.
923 if (R.QualifierIsInformative && !R.Qualifier &&
924 !R.StartsNestedNameSpecifier) {
925 DeclContext *Ctx = R.Declaration->getDeclContext();
926 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
927 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
928 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
929 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000930 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000931 else
932 R.QualifierIsInformative = false;
933 }
934
Douglas Gregor12e13132010-05-26 22:00:08 +0000935 // Adjust the priority if this result comes from a base class.
936 if (InBaseClass)
937 R.Priority += CCD_InBaseClass;
938
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000939 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000940
Douglas Gregor3cdee122010-08-26 16:36:48 +0000941 if (HasObjectTypeQualifiers)
942 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
943 if (Method->isInstance()) {
944 Qualifiers MethodQuals
945 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
946 if (ObjectTypeQualifiers == MethodQuals)
947 R.Priority += CCD_ObjectQualifierMatch;
948 else if (ObjectTypeQualifiers - MethodQuals) {
949 // The method cannot be invoked, because doing so would drop
950 // qualifiers.
951 return;
952 }
953 }
954
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000955 // Insert this result into the set of results.
956 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000957
958 if (!AsNestedNameSpecifier)
959 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000960}
961
Douglas Gregora4477812010-01-14 16:01:26 +0000962void ResultBuilder::AddResult(Result R) {
963 assert(R.Kind != Result::RK_Declaration &&
964 "Declaration results need more context");
965 Results.push_back(R);
966}
967
Douglas Gregor86d9a522009-09-21 16:56:56 +0000968/// \brief Enter into a new scope.
969void ResultBuilder::EnterNewScope() {
970 ShadowMaps.push_back(ShadowMap());
971}
972
973/// \brief Exit from the current scope.
974void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000975 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
976 EEnd = ShadowMaps.back().end();
977 E != EEnd;
978 ++E)
979 E->second.Destroy();
980
Douglas Gregor86d9a522009-09-21 16:56:56 +0000981 ShadowMaps.pop_back();
982}
983
Douglas Gregor791215b2009-09-21 20:51:25 +0000984/// \brief Determines whether this given declaration will be found by
985/// ordinary name lookup.
986bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000987 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
988
Douglas Gregor791215b2009-09-21 20:51:25 +0000989 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +0000990 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000991 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +0000992 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +0000993 if (isa<ObjCIvarDecl>(ND))
994 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +0000995 }
996
Douglas Gregor791215b2009-09-21 20:51:25 +0000997 return ND->getIdentifierNamespace() & IDNS;
998}
999
Douglas Gregor01dfea02010-01-10 23:08:15 +00001000/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001001/// ordinary name lookup but is not a type name.
1002bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
1003 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1004 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1005 return false;
1006
1007 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001008 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +00001009 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +00001010 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +00001011 if (isa<ObjCIvarDecl>(ND))
1012 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001013 }
1014
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001015 return ND->getIdentifierNamespace() & IDNS;
1016}
1017
Douglas Gregorf9578432010-07-28 21:50:18 +00001018bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
1019 if (!IsOrdinaryNonTypeName(ND))
1020 return 0;
1021
1022 if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
1023 if (VD->getType()->isIntegralOrEnumerationType())
1024 return true;
1025
1026 return false;
1027}
1028
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001029/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001030/// ordinary name lookup.
1031bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001032 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1033
Douglas Gregor01dfea02010-01-10 23:08:15 +00001034 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001035 if (SemaRef.getLangOpts().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001036 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001037
1038 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001039 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1040 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001041}
1042
Douglas Gregor86d9a522009-09-21 16:56:56 +00001043/// \brief Determines whether the given declaration is suitable as the
1044/// start of a C++ nested-name-specifier, e.g., a class or namespace.
1045bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
1046 // Allow us to find class templates, too.
1047 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1048 ND = ClassTemplate->getTemplatedDecl();
1049
1050 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1051}
1052
1053/// \brief Determines whether the given declaration is an enumeration.
1054bool ResultBuilder::IsEnum(NamedDecl *ND) const {
1055 return isa<EnumDecl>(ND);
1056}
1057
1058/// \brief Determines whether the given declaration is a class or struct.
1059bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
1060 // Allow us to find class templates, too.
1061 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1062 ND = ClassTemplate->getTemplatedDecl();
Joao Matos6666ed42012-08-31 18:45:21 +00001063
1064 // For purposes of this check, interfaces match too.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001065 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001066 return RD->getTagKind() == TTK_Class ||
Joao Matos6666ed42012-08-31 18:45:21 +00001067 RD->getTagKind() == TTK_Struct ||
1068 RD->getTagKind() == TTK_Interface;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001069
1070 return false;
1071}
1072
1073/// \brief Determines whether the given declaration is a union.
1074bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1075 // Allow us to find class templates, too.
1076 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1077 ND = ClassTemplate->getTemplatedDecl();
1078
1079 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001080 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001081
1082 return false;
1083}
1084
1085/// \brief Determines whether the given declaration is a namespace.
1086bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1087 return isa<NamespaceDecl>(ND);
1088}
1089
1090/// \brief Determines whether the given declaration is a namespace or
1091/// namespace alias.
1092bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1093 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1094}
1095
Douglas Gregor76282942009-12-11 17:31:05 +00001096/// \brief Determines whether the given declaration is a type.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001097bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregord32b0222010-08-24 01:06:58 +00001098 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1099 ND = Using->getTargetDecl();
1100
1101 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001102}
1103
Douglas Gregor76282942009-12-11 17:31:05 +00001104/// \brief Determines which members of a class should be visible via
1105/// "." or "->". Only value declarations, nested name specifiers, and
1106/// using declarations thereof should show up.
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001107bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor76282942009-12-11 17:31:05 +00001108 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1109 ND = Using->getTargetDecl();
1110
Douglas Gregorce821962009-12-11 18:14:22 +00001111 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1112 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001113}
1114
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001115static bool isObjCReceiverType(ASTContext &C, QualType T) {
1116 T = C.getCanonicalType(T);
1117 switch (T->getTypeClass()) {
1118 case Type::ObjCObject:
1119 case Type::ObjCInterface:
1120 case Type::ObjCObjectPointer:
1121 return true;
1122
1123 case Type::Builtin:
1124 switch (cast<BuiltinType>(T)->getKind()) {
1125 case BuiltinType::ObjCId:
1126 case BuiltinType::ObjCClass:
1127 case BuiltinType::ObjCSel:
1128 return true;
1129
1130 default:
1131 break;
1132 }
1133 return false;
1134
1135 default:
1136 break;
1137 }
1138
David Blaikie4e4d0842012-03-11 07:00:24 +00001139 if (!C.getLangOpts().CPlusPlus)
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001140 return false;
1141
1142 // FIXME: We could perform more analysis here to determine whether a
1143 // particular class type has any conversions to Objective-C types. For now,
1144 // just accept all class types.
1145 return T->isDependentType() || T->isRecordType();
1146}
1147
1148bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1149 QualType T = getDeclUsageType(SemaRef.Context, ND);
1150 if (T.isNull())
1151 return false;
1152
1153 T = SemaRef.Context.getBaseElementType(T);
1154 return isObjCReceiverType(SemaRef.Context, T);
1155}
1156
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001157bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const {
1158 if (IsObjCMessageReceiver(ND))
1159 return true;
1160
1161 VarDecl *Var = dyn_cast<VarDecl>(ND);
1162 if (!Var)
1163 return false;
1164
1165 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1166}
1167
Douglas Gregorfb629412010-08-23 21:17:50 +00001168bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
David Blaikie4e4d0842012-03-11 07:00:24 +00001169 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1170 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregorfb629412010-08-23 21:17:50 +00001171 return false;
1172
1173 QualType T = getDeclUsageType(SemaRef.Context, ND);
1174 if (T.isNull())
1175 return false;
1176
1177 T = SemaRef.Context.getBaseElementType(T);
1178 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1179 T->isObjCIdType() ||
David Blaikie4e4d0842012-03-11 07:00:24 +00001180 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregorfb629412010-08-23 21:17:50 +00001181}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001182
Douglas Gregor52779fb2010-09-23 23:01:17 +00001183bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1184 return false;
1185}
1186
James Dennettde23c7e2012-06-17 05:33:25 +00001187/// \brief Determines whether the given declaration is an Objective-C
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001188/// instance variable.
1189bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1190 return isa<ObjCIvarDecl>(ND);
1191}
1192
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001193namespace {
1194 /// \brief Visible declaration consumer that adds a code-completion result
1195 /// for each visible declaration.
1196 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1197 ResultBuilder &Results;
1198 DeclContext *CurContext;
1199
1200 public:
1201 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1202 : Results(Results), CurContext(CurContext) { }
1203
Erik Verbruggend1205962011-10-06 07:27:49 +00001204 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1205 bool InBaseClass) {
1206 bool Accessible = true;
Douglas Gregor17015ef2011-11-03 16:51:37 +00001207 if (Ctx)
1208 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1209
Erik Verbruggend1205962011-10-06 07:27:49 +00001210 ResultBuilder::Result Result(ND, 0, false, Accessible);
1211 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001212 }
1213 };
1214}
1215
Douglas Gregor86d9a522009-09-21 16:56:56 +00001216/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001217static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001218 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001219 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001220 Results.AddResult(Result("short", CCP_Type));
1221 Results.AddResult(Result("long", CCP_Type));
1222 Results.AddResult(Result("signed", CCP_Type));
1223 Results.AddResult(Result("unsigned", CCP_Type));
1224 Results.AddResult(Result("void", CCP_Type));
1225 Results.AddResult(Result("char", CCP_Type));
1226 Results.AddResult(Result("int", CCP_Type));
1227 Results.AddResult(Result("float", CCP_Type));
1228 Results.AddResult(Result("double", CCP_Type));
1229 Results.AddResult(Result("enum", CCP_Type));
1230 Results.AddResult(Result("struct", CCP_Type));
1231 Results.AddResult(Result("union", CCP_Type));
1232 Results.AddResult(Result("const", CCP_Type));
1233 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001234
Douglas Gregor86d9a522009-09-21 16:56:56 +00001235 if (LangOpts.C99) {
1236 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001237 Results.AddResult(Result("_Complex", CCP_Type));
1238 Results.AddResult(Result("_Imaginary", CCP_Type));
1239 Results.AddResult(Result("_Bool", CCP_Type));
1240 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001241 }
1242
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001243 CodeCompletionBuilder Builder(Results.getAllocator(),
1244 Results.getCodeCompletionTUInfo());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001245 if (LangOpts.CPlusPlus) {
1246 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001247 Results.AddResult(Result("bool", CCP_Type +
1248 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001249 Results.AddResult(Result("class", CCP_Type));
1250 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001251
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001252 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001253 Builder.AddTypedTextChunk("typename");
1254 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1255 Builder.AddPlaceholderChunk("qualifier");
1256 Builder.AddTextChunk("::");
1257 Builder.AddPlaceholderChunk("name");
1258 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001259
Douglas Gregor86d9a522009-09-21 16:56:56 +00001260 if (LangOpts.CPlusPlus0x) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001261 Results.AddResult(Result("auto", CCP_Type));
1262 Results.AddResult(Result("char16_t", CCP_Type));
1263 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001264
Douglas Gregor218937c2011-02-01 19:23:04 +00001265 Builder.AddTypedTextChunk("decltype");
1266 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1267 Builder.AddPlaceholderChunk("expression");
1268 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1269 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001270 }
1271 }
1272
1273 // GNU extensions
1274 if (LangOpts.GNUMode) {
1275 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001276 // Results.AddResult(Result("_Decimal32"));
1277 // Results.AddResult(Result("_Decimal64"));
1278 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001279
Douglas Gregor218937c2011-02-01 19:23:04 +00001280 Builder.AddTypedTextChunk("typeof");
1281 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1282 Builder.AddPlaceholderChunk("expression");
1283 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001284
Douglas Gregor218937c2011-02-01 19:23:04 +00001285 Builder.AddTypedTextChunk("typeof");
1286 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1287 Builder.AddPlaceholderChunk("type");
1288 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1289 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001290 }
1291}
1292
John McCallf312b1e2010-08-26 23:41:50 +00001293static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001294 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001295 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001296 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001297 // Note: we don't suggest either "auto" or "register", because both
1298 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1299 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001300 Results.AddResult(Result("extern"));
1301 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001302}
1303
John McCallf312b1e2010-08-26 23:41:50 +00001304static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001305 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001306 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001307 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001308 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001309 case Sema::PCC_Class:
1310 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001311 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001312 Results.AddResult(Result("explicit"));
1313 Results.AddResult(Result("friend"));
1314 Results.AddResult(Result("mutable"));
1315 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001316 }
1317 // Fall through
1318
John McCallf312b1e2010-08-26 23:41:50 +00001319 case Sema::PCC_ObjCInterface:
1320 case Sema::PCC_ObjCImplementation:
1321 case Sema::PCC_Namespace:
1322 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001323 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001324 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001325 break;
1326
John McCallf312b1e2010-08-26 23:41:50 +00001327 case Sema::PCC_ObjCInstanceVariableList:
1328 case Sema::PCC_Expression:
1329 case Sema::PCC_Statement:
1330 case Sema::PCC_ForInit:
1331 case Sema::PCC_Condition:
1332 case Sema::PCC_RecoveryInFunction:
1333 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001334 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001335 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001336 break;
1337 }
1338}
1339
Douglas Gregorbca403c2010-01-13 23:51:12 +00001340static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1341static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1342static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001343 ResultBuilder &Results,
1344 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001345static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001346 ResultBuilder &Results,
1347 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001348static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001349 ResultBuilder &Results,
1350 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001351static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001352
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001353static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001354 CodeCompletionBuilder Builder(Results.getAllocator(),
1355 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00001356 Builder.AddTypedTextChunk("typedef");
1357 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1358 Builder.AddPlaceholderChunk("type");
1359 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1360 Builder.AddPlaceholderChunk("name");
1361 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001362}
1363
John McCallf312b1e2010-08-26 23:41:50 +00001364static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001365 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001366 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001367 case Sema::PCC_Namespace:
1368 case Sema::PCC_Class:
1369 case Sema::PCC_ObjCInstanceVariableList:
1370 case Sema::PCC_Template:
1371 case Sema::PCC_MemberTemplate:
1372 case Sema::PCC_Statement:
1373 case Sema::PCC_RecoveryInFunction:
1374 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001375 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001376 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001377 return true;
1378
John McCallf312b1e2010-08-26 23:41:50 +00001379 case Sema::PCC_Expression:
1380 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001381 return LangOpts.CPlusPlus;
1382
1383 case Sema::PCC_ObjCInterface:
1384 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001385 return false;
1386
John McCallf312b1e2010-08-26 23:41:50 +00001387 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001388 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001389 }
David Blaikie7530c032012-01-17 06:56:22 +00001390
1391 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001392}
1393
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001394static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1395 const Preprocessor &PP) {
1396 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001397 Policy.AnonymousTagLocations = false;
1398 Policy.SuppressStrongLifetime = true;
Douglas Gregor25270b62011-11-03 00:16:13 +00001399 Policy.SuppressUnwrittenScope = true;
Douglas Gregor8ca72082011-10-18 21:20:17 +00001400 return Policy;
1401}
1402
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001403/// \brief Retrieve a printing policy suitable for code completion.
1404static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1405 return getCompletionPrintingPolicy(S.Context, S.PP);
1406}
1407
Douglas Gregor8ca72082011-10-18 21:20:17 +00001408/// \brief Retrieve the string representation of the given type as a string
1409/// that has the appropriate lifetime for code completion.
1410///
1411/// This routine provides a fast path where we provide constant strings for
1412/// common type names.
1413static const char *GetCompletionTypeString(QualType T,
1414 ASTContext &Context,
1415 const PrintingPolicy &Policy,
1416 CodeCompletionAllocator &Allocator) {
1417 if (!T.getLocalQualifiers()) {
1418 // Built-in type names are constant strings.
1419 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidis27a00972012-05-05 04:20:28 +00001420 return BT->getNameAsCString(Policy);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001421
1422 // Anonymous tag types are constant strings.
1423 if (const TagType *TagT = dyn_cast<TagType>(T))
1424 if (TagDecl *Tag = TagT->getDecl())
1425 if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
1426 switch (Tag->getTagKind()) {
1427 case TTK_Struct: return "struct <anonymous>";
Joao Matos6666ed42012-08-31 18:45:21 +00001428 case TTK_Interface: return "__interface <anonymous>";
1429 case TTK_Class: return "class <anonymous>";
Douglas Gregor8ca72082011-10-18 21:20:17 +00001430 case TTK_Union: return "union <anonymous>";
1431 case TTK_Enum: return "enum <anonymous>";
1432 }
1433 }
1434 }
1435
1436 // Slow path: format the type as a string.
1437 std::string Result;
1438 T.getAsStringInternal(Result, Policy);
1439 return Allocator.CopyString(Result);
1440}
1441
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001442/// \brief Add a completion for "this", if we're in a member function.
1443static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1444 QualType ThisTy = S.getCurrentThisType();
1445 if (ThisTy.isNull())
1446 return;
1447
1448 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001449 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001450 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1451 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1452 S.Context,
1453 Policy,
1454 Allocator));
1455 Builder.AddTypedTextChunk("this");
Joao Matos6666ed42012-08-31 18:45:21 +00001456 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001457}
1458
Douglas Gregor01dfea02010-01-10 23:08:15 +00001459/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001460static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001461 Scope *S,
1462 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001463 ResultBuilder &Results) {
Douglas Gregor8ca72082011-10-18 21:20:17 +00001464 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001465 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor8ca72082011-10-18 21:20:17 +00001466 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregor218937c2011-02-01 19:23:04 +00001467
John McCall0a2c5e22010-08-25 06:19:51 +00001468 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001469 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001470 case Sema::PCC_Namespace:
David Blaikie4e4d0842012-03-11 07:00:24 +00001471 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001472 if (Results.includeCodePatterns()) {
1473 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001474 Builder.AddTypedTextChunk("namespace");
1475 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1476 Builder.AddPlaceholderChunk("identifier");
1477 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1478 Builder.AddPlaceholderChunk("declarations");
1479 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1480 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1481 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001482 }
1483
Douglas Gregor01dfea02010-01-10 23:08:15 +00001484 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001485 Builder.AddTypedTextChunk("namespace");
1486 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1487 Builder.AddPlaceholderChunk("name");
1488 Builder.AddChunk(CodeCompletionString::CK_Equal);
1489 Builder.AddPlaceholderChunk("namespace");
1490 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001491
1492 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001493 Builder.AddTypedTextChunk("using");
1494 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1495 Builder.AddTextChunk("namespace");
1496 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1497 Builder.AddPlaceholderChunk("identifier");
1498 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001499
1500 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001501 Builder.AddTypedTextChunk("asm");
1502 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1503 Builder.AddPlaceholderChunk("string-literal");
1504 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1505 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001506
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001507 if (Results.includeCodePatterns()) {
1508 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001509 Builder.AddTypedTextChunk("template");
1510 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1511 Builder.AddPlaceholderChunk("declaration");
1512 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001513 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001514 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001515
David Blaikie4e4d0842012-03-11 07:00:24 +00001516 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001517 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001518
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001519 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001520 // Fall through
1521
John McCallf312b1e2010-08-26 23:41:50 +00001522 case Sema::PCC_Class:
David Blaikie4e4d0842012-03-11 07:00:24 +00001523 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001524 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001525 Builder.AddTypedTextChunk("using");
1526 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1527 Builder.AddPlaceholderChunk("qualifier");
1528 Builder.AddTextChunk("::");
1529 Builder.AddPlaceholderChunk("name");
1530 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001531
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001532 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001533 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001534 Builder.AddTypedTextChunk("using");
1535 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1536 Builder.AddTextChunk("typename");
1537 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1538 Builder.AddPlaceholderChunk("qualifier");
1539 Builder.AddTextChunk("::");
1540 Builder.AddPlaceholderChunk("name");
1541 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001542 }
1543
John McCallf312b1e2010-08-26 23:41:50 +00001544 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001545 AddTypedefResult(Results);
1546
Douglas Gregor01dfea02010-01-10 23:08:15 +00001547 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001548 Builder.AddTypedTextChunk("public");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001549 if (Results.includeCodePatterns())
1550 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001551 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001552
1553 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001554 Builder.AddTypedTextChunk("protected");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001555 if (Results.includeCodePatterns())
1556 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001557 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001558
1559 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001560 Builder.AddTypedTextChunk("private");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001561 if (Results.includeCodePatterns())
1562 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001563 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001564 }
1565 }
1566 // Fall through
1567
John McCallf312b1e2010-08-26 23:41:50 +00001568 case Sema::PCC_Template:
1569 case Sema::PCC_MemberTemplate:
David Blaikie4e4d0842012-03-11 07:00:24 +00001570 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001571 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001572 Builder.AddTypedTextChunk("template");
1573 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1574 Builder.AddPlaceholderChunk("parameters");
1575 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1576 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001577 }
1578
David Blaikie4e4d0842012-03-11 07:00:24 +00001579 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1580 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001581 break;
1582
John McCallf312b1e2010-08-26 23:41:50 +00001583 case Sema::PCC_ObjCInterface:
David Blaikie4e4d0842012-03-11 07:00:24 +00001584 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1585 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1586 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001587 break;
1588
John McCallf312b1e2010-08-26 23:41:50 +00001589 case Sema::PCC_ObjCImplementation:
David Blaikie4e4d0842012-03-11 07:00:24 +00001590 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1591 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1592 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001593 break;
1594
John McCallf312b1e2010-08-26 23:41:50 +00001595 case Sema::PCC_ObjCInstanceVariableList:
David Blaikie4e4d0842012-03-11 07:00:24 +00001596 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001597 break;
1598
John McCallf312b1e2010-08-26 23:41:50 +00001599 case Sema::PCC_RecoveryInFunction:
1600 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001601 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001602
David Blaikie4e4d0842012-03-11 07:00:24 +00001603 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1604 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001605 Builder.AddTypedTextChunk("try");
1606 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1607 Builder.AddPlaceholderChunk("statements");
1608 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1609 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1610 Builder.AddTextChunk("catch");
1611 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1612 Builder.AddPlaceholderChunk("declaration");
1613 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1614 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1615 Builder.AddPlaceholderChunk("statements");
1616 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1617 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1618 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001619 }
David Blaikie4e4d0842012-03-11 07:00:24 +00001620 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001621 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001622
Douglas Gregord8e8a582010-05-25 21:41:55 +00001623 if (Results.includeCodePatterns()) {
1624 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001625 Builder.AddTypedTextChunk("if");
1626 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001627 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001628 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001629 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001630 Builder.AddPlaceholderChunk("expression");
1631 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1632 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1633 Builder.AddPlaceholderChunk("statements");
1634 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1635 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1636 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001637
Douglas Gregord8e8a582010-05-25 21:41:55 +00001638 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001639 Builder.AddTypedTextChunk("switch");
1640 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001641 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001642 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001643 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001644 Builder.AddPlaceholderChunk("expression");
1645 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1646 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1647 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1648 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1649 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001650 }
1651
Douglas Gregor01dfea02010-01-10 23:08:15 +00001652 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001653 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001654 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001655 Builder.AddTypedTextChunk("case");
1656 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1657 Builder.AddPlaceholderChunk("expression");
1658 Builder.AddChunk(CodeCompletionString::CK_Colon);
1659 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001660
1661 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001662 Builder.AddTypedTextChunk("default");
1663 Builder.AddChunk(CodeCompletionString::CK_Colon);
1664 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001665 }
1666
Douglas Gregord8e8a582010-05-25 21:41:55 +00001667 if (Results.includeCodePatterns()) {
1668 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001669 Builder.AddTypedTextChunk("while");
1670 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001671 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001672 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001673 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001674 Builder.AddPlaceholderChunk("expression");
1675 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1676 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1677 Builder.AddPlaceholderChunk("statements");
1678 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1679 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1680 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001681
1682 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001683 Builder.AddTypedTextChunk("do");
1684 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1685 Builder.AddPlaceholderChunk("statements");
1686 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1687 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1688 Builder.AddTextChunk("while");
1689 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1690 Builder.AddPlaceholderChunk("expression");
1691 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1692 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001693
Douglas Gregord8e8a582010-05-25 21:41:55 +00001694 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001695 Builder.AddTypedTextChunk("for");
1696 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001697 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001698 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001699 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001700 Builder.AddPlaceholderChunk("init-expression");
1701 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1702 Builder.AddPlaceholderChunk("condition");
1703 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1704 Builder.AddPlaceholderChunk("inc-expression");
1705 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1706 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1707 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1708 Builder.AddPlaceholderChunk("statements");
1709 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1710 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1711 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001712 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001713
1714 if (S->getContinueParent()) {
1715 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001716 Builder.AddTypedTextChunk("continue");
1717 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001718 }
1719
1720 if (S->getBreakParent()) {
1721 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001722 Builder.AddTypedTextChunk("break");
1723 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001724 }
1725
1726 // "return expression ;" or "return ;", depending on whether we
1727 // know the function is void or not.
1728 bool isVoid = false;
1729 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1730 isVoid = Function->getResultType()->isVoidType();
1731 else if (ObjCMethodDecl *Method
1732 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1733 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001734 else if (SemaRef.getCurBlock() &&
1735 !SemaRef.getCurBlock()->ReturnType.isNull())
1736 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001737 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001738 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001739 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1740 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001741 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001742 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001743
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001744 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001745 Builder.AddTypedTextChunk("goto");
1746 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1747 Builder.AddPlaceholderChunk("label");
1748 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001749
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001750 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001751 Builder.AddTypedTextChunk("using");
1752 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1753 Builder.AddTextChunk("namespace");
1754 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1755 Builder.AddPlaceholderChunk("identifier");
1756 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001757 }
1758
1759 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001760 case Sema::PCC_ForInit:
1761 case Sema::PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00001762 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001763 // Fall through: conditions and statements can have expressions.
1764
Douglas Gregor02688102010-09-14 23:59:36 +00001765 case Sema::PCC_ParenthesizedExpression:
David Blaikie4e4d0842012-03-11 07:00:24 +00001766 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCallf85e1932011-06-15 23:02:42 +00001767 CCC == Sema::PCC_ParenthesizedExpression) {
1768 // (__bridge <type>)<expression>
1769 Builder.AddTypedTextChunk("__bridge");
1770 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1771 Builder.AddPlaceholderChunk("type");
1772 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1773 Builder.AddPlaceholderChunk("expression");
1774 Results.AddResult(Result(Builder.TakeString()));
1775
1776 // (__bridge_transfer <Objective-C type>)<expression>
1777 Builder.AddTypedTextChunk("__bridge_transfer");
1778 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1779 Builder.AddPlaceholderChunk("Objective-C type");
1780 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1781 Builder.AddPlaceholderChunk("expression");
1782 Results.AddResult(Result(Builder.TakeString()));
1783
1784 // (__bridge_retained <CF type>)<expression>
1785 Builder.AddTypedTextChunk("__bridge_retained");
1786 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1787 Builder.AddPlaceholderChunk("CF type");
1788 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1789 Builder.AddPlaceholderChunk("expression");
1790 Results.AddResult(Result(Builder.TakeString()));
1791 }
1792 // Fall through
1793
John McCallf312b1e2010-08-26 23:41:50 +00001794 case Sema::PCC_Expression: {
David Blaikie4e4d0842012-03-11 07:00:24 +00001795 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001796 // 'this', if we're in a non-static member function.
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001797 addThisCompletion(SemaRef, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001798
Douglas Gregor8ca72082011-10-18 21:20:17 +00001799 // true
1800 Builder.AddResultTypeChunk("bool");
1801 Builder.AddTypedTextChunk("true");
1802 Results.AddResult(Result(Builder.TakeString()));
1803
1804 // false
1805 Builder.AddResultTypeChunk("bool");
1806 Builder.AddTypedTextChunk("false");
1807 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001808
David Blaikie4e4d0842012-03-11 07:00:24 +00001809 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001810 // dynamic_cast < type-id > ( expression )
1811 Builder.AddTypedTextChunk("dynamic_cast");
1812 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1813 Builder.AddPlaceholderChunk("type");
1814 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1815 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1816 Builder.AddPlaceholderChunk("expression");
1817 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1818 Results.AddResult(Result(Builder.TakeString()));
1819 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001820
1821 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001822 Builder.AddTypedTextChunk("static_cast");
1823 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1824 Builder.AddPlaceholderChunk("type");
1825 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1826 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1827 Builder.AddPlaceholderChunk("expression");
1828 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1829 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001830
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001831 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001832 Builder.AddTypedTextChunk("reinterpret_cast");
1833 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1834 Builder.AddPlaceholderChunk("type");
1835 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1836 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1837 Builder.AddPlaceholderChunk("expression");
1838 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1839 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001840
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001841 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001842 Builder.AddTypedTextChunk("const_cast");
1843 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1844 Builder.AddPlaceholderChunk("type");
1845 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1846 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1847 Builder.AddPlaceholderChunk("expression");
1848 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1849 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001850
David Blaikie4e4d0842012-03-11 07:00:24 +00001851 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001852 // typeid ( expression-or-type )
Douglas Gregor8ca72082011-10-18 21:20:17 +00001853 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001854 Builder.AddTypedTextChunk("typeid");
1855 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1856 Builder.AddPlaceholderChunk("expression-or-type");
1857 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1858 Results.AddResult(Result(Builder.TakeString()));
1859 }
1860
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001861 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001862 Builder.AddTypedTextChunk("new");
1863 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1864 Builder.AddPlaceholderChunk("type");
1865 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1866 Builder.AddPlaceholderChunk("expressions");
1867 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1868 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001869
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001870 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001871 Builder.AddTypedTextChunk("new");
1872 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1873 Builder.AddPlaceholderChunk("type");
1874 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1875 Builder.AddPlaceholderChunk("size");
1876 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1877 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1878 Builder.AddPlaceholderChunk("expressions");
1879 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1880 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001881
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001882 // delete expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001883 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001884 Builder.AddTypedTextChunk("delete");
1885 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1886 Builder.AddPlaceholderChunk("expression");
1887 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001888
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001889 // delete [] expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001890 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001891 Builder.AddTypedTextChunk("delete");
1892 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1893 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1894 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1895 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1896 Builder.AddPlaceholderChunk("expression");
1897 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001898
David Blaikie4e4d0842012-03-11 07:00:24 +00001899 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001900 // throw expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001901 Builder.AddResultTypeChunk("void");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001902 Builder.AddTypedTextChunk("throw");
1903 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1904 Builder.AddPlaceholderChunk("expression");
1905 Results.AddResult(Result(Builder.TakeString()));
1906 }
Douglas Gregora50216c2011-10-18 16:29:03 +00001907
Douglas Gregor12e13132010-05-26 22:00:08 +00001908 // FIXME: Rethrow?
Douglas Gregora50216c2011-10-18 16:29:03 +00001909
David Blaikie4e4d0842012-03-11 07:00:24 +00001910 if (SemaRef.getLangOpts().CPlusPlus0x) {
Douglas Gregora50216c2011-10-18 16:29:03 +00001911 // nullptr
Douglas Gregor8ca72082011-10-18 21:20:17 +00001912 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001913 Builder.AddTypedTextChunk("nullptr");
1914 Results.AddResult(Result(Builder.TakeString()));
1915
1916 // alignof
Douglas Gregor8ca72082011-10-18 21:20:17 +00001917 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001918 Builder.AddTypedTextChunk("alignof");
1919 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1920 Builder.AddPlaceholderChunk("type");
1921 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1922 Results.AddResult(Result(Builder.TakeString()));
1923
1924 // noexcept
Douglas Gregor8ca72082011-10-18 21:20:17 +00001925 Builder.AddResultTypeChunk("bool");
Douglas Gregora50216c2011-10-18 16:29:03 +00001926 Builder.AddTypedTextChunk("noexcept");
1927 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1928 Builder.AddPlaceholderChunk("expression");
1929 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1930 Results.AddResult(Result(Builder.TakeString()));
1931
1932 // sizeof... expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001933 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001934 Builder.AddTypedTextChunk("sizeof...");
1935 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1936 Builder.AddPlaceholderChunk("parameter-pack");
1937 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1938 Results.AddResult(Result(Builder.TakeString()));
1939 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001940 }
1941
David Blaikie4e4d0842012-03-11 07:00:24 +00001942 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001943 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001944 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1945 // The interface can be NULL.
1946 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregor8ca72082011-10-18 21:20:17 +00001947 if (ID->getSuperClass()) {
1948 std::string SuperType;
1949 SuperType = ID->getSuperClass()->getNameAsString();
1950 if (Method->isInstanceMethod())
1951 SuperType += " *";
1952
1953 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1954 Builder.AddTypedTextChunk("super");
1955 Results.AddResult(Result(Builder.TakeString()));
1956 }
Ted Kremenek681e2562010-05-31 21:43:10 +00001957 }
1958
Douglas Gregorbca403c2010-01-13 23:51:12 +00001959 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001960 }
1961
Jordan Rosef70a8862012-06-30 21:33:57 +00001962 if (SemaRef.getLangOpts().C11) {
1963 // _Alignof
1964 Builder.AddResultTypeChunk("size_t");
1965 if (SemaRef.getASTContext().Idents.get("alignof").hasMacroDefinition())
1966 Builder.AddTypedTextChunk("alignof");
1967 else
1968 Builder.AddTypedTextChunk("_Alignof");
1969 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1970 Builder.AddPlaceholderChunk("type");
1971 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1972 Results.AddResult(Result(Builder.TakeString()));
1973 }
1974
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001975 // sizeof expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001976 Builder.AddResultTypeChunk("size_t");
Douglas Gregor218937c2011-02-01 19:23:04 +00001977 Builder.AddTypedTextChunk("sizeof");
1978 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1979 Builder.AddPlaceholderChunk("expression-or-type");
1980 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1981 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001982 break;
1983 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001984
John McCallf312b1e2010-08-26 23:41:50 +00001985 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001986 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00001987 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001988 }
1989
David Blaikie4e4d0842012-03-11 07:00:24 +00001990 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
1991 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001992
David Blaikie4e4d0842012-03-11 07:00:24 +00001993 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00001994 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001995}
1996
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001997/// \brief If the given declaration has an associated type, add it as a result
1998/// type chunk.
1999static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002000 const PrintingPolicy &Policy,
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002001 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00002002 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002003 if (!ND)
2004 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00002005
2006 // Skip constructors and conversion functions, which have their return types
2007 // built into their names.
2008 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
2009 return;
2010
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002011 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00002012 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002013 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
2014 T = Function->getResultType();
2015 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
2016 T = Method->getResultType();
2017 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
2018 T = FunTmpl->getTemplatedDecl()->getResultType();
2019 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
2020 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
2021 else if (isa<UnresolvedUsingValueDecl>(ND)) {
2022 /* Do nothing: ignore unresolved using declarations*/
John McCallf85e1932011-06-15 23:02:42 +00002023 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002024 T = Value->getType();
John McCallf85e1932011-06-15 23:02:42 +00002025 } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002026 T = Property->getType();
2027
2028 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2029 return;
2030
Douglas Gregor8987b232011-09-27 23:30:47 +00002031 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002032 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002033}
2034
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002035static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00002036 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002037 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2038 if (Sentinel->getSentinel() == 0) {
David Blaikie4e4d0842012-03-11 07:00:24 +00002039 if (Context.getLangOpts().ObjC1 &&
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002040 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002041 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002042 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002043 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002044 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002045 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002046 }
2047}
2048
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002049static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2050 std::string Result;
2051 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002052 Result += "in ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002053 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002054 Result += "inout ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002055 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002056 Result += "out ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002057 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002058 Result += "bycopy ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002059 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002060 Result += "byref ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002061 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002062 Result += "oneway ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002063 return Result;
2064}
2065
Douglas Gregor83482d12010-08-24 16:15:59 +00002066static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002067 const PrintingPolicy &Policy,
Douglas Gregoraba48082010-08-29 19:47:46 +00002068 ParmVarDecl *Param,
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002069 bool SuppressName = false,
2070 bool SuppressBlock = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00002071 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2072 if (Param->getType()->isDependentType() ||
2073 !Param->getType()->isBlockPointerType()) {
2074 // The argument for a dependent or non-block parameter is a placeholder
2075 // containing that parameter's type.
2076 std::string Result;
2077
Douglas Gregoraba48082010-08-29 19:47:46 +00002078 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002079 Result = Param->getIdentifier()->getName();
2080
John McCallf85e1932011-06-15 23:02:42 +00002081 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002082
2083 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002084 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2085 + Result + ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00002086 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002087 Result += Param->getIdentifier()->getName();
2088 }
2089 return Result;
2090 }
2091
2092 // The argument for a block pointer parameter is a block literal with
2093 // the appropriate type.
Douglas Gregor830072c2011-02-15 22:37:09 +00002094 FunctionTypeLoc *Block = 0;
2095 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregor83482d12010-08-24 16:15:59 +00002096 TypeLoc TL;
2097 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2098 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2099 while (true) {
2100 // Look through typedefs.
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002101 if (!SuppressBlock) {
2102 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2103 if (TypeSourceInfo *InnerTSInfo
2104 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2105 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2106 continue;
2107 }
2108 }
2109
2110 // Look through qualified types
2111 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2112 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregor83482d12010-08-24 16:15:59 +00002113 continue;
2114 }
2115 }
2116
Douglas Gregor83482d12010-08-24 16:15:59 +00002117 // Try to get the function prototype behind the block pointer type,
2118 // then we're done.
2119 if (BlockPointerTypeLoc *BlockPtr
2120 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00002121 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor830072c2011-02-15 22:37:09 +00002122 Block = dyn_cast<FunctionTypeLoc>(&TL);
2123 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregor83482d12010-08-24 16:15:59 +00002124 }
2125 break;
2126 }
2127 }
2128
2129 if (!Block) {
2130 // We were unable to find a FunctionProtoTypeLoc with parameter names
2131 // for the block; just use the parameter type as a placeholder.
2132 std::string Result;
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002133 if (!ObjCMethodParam && Param->getIdentifier())
2134 Result = Param->getIdentifier()->getName();
2135
John McCallf85e1932011-06-15 23:02:42 +00002136 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002137
2138 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002139 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2140 + Result + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002141 if (Param->getIdentifier())
2142 Result += Param->getIdentifier()->getName();
2143 }
2144
2145 return Result;
2146 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002147
Douglas Gregor83482d12010-08-24 16:15:59 +00002148 // We have the function prototype behind the block pointer type, as it was
2149 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00002150 std::string Result;
2151 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002152 if (!ResultType->isVoidType() || SuppressBlock)
John McCallf85e1932011-06-15 23:02:42 +00002153 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002154
2155 // Format the parameter list.
2156 std::string Params;
Douglas Gregor830072c2011-02-15 22:37:09 +00002157 if (!BlockProto || Block->getNumArgs() == 0) {
2158 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002159 Params = "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00002160 else
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002161 Params = "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00002162 } else {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002163 Params += "(";
Douglas Gregor38276252010-09-08 22:47:51 +00002164 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2165 if (I)
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002166 Params += ", ";
2167 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2168 /*SuppressName=*/false,
2169 /*SuppressBlock=*/true);
Douglas Gregor38276252010-09-08 22:47:51 +00002170
Douglas Gregor830072c2011-02-15 22:37:09 +00002171 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002172 Params += ", ...";
Douglas Gregor38276252010-09-08 22:47:51 +00002173 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002174 Params += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00002175 }
Douglas Gregor38276252010-09-08 22:47:51 +00002176
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002177 if (SuppressBlock) {
2178 // Format as a parameter.
2179 Result = Result + " (^";
2180 if (Param->getIdentifier())
2181 Result += Param->getIdentifier()->getName();
2182 Result += ")";
2183 Result += Params;
2184 } else {
2185 // Format as a block literal argument.
2186 Result = '^' + Result;
2187 Result += Params;
2188
2189 if (Param->getIdentifier())
2190 Result += Param->getIdentifier()->getName();
2191 }
2192
Douglas Gregor83482d12010-08-24 16:15:59 +00002193 return Result;
2194}
2195
Douglas Gregor86d9a522009-09-21 16:56:56 +00002196/// \brief Add function parameter chunks to the given code completion string.
2197static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002198 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002199 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00002200 CodeCompletionBuilder &Result,
2201 unsigned Start = 0,
2202 bool InOptional = false) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002203 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002204
Douglas Gregor218937c2011-02-01 19:23:04 +00002205 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002206 ParmVarDecl *Param = Function->getParamDecl(P);
2207
Douglas Gregor218937c2011-02-01 19:23:04 +00002208 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002209 // When we see an optional default argument, put that argument and
2210 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002211 CodeCompletionBuilder Opt(Result.getAllocator(),
2212 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002213 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002214 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002215 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregor218937c2011-02-01 19:23:04 +00002216 Result.AddOptionalChunk(Opt.TakeString());
2217 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002218 }
2219
Douglas Gregor218937c2011-02-01 19:23:04 +00002220 if (FirstParameter)
2221 FirstParameter = false;
2222 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002223 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor218937c2011-02-01 19:23:04 +00002224
2225 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002226
2227 // Format the placeholder string.
Douglas Gregor8987b232011-09-27 23:30:47 +00002228 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2229 Param);
Douglas Gregor83482d12010-08-24 16:15:59 +00002230
Douglas Gregore17794f2010-08-31 05:13:43 +00002231 if (Function->isVariadic() && P == N - 1)
2232 PlaceholderStr += ", ...";
2233
Douglas Gregor86d9a522009-09-21 16:56:56 +00002234 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002235 Result.AddPlaceholderChunk(
2236 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002237 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002238
2239 if (const FunctionProtoType *Proto
2240 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002241 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002242 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002243 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002244
Douglas Gregor218937c2011-02-01 19:23:04 +00002245 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002246 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002247}
2248
2249/// \brief Add template parameter chunks to the given code completion string.
2250static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002251 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002252 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002253 CodeCompletionBuilder &Result,
2254 unsigned MaxParameters = 0,
2255 unsigned Start = 0,
2256 bool InDefaultArg = false) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002257 bool FirstParameter = true;
2258
2259 TemplateParameterList *Params = Template->getTemplateParameters();
2260 TemplateParameterList::iterator PEnd = Params->end();
2261 if (MaxParameters)
2262 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002263 for (TemplateParameterList::iterator P = Params->begin() + Start;
2264 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002265 bool HasDefaultArg = false;
2266 std::string PlaceholderStr;
2267 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2268 if (TTP->wasDeclaredWithTypename())
2269 PlaceholderStr = "typename";
2270 else
2271 PlaceholderStr = "class";
2272
2273 if (TTP->getIdentifier()) {
2274 PlaceholderStr += ' ';
2275 PlaceholderStr += TTP->getIdentifier()->getName();
2276 }
2277
2278 HasDefaultArg = TTP->hasDefaultArgument();
2279 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002280 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002281 if (NTTP->getIdentifier())
2282 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCallf85e1932011-06-15 23:02:42 +00002283 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002284 HasDefaultArg = NTTP->hasDefaultArgument();
2285 } else {
2286 assert(isa<TemplateTemplateParmDecl>(*P));
2287 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2288
2289 // Since putting the template argument list into the placeholder would
2290 // be very, very long, we just use an abbreviation.
2291 PlaceholderStr = "template<...> class";
2292 if (TTP->getIdentifier()) {
2293 PlaceholderStr += ' ';
2294 PlaceholderStr += TTP->getIdentifier()->getName();
2295 }
2296
2297 HasDefaultArg = TTP->hasDefaultArgument();
2298 }
2299
Douglas Gregor218937c2011-02-01 19:23:04 +00002300 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002301 // When we see an optional default argument, put that argument and
2302 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002303 CodeCompletionBuilder Opt(Result.getAllocator(),
2304 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002305 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002306 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002307 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregor218937c2011-02-01 19:23:04 +00002308 P - Params->begin(), true);
2309 Result.AddOptionalChunk(Opt.TakeString());
2310 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002311 }
2312
Douglas Gregor218937c2011-02-01 19:23:04 +00002313 InDefaultArg = false;
2314
Douglas Gregor86d9a522009-09-21 16:56:56 +00002315 if (FirstParameter)
2316 FirstParameter = false;
2317 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002318 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002319
2320 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002321 Result.AddPlaceholderChunk(
2322 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002323 }
2324}
2325
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002326/// \brief Add a qualifier to the given code-completion string, if the
2327/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002328static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002329AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002330 NestedNameSpecifier *Qualifier,
2331 bool QualifierIsInformative,
Douglas Gregor8987b232011-09-27 23:30:47 +00002332 ASTContext &Context,
2333 const PrintingPolicy &Policy) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002334 if (!Qualifier)
2335 return;
2336
2337 std::string PrintedNNS;
2338 {
2339 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor8987b232011-09-27 23:30:47 +00002340 Qualifier->print(OS, Policy);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002341 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002342 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002343 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002344 else
Douglas Gregordae68752011-02-01 22:57:45 +00002345 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002346}
2347
Douglas Gregor218937c2011-02-01 19:23:04 +00002348static void
2349AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2350 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002351 const FunctionProtoType *Proto
2352 = Function->getType()->getAs<FunctionProtoType>();
2353 if (!Proto || !Proto->getTypeQuals())
2354 return;
2355
Douglas Gregora63f6de2011-02-01 21:15:40 +00002356 // FIXME: Add ref-qualifier!
2357
2358 // Handle single qualifiers without copying
2359 if (Proto->getTypeQuals() == Qualifiers::Const) {
2360 Result.AddInformativeChunk(" const");
2361 return;
2362 }
2363
2364 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2365 Result.AddInformativeChunk(" volatile");
2366 return;
2367 }
2368
2369 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2370 Result.AddInformativeChunk(" restrict");
2371 return;
2372 }
2373
2374 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002375 std::string QualsStr;
David Blaikie4ef832f2012-08-10 00:55:35 +00002376 if (Proto->isConst())
Douglas Gregora61a8792009-12-11 18:44:16 +00002377 QualsStr += " const";
David Blaikie4ef832f2012-08-10 00:55:35 +00002378 if (Proto->isVolatile())
Douglas Gregora61a8792009-12-11 18:44:16 +00002379 QualsStr += " volatile";
David Blaikie4ef832f2012-08-10 00:55:35 +00002380 if (Proto->isRestrict())
Douglas Gregora61a8792009-12-11 18:44:16 +00002381 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002382 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002383}
2384
Douglas Gregor6f942b22010-09-21 16:06:22 +00002385/// \brief Add the name of the given declaration
Douglas Gregor8987b232011-09-27 23:30:47 +00002386static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
2387 NamedDecl *ND, CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002388 DeclarationName Name = ND->getDeclName();
2389 if (!Name)
2390 return;
2391
2392 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002393 case DeclarationName::CXXOperatorName: {
2394 const char *OperatorName = 0;
2395 switch (Name.getCXXOverloadedOperator()) {
2396 case OO_None:
2397 case OO_Conditional:
2398 case NUM_OVERLOADED_OPERATORS:
2399 OperatorName = "operator";
2400 break;
2401
2402#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2403 case OO_##Name: OperatorName = "operator" Spelling; break;
2404#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2405#include "clang/Basic/OperatorKinds.def"
2406
2407 case OO_New: OperatorName = "operator new"; break;
2408 case OO_Delete: OperatorName = "operator delete"; break;
2409 case OO_Array_New: OperatorName = "operator new[]"; break;
2410 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2411 case OO_Call: OperatorName = "operator()"; break;
2412 case OO_Subscript: OperatorName = "operator[]"; break;
2413 }
2414 Result.AddTypedTextChunk(OperatorName);
2415 break;
2416 }
2417
Douglas Gregor6f942b22010-09-21 16:06:22 +00002418 case DeclarationName::Identifier:
2419 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002420 case DeclarationName::CXXDestructorName:
2421 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002422 Result.AddTypedTextChunk(
2423 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002424 break;
2425
2426 case DeclarationName::CXXUsingDirective:
2427 case DeclarationName::ObjCZeroArgSelector:
2428 case DeclarationName::ObjCOneArgSelector:
2429 case DeclarationName::ObjCMultiArgSelector:
2430 break;
2431
2432 case DeclarationName::CXXConstructorName: {
2433 CXXRecordDecl *Record = 0;
2434 QualType Ty = Name.getCXXNameType();
2435 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2436 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2437 else if (const InjectedClassNameType *InjectedTy
2438 = Ty->getAs<InjectedClassNameType>())
2439 Record = InjectedTy->getDecl();
2440 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002441 Result.AddTypedTextChunk(
2442 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002443 break;
2444 }
2445
Douglas Gregordae68752011-02-01 22:57:45 +00002446 Result.AddTypedTextChunk(
2447 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002448 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002449 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor8987b232011-09-27 23:30:47 +00002450 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002451 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002452 }
2453 break;
2454 }
2455 }
2456}
2457
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002458CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002459 CodeCompletionAllocator &Allocator,
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002460 CodeCompletionTUInfo &CCTUInfo,
2461 bool IncludeBriefComments) {
2462 return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo,
2463 IncludeBriefComments);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002464}
2465
Douglas Gregor86d9a522009-09-21 16:56:56 +00002466/// \brief If possible, create a new code completion string for the given
2467/// result.
2468///
2469/// \returns Either a new, heap-allocated code completion string describing
2470/// how to use this result, or NULL to indicate that the string or name of the
2471/// result is all that is needed.
2472CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002473CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2474 Preprocessor &PP,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002475 CodeCompletionAllocator &Allocator,
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002476 CodeCompletionTUInfo &CCTUInfo,
2477 bool IncludeBriefComments) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002478 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002479
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002480 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002481 if (Kind == RK_Pattern) {
2482 Pattern->Priority = Priority;
2483 Pattern->Availability = Availability;
Douglas Gregorba103062012-03-27 23:34:16 +00002484
2485 if (Declaration) {
2486 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregorba103062012-03-27 23:34:16 +00002487 Pattern->ParentName = Result.getParentName();
2488 }
2489
Douglas Gregor218937c2011-02-01 19:23:04 +00002490 return Pattern;
2491 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002492
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002493 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002494 Result.AddTypedTextChunk(Keyword);
2495 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002496 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002497
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002498 if (Kind == RK_Macro) {
Douglas Gregor3644d972012-10-09 16:01:50 +00002499 MacroInfo *MI = PP.getMacroInfoHistory(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002500 assert(MI && "Not a macro?");
2501
Douglas Gregordae68752011-02-01 22:57:45 +00002502 Result.AddTypedTextChunk(
2503 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002504
2505 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002506 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002507
2508 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002509 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregore4244702011-07-30 08:17:44 +00002510 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002511
2512 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2513 if (MI->isC99Varargs()) {
2514 --AEnd;
2515
2516 if (A == AEnd) {
2517 Result.AddPlaceholderChunk("...");
2518 }
Douglas Gregore4244702011-07-30 08:17:44 +00002519 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002520
Douglas Gregore4244702011-07-30 08:17:44 +00002521 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002522 if (A != MI->arg_begin())
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002523 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002524
2525 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002526 SmallString<32> Arg = (*A)->getName();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002527 if (MI->isC99Varargs())
2528 Arg += ", ...";
2529 else
2530 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002531 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002532 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002533 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002534
2535 // Non-variadic macros are simple.
2536 Result.AddPlaceholderChunk(
2537 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002538 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002539 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002540 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002541 }
2542
Douglas Gregord8e8a582010-05-25 21:41:55 +00002543 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002544 NamedDecl *ND = Declaration;
Douglas Gregorba103062012-03-27 23:34:16 +00002545 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002546
2547 if (IncludeBriefComments) {
2548 // Add documentation comment, if it exists.
Dmitri Gribenkof50555e2012-08-11 00:51:43 +00002549 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002550 Result.addBriefComment(RC->getBriefText(Ctx));
2551 }
2552 }
2553
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002554 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002555 Result.AddTypedTextChunk(
2556 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002557 Result.AddTextChunk("::");
2558 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002559 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002560
2561 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2562 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2563 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2564 }
2565 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002566
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002567 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002568
Douglas Gregor86d9a522009-09-21 16:56:56 +00002569 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002570 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002571 Ctx, Policy);
2572 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002573 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002574 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002575 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002576 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002577 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002578 }
2579
2580 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002581 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002582 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002583 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002584 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002585
Douglas Gregor86d9a522009-09-21 16:56:56 +00002586 // Figure out which template parameters are deduced (or have default
2587 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002588 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002589 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002590 unsigned LastDeducibleArgument;
2591 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2592 --LastDeducibleArgument) {
2593 if (!Deduced[LastDeducibleArgument - 1]) {
2594 // C++0x: Figure out if the template argument has a default. If so,
2595 // the user doesn't need to type this argument.
2596 // FIXME: We need to abstract template parameters better!
2597 bool HasDefaultArg = false;
2598 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002599 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002600 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2601 HasDefaultArg = TTP->hasDefaultArgument();
2602 else if (NonTypeTemplateParmDecl *NTTP
2603 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2604 HasDefaultArg = NTTP->hasDefaultArgument();
2605 else {
2606 assert(isa<TemplateTemplateParmDecl>(Param));
2607 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002608 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002609 }
2610
2611 if (!HasDefaultArg)
2612 break;
2613 }
2614 }
2615
2616 if (LastDeducibleArgument) {
2617 // Some of the function template arguments cannot be deduced from a
2618 // function call, so we introduce an explicit template argument list
2619 // containing all of the arguments up to the first deducible argument.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002620 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002621 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002622 LastDeducibleArgument);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002623 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002624 }
2625
2626 // Add the function parameters
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002627 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002628 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002629 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002630 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002631 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002632 }
2633
2634 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002635 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002636 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002637 Result.AddTypedTextChunk(
2638 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002639 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002640 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002641 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor218937c2011-02-01 19:23:04 +00002642 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002643 }
2644
Douglas Gregor9630eb62009-11-17 16:44:22 +00002645 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002646 Selector Sel = Method->getSelector();
2647 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002648 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002649 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002650 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002651 }
2652
Douglas Gregor813d8342011-02-18 22:29:55 +00002653 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002654 SelName += ':';
2655 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002656 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002657 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002658 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002659
2660 // If there is only one parameter, and we're past it, add an empty
2661 // typed-text chunk since there is nothing to type.
2662 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002663 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002664 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002665 unsigned Idx = 0;
2666 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2667 PEnd = Method->param_end();
2668 P != PEnd; (void)++P, ++Idx) {
2669 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002670 std::string Keyword;
2671 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002672 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002673 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002674 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002675 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002676 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002677 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002678 else
Douglas Gregordae68752011-02-01 22:57:45 +00002679 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002680 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002681
2682 // If we're before the starting parameter, skip the placeholder.
2683 if (Idx < StartParameter)
2684 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002685
2686 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002687
2688 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002689 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002690 else {
John McCallf85e1932011-06-15 23:02:42 +00002691 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002692 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2693 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002694 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002695 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002696 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002697 }
2698
Douglas Gregore17794f2010-08-31 05:13:43 +00002699 if (Method->isVariadic() && (P + 1) == PEnd)
2700 Arg += ", ...";
2701
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002702 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002703 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002704 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002705 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002706 else
Douglas Gregordae68752011-02-01 22:57:45 +00002707 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002708 }
2709
Douglas Gregor2a17af02009-12-23 00:21:46 +00002710 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002711 if (Method->param_size() == 0) {
2712 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002713 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002714 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002715 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002716 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002717 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002718 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002719
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002720 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002721 }
2722
Douglas Gregor218937c2011-02-01 19:23:04 +00002723 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002724 }
2725
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002726 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002727 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002728 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002729
Douglas Gregordae68752011-02-01 22:57:45 +00002730 Result.AddTypedTextChunk(
2731 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002732 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002733}
2734
Douglas Gregor86d802e2009-09-23 00:34:09 +00002735CodeCompletionString *
2736CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2737 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002738 Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002739 CodeCompletionAllocator &Allocator,
2740 CodeCompletionTUInfo &CCTUInfo) const {
Douglas Gregor8987b232011-09-27 23:30:47 +00002741 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002742
Douglas Gregor218937c2011-02-01 19:23:04 +00002743 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002744 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002745 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002746 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002747 const FunctionProtoType *Proto
2748 = dyn_cast<FunctionProtoType>(getFunctionType());
2749 if (!FDecl && !Proto) {
2750 // Function without a prototype. Just give the return type and a
2751 // highlighted ellipsis.
2752 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002753 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002754 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002755 Result.getAllocator()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002756 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2757 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2758 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002759 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002760 }
2761
2762 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002763 Result.AddTextChunk(
2764 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002765 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002766 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002767 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002768 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002769
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002770 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002771 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2772 for (unsigned I = 0; I != NumParams; ++I) {
2773 if (I)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002774 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002775
2776 std::string ArgString;
2777 QualType ArgType;
2778
2779 if (FDecl) {
2780 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2781 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2782 } else {
2783 ArgType = Proto->getArgType(I);
2784 }
2785
John McCallf85e1932011-06-15 23:02:42 +00002786 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002787
2788 if (I == CurrentArg)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002789 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2790 Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002791 else
Douglas Gregordae68752011-02-01 22:57:45 +00002792 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002793 }
2794
2795 if (Proto && Proto->isVariadic()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002796 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002797 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002798 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002799 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002800 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002801 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002802 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002803
Douglas Gregor218937c2011-02-01 19:23:04 +00002804 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002805}
2806
Chris Lattner5f9e2722011-07-23 10:55:15 +00002807unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002808 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002809 bool PreferredTypeIsPointer) {
2810 unsigned Priority = CCP_Macro;
2811
Douglas Gregorb05496d2010-09-20 21:11:48 +00002812 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2813 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2814 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002815 Priority = CCP_Constant;
2816 if (PreferredTypeIsPointer)
2817 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002818 }
2819 // Treat "YES", "NO", "true", and "false" as constants.
2820 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2821 MacroName.equals("true") || MacroName.equals("false"))
2822 Priority = CCP_Constant;
2823 // Treat "bool" as a type.
2824 else if (MacroName.equals("bool"))
2825 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2826
Douglas Gregor1827e102010-08-16 16:18:59 +00002827
2828 return Priority;
2829}
2830
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002831CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2832 if (!D)
2833 return CXCursor_UnexposedDecl;
2834
2835 switch (D->getKind()) {
2836 case Decl::Enum: return CXCursor_EnumDecl;
2837 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2838 case Decl::Field: return CXCursor_FieldDecl;
2839 case Decl::Function:
2840 return CXCursor_FunctionDecl;
2841 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2842 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002843 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002844
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002845 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002846 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2847 case Decl::ObjCMethod:
2848 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2849 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2850 case Decl::CXXMethod: return CXCursor_CXXMethod;
2851 case Decl::CXXConstructor: return CXCursor_Constructor;
2852 case Decl::CXXDestructor: return CXCursor_Destructor;
2853 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2854 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002855 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002856 case Decl::ParmVar: return CXCursor_ParmDecl;
2857 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002858 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002859 case Decl::Var: return CXCursor_VarDecl;
2860 case Decl::Namespace: return CXCursor_Namespace;
2861 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2862 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2863 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2864 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2865 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2866 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002867 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002868 case Decl::ClassTemplatePartialSpecialization:
2869 return CXCursor_ClassTemplatePartialSpecialization;
2870 case Decl::UsingDirective: return CXCursor_UsingDirective;
Douglas Gregor8e5900c2012-04-30 23:41:16 +00002871 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002872
2873 case Decl::Using:
2874 case Decl::UnresolvedUsingValue:
2875 case Decl::UnresolvedUsingTypename:
2876 return CXCursor_UsingDeclaration;
2877
Douglas Gregor352697a2011-06-03 23:08:58 +00002878 case Decl::ObjCPropertyImpl:
2879 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2880 case ObjCPropertyImplDecl::Dynamic:
2881 return CXCursor_ObjCDynamicDecl;
2882
2883 case ObjCPropertyImplDecl::Synthesize:
2884 return CXCursor_ObjCSynthesizeDecl;
2885 }
Argyrios Kyrtzidis6a010122012-10-05 00:22:24 +00002886
2887 case Decl::Import:
2888 return CXCursor_ModuleImportDecl;
Douglas Gregor352697a2011-06-03 23:08:58 +00002889
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002890 default:
2891 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2892 switch (TD->getTagKind()) {
Joao Matos6666ed42012-08-31 18:45:21 +00002893 case TTK_Interface: // fall through
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002894 case TTK_Struct: return CXCursor_StructDecl;
2895 case TTK_Class: return CXCursor_ClassDecl;
2896 case TTK_Union: return CXCursor_UnionDecl;
2897 case TTK_Enum: return CXCursor_EnumDecl;
2898 }
2899 }
2900 }
2901
2902 return CXCursor_UnexposedDecl;
2903}
2904
Douglas Gregor590c7d52010-07-08 20:55:51 +00002905static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Douglas Gregor3644d972012-10-09 16:01:50 +00002906 bool IncludeUndefined,
Douglas Gregor590c7d52010-07-08 20:55:51 +00002907 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002908 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002909
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002910 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002911
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002912 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2913 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002914 M != MEnd; ++M) {
Douglas Gregor3644d972012-10-09 16:01:50 +00002915 if (IncludeUndefined || M->first->hasMacroDefinition())
2916 Results.AddResult(Result(M->first,
Douglas Gregor1827e102010-08-16 16:18:59 +00002917 getMacroUsagePriority(M->first->getName(),
David Blaikie4e4d0842012-03-11 07:00:24 +00002918 PP.getLangOpts(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002919 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002920 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002921
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002922 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002923
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002924}
2925
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002926static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2927 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002928 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002929
2930 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002931
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002932 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2933 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2934 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2935 Results.AddResult(Result("__func__", CCP_Constant));
2936 Results.ExitScope();
2937}
2938
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002939static void HandleCodeCompleteResults(Sema *S,
2940 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002941 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002942 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002943 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002944 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002945 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002946}
2947
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002948static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2949 Sema::ParserCompletionContext PCC) {
2950 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002951 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002952 return CodeCompletionContext::CCC_TopLevel;
2953
John McCallf312b1e2010-08-26 23:41:50 +00002954 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002955 return CodeCompletionContext::CCC_ClassStructUnion;
2956
John McCallf312b1e2010-08-26 23:41:50 +00002957 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002958 return CodeCompletionContext::CCC_ObjCInterface;
2959
John McCallf312b1e2010-08-26 23:41:50 +00002960 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002961 return CodeCompletionContext::CCC_ObjCImplementation;
2962
John McCallf312b1e2010-08-26 23:41:50 +00002963 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002964 return CodeCompletionContext::CCC_ObjCIvarList;
2965
John McCallf312b1e2010-08-26 23:41:50 +00002966 case Sema::PCC_Template:
2967 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002968 if (S.CurContext->isFileContext())
2969 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002970 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002971 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002972 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002973
John McCallf312b1e2010-08-26 23:41:50 +00002974 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002975 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002976
John McCallf312b1e2010-08-26 23:41:50 +00002977 case Sema::PCC_ForInit:
David Blaikie4e4d0842012-03-11 07:00:24 +00002978 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2979 S.getLangOpts().ObjC1)
Douglas Gregora5450a02010-10-18 22:01:46 +00002980 return CodeCompletionContext::CCC_ParenthesizedExpression;
2981 else
2982 return CodeCompletionContext::CCC_Expression;
2983
2984 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002985 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002986 return CodeCompletionContext::CCC_Expression;
2987
John McCallf312b1e2010-08-26 23:41:50 +00002988 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002989 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002990
John McCallf312b1e2010-08-26 23:41:50 +00002991 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002992 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002993
2994 case Sema::PCC_ParenthesizedExpression:
2995 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002996
2997 case Sema::PCC_LocalDeclarationSpecifiers:
2998 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002999 }
David Blaikie7530c032012-01-17 06:56:22 +00003000
3001 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003002}
3003
Douglas Gregorf6961522010-08-27 21:18:54 +00003004/// \brief If we're in a C++ virtual member function, add completion results
3005/// that invoke the functions we override, since it's common to invoke the
3006/// overridden function as well as adding new functionality.
3007///
3008/// \param S The semantic analysis object for which we are generating results.
3009///
3010/// \param InContext This context in which the nested-name-specifier preceding
3011/// the code-completion point
3012static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3013 ResultBuilder &Results) {
3014 // Look through blocks.
3015 DeclContext *CurContext = S.CurContext;
3016 while (isa<BlockDecl>(CurContext))
3017 CurContext = CurContext->getParent();
3018
3019
3020 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3021 if (!Method || !Method->isVirtual())
3022 return;
3023
3024 // We need to have names for all of the parameters, if we're going to
3025 // generate a forwarding call.
3026 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3027 PEnd = Method->param_end();
3028 P != PEnd;
3029 ++P) {
3030 if (!(*P)->getDeclName())
3031 return;
3032 }
3033
Douglas Gregor8987b232011-09-27 23:30:47 +00003034 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00003035 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
3036 MEnd = Method->end_overridden_methods();
3037 M != MEnd; ++M) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003038 CodeCompletionBuilder Builder(Results.getAllocator(),
3039 Results.getCodeCompletionTUInfo());
Douglas Gregorf6961522010-08-27 21:18:54 +00003040 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
3041 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3042 continue;
3043
3044 // If we need a nested-name-specifier, add one now.
3045 if (!InContext) {
3046 NestedNameSpecifier *NNS
3047 = getRequiredQualification(S.Context, CurContext,
3048 Overridden->getDeclContext());
3049 if (NNS) {
3050 std::string Str;
3051 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00003052 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00003053 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003054 }
3055 } else if (!InContext->Equals(Overridden->getDeclContext()))
3056 continue;
3057
Douglas Gregordae68752011-02-01 22:57:45 +00003058 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003059 Overridden->getNameAsString()));
3060 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00003061 bool FirstParam = true;
3062 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3063 PEnd = Method->param_end();
3064 P != PEnd; ++P) {
3065 if (FirstParam)
3066 FirstParam = false;
3067 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003068 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003069
Douglas Gregordae68752011-02-01 22:57:45 +00003070 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003071 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003072 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003073 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3074 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003075 CCP_SuperCompletion,
Douglas Gregorba103062012-03-27 23:34:16 +00003076 CXCursor_CXXMethod,
3077 CXAvailability_Available,
3078 Overridden));
Douglas Gregorf6961522010-08-27 21:18:54 +00003079 Results.Ignore(Overridden);
3080 }
3081}
3082
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003083void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3084 ModuleIdPath Path) {
3085 typedef CodeCompletionResult Result;
3086 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003087 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003088 CodeCompletionContext::CCC_Other);
3089 Results.EnterNewScope();
3090
3091 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003092 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003093 typedef CodeCompletionResult Result;
3094 if (Path.empty()) {
3095 // Enumerate all top-level modules.
3096 llvm::SmallVector<Module *, 8> Modules;
3097 PP.getHeaderSearchInfo().collectAllModules(Modules);
3098 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3099 Builder.AddTypedTextChunk(
3100 Builder.getAllocator().CopyString(Modules[I]->Name));
3101 Results.AddResult(Result(Builder.TakeString(),
3102 CCP_Declaration,
3103 CXCursor_NotImplemented,
3104 Modules[I]->isAvailable()
3105 ? CXAvailability_Available
3106 : CXAvailability_NotAvailable));
3107 }
3108 } else {
3109 // Load the named module.
3110 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3111 Module::AllVisible,
3112 /*IsInclusionDirective=*/false);
3113 // Enumerate submodules.
3114 if (Mod) {
3115 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3116 SubEnd = Mod->submodule_end();
3117 Sub != SubEnd; ++Sub) {
3118
3119 Builder.AddTypedTextChunk(
3120 Builder.getAllocator().CopyString((*Sub)->Name));
3121 Results.AddResult(Result(Builder.TakeString(),
3122 CCP_Declaration,
3123 CXCursor_NotImplemented,
3124 (*Sub)->isAvailable()
3125 ? CXAvailability_Available
3126 : CXAvailability_NotAvailable));
3127 }
3128 }
3129 }
3130 Results.ExitScope();
3131 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3132 Results.data(),Results.size());
3133}
3134
Douglas Gregor01dfea02010-01-10 23:08:15 +00003135void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003136 ParserCompletionContext CompletionContext) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003137 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003138 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003139 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003140 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003141
Douglas Gregor01dfea02010-01-10 23:08:15 +00003142 // Determine how to filter results, e.g., so that the names of
3143 // values (functions, enumerators, function templates, etc.) are
3144 // only allowed where we can have an expression.
3145 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003146 case PCC_Namespace:
3147 case PCC_Class:
3148 case PCC_ObjCInterface:
3149 case PCC_ObjCImplementation:
3150 case PCC_ObjCInstanceVariableList:
3151 case PCC_Template:
3152 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003153 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003154 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003155 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3156 break;
3157
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003158 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003159 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003160 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003161 case PCC_ForInit:
3162 case PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00003163 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003164 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3165 else
3166 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003167
David Blaikie4e4d0842012-03-11 07:00:24 +00003168 if (getLangOpts().CPlusPlus)
Douglas Gregorf6961522010-08-27 21:18:54 +00003169 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003170 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003171
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003172 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003173 // Unfiltered
3174 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003175 }
3176
Douglas Gregor3cdee122010-08-26 16:36:48 +00003177 // If we are in a C++ non-static member function, check the qualifiers on
3178 // the member function to filter/prioritize the results list.
3179 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3180 if (CurMethod->isInstance())
3181 Results.setObjectTypeQualifiers(
3182 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3183
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003184 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003185 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3186 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003187
Douglas Gregorbca403c2010-01-13 23:51:12 +00003188 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003189 Results.ExitScope();
3190
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003191 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003192 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003193 case PCC_Expression:
3194 case PCC_Statement:
3195 case PCC_RecoveryInFunction:
3196 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003197 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor72db1082010-08-24 01:11:00 +00003198 break;
3199
3200 case PCC_Namespace:
3201 case PCC_Class:
3202 case PCC_ObjCInterface:
3203 case PCC_ObjCImplementation:
3204 case PCC_ObjCInstanceVariableList:
3205 case PCC_Template:
3206 case PCC_MemberTemplate:
3207 case PCC_ForInit:
3208 case PCC_Condition:
3209 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003210 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003211 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003212 }
3213
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003214 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003215 AddMacroResults(PP, Results, false);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003216
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003217 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003218 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003219}
3220
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003221static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3222 ParsedType Receiver,
3223 IdentifierInfo **SelIdents,
3224 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003225 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003226 bool IsSuper,
3227 ResultBuilder &Results);
3228
3229void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3230 bool AllowNonIdentifiers,
3231 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003232 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003233 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003234 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003235 AllowNestedNameSpecifiers
3236 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3237 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003238 Results.EnterNewScope();
3239
3240 // Type qualifiers can come after names.
3241 Results.AddResult(Result("const"));
3242 Results.AddResult(Result("volatile"));
David Blaikie4e4d0842012-03-11 07:00:24 +00003243 if (getLangOpts().C99)
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003244 Results.AddResult(Result("restrict"));
3245
David Blaikie4e4d0842012-03-11 07:00:24 +00003246 if (getLangOpts().CPlusPlus) {
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003247 if (AllowNonIdentifiers) {
3248 Results.AddResult(Result("operator"));
3249 }
3250
3251 // Add nested-name-specifiers.
3252 if (AllowNestedNameSpecifiers) {
3253 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003254 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003255 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3256 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3257 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003258 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003259 }
3260 }
3261 Results.ExitScope();
3262
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003263 // If we're in a context where we might have an expression (rather than a
3264 // declaration), and what we've seen so far is an Objective-C type that could
3265 // be a receiver of a class message, this may be a class message send with
3266 // the initial opening bracket '[' missing. Add appropriate completions.
3267 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3268 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3269 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3270 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3271 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3272 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3273 DS.getTypeQualifiers() == 0 &&
3274 S &&
3275 (S->getFlags() & Scope::DeclScope) != 0 &&
3276 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3277 Scope::FunctionPrototypeScope |
3278 Scope::AtCatchScope)) == 0) {
3279 ParsedType T = DS.getRepAsType();
3280 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003281 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003282 }
3283
Douglas Gregor4497dd42010-08-24 04:59:56 +00003284 // Note that we intentionally suppress macro results here, since we do not
3285 // encourage using macros to produce the names of entities.
3286
Douglas Gregor52779fb2010-09-23 23:01:17 +00003287 HandleCodeCompleteResults(this, CodeCompleter,
3288 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003289 Results.data(), Results.size());
3290}
3291
Douglas Gregorfb629412010-08-23 21:17:50 +00003292struct Sema::CodeCompleteExpressionData {
3293 CodeCompleteExpressionData(QualType PreferredType = QualType())
3294 : PreferredType(PreferredType), IntegralConstantExpression(false),
3295 ObjCCollection(false) { }
3296
3297 QualType PreferredType;
3298 bool IntegralConstantExpression;
3299 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003300 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003301};
3302
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003303/// \brief Perform code-completion in an expression context when we know what
3304/// type we're looking for.
Douglas Gregorfb629412010-08-23 21:17:50 +00003305void Sema::CodeCompleteExpression(Scope *S,
3306 const CodeCompleteExpressionData &Data) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003307 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003308 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003309 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003310 if (Data.ObjCCollection)
3311 Results.setFilter(&ResultBuilder::IsObjCCollection);
3312 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003313 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikie4e4d0842012-03-11 07:00:24 +00003314 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003315 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3316 else
3317 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003318
3319 if (!Data.PreferredType.isNull())
3320 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3321
3322 // Ignore any declarations that we were told that we don't care about.
3323 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3324 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003325
3326 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003327 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3328 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003329
3330 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003331 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003332 Results.ExitScope();
3333
Douglas Gregor590c7d52010-07-08 20:55:51 +00003334 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003335 if (!Data.PreferredType.isNull())
3336 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3337 || Data.PreferredType->isMemberPointerType()
3338 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003339
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003340 if (S->getFnParent() &&
3341 !Data.ObjCCollection &&
3342 !Data.IntegralConstantExpression)
David Blaikie4e4d0842012-03-11 07:00:24 +00003343 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003344
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003345 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003346 AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003347 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003348 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3349 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003350 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003351}
3352
Douglas Gregorac5fd842010-09-18 01:28:11 +00003353void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3354 if (E.isInvalid())
3355 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikie4e4d0842012-03-11 07:00:24 +00003356 else if (getLangOpts().ObjC1)
Douglas Gregorac5fd842010-09-18 01:28:11 +00003357 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003358}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003359
Douglas Gregor73449212010-12-09 23:01:55 +00003360/// \brief The set of properties that have already been added, referenced by
3361/// property name.
3362typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3363
Douglas Gregorb92a4082012-06-12 13:44:08 +00003364/// \brief Retrieve the container definition, if any?
3365static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3366 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3367 if (Interface->hasDefinition())
3368 return Interface->getDefinition();
3369
3370 return Interface;
3371 }
3372
3373 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3374 if (Protocol->hasDefinition())
3375 return Protocol->getDefinition();
3376
3377 return Protocol;
3378 }
3379 return Container;
3380}
3381
3382static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003383 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003384 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003385 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003386 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003387 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003388 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003389
Douglas Gregorb92a4082012-06-12 13:44:08 +00003390 // Retrieve the definition.
3391 Container = getContainerDef(Container);
3392
Douglas Gregor95ac6552009-11-18 01:29:26 +00003393 // Add properties in this container.
3394 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3395 PEnd = Container->prop_end();
3396 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003397 ++P) {
3398 if (AddedProperties.insert(P->getIdentifier()))
David Blaikie581deb32012-06-06 20:45:41 +00003399 Results.MaybeAddResult(Result(*P, 0), CurContext);
Douglas Gregor73449212010-12-09 23:01:55 +00003400 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003401
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003402 // Add nullary methods
3403 if (AllowNullaryMethods) {
3404 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003405 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003406 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3407 MEnd = Container->meth_end();
3408 M != MEnd; ++M) {
3409 if (M->getSelector().isUnarySelector())
3410 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3411 if (AddedProperties.insert(Name)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003412 CodeCompletionBuilder Builder(Results.getAllocator(),
3413 Results.getCodeCompletionTUInfo());
David Blaikie581deb32012-06-06 20:45:41 +00003414 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003415 Builder.AddTypedTextChunk(
3416 Results.getAllocator().CopyString(Name->getName()));
3417
David Blaikie581deb32012-06-06 20:45:41 +00003418 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
Douglas Gregorba103062012-03-27 23:34:16 +00003419 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003420 CurContext);
3421 }
3422 }
3423 }
3424
3425
Douglas Gregor95ac6552009-11-18 01:29:26 +00003426 // Add properties in referenced protocols.
3427 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3428 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3429 PEnd = Protocol->protocol_end();
3430 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003431 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3432 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003433 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003434 if (AllowCategories) {
3435 // Look through categories.
3436 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3437 Category; Category = Category->getNextClassCategory())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003438 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3439 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003440 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003441
3442 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003443 for (ObjCInterfaceDecl::all_protocol_iterator
3444 I = IFace->all_referenced_protocol_begin(),
3445 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003446 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3447 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003448
3449 // Look in the superclass.
3450 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003451 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3452 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003453 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003454 } else if (const ObjCCategoryDecl *Category
3455 = dyn_cast<ObjCCategoryDecl>(Container)) {
3456 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003457 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3458 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003459 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003460 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3461 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003462 }
3463}
3464
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003465void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003466 SourceLocation OpLoc,
3467 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003468 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003469 return;
3470
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003471 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3472 if (ConvertedBase.isInvalid())
3473 return;
3474 Base = ConvertedBase.get();
3475
John McCall0a2c5e22010-08-25 06:19:51 +00003476 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003477
Douglas Gregor81b747b2009-09-17 21:32:03 +00003478 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003479
3480 if (IsArrow) {
3481 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3482 BaseType = Ptr->getPointeeType();
3483 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003484 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003485 else
3486 return;
3487 }
3488
Douglas Gregor3da626b2011-07-07 16:03:39 +00003489 enum CodeCompletionContext::Kind contextKind;
3490
3491 if (IsArrow) {
3492 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3493 }
3494 else {
3495 if (BaseType->isObjCObjectPointerType() ||
3496 BaseType->isObjCObjectOrInterfaceType()) {
3497 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3498 }
3499 else {
3500 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3501 }
3502 }
3503
Douglas Gregor218937c2011-02-01 19:23:04 +00003504 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003505 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003506 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003507 BaseType),
3508 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003509 Results.EnterNewScope();
3510 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003511 // Indicate that we are performing a member access, and the cv-qualifiers
3512 // for the base object type.
3513 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3514
Douglas Gregor95ac6552009-11-18 01:29:26 +00003515 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003516 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003517 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003518 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3519 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003520
David Blaikie4e4d0842012-03-11 07:00:24 +00003521 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003522 if (!Results.empty()) {
3523 // The "template" keyword can follow "->" or "." in the grammar.
3524 // However, we only want to suggest the template keyword if something
3525 // is dependent.
3526 bool IsDependent = BaseType->isDependentType();
3527 if (!IsDependent) {
3528 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3529 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3530 IsDependent = Ctx->isDependentContext();
3531 break;
3532 }
3533 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003534
Douglas Gregor95ac6552009-11-18 01:29:26 +00003535 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003536 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003537 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003538 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003539 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3540 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003541 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003542
3543 // Add property results based on our interface.
3544 const ObjCObjectPointerType *ObjCPtr
3545 = BaseType->getAsObjCInterfacePointerType();
3546 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003547 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3548 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003549 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003550
3551 // Add properties from the protocols in a qualified interface.
3552 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3553 E = ObjCPtr->qual_end();
3554 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003555 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3556 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003557 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003558 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003559 // Objective-C instance variable access.
3560 ObjCInterfaceDecl *Class = 0;
3561 if (const ObjCObjectPointerType *ObjCPtr
3562 = BaseType->getAs<ObjCObjectPointerType>())
3563 Class = ObjCPtr->getInterfaceDecl();
3564 else
John McCallc12c5bb2010-05-15 11:32:37 +00003565 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003566
3567 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003568 if (Class) {
3569 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3570 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003571 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3572 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003573 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003574 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003575
3576 // FIXME: How do we cope with isa?
3577
3578 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003579
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003580 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003581 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003582 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003583 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003584}
3585
Douglas Gregor374929f2009-09-18 15:37:17 +00003586void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3587 if (!CodeCompleter)
3588 return;
3589
Douglas Gregor86d9a522009-09-21 16:56:56 +00003590 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003591 enum CodeCompletionContext::Kind ContextKind
3592 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003593 switch ((DeclSpec::TST)TagSpec) {
3594 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003595 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003596 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003597 break;
3598
3599 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003600 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003601 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003602 break;
3603
3604 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003605 case DeclSpec::TST_class:
Joao Matos6666ed42012-08-31 18:45:21 +00003606 case DeclSpec::TST_interface:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003607 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003608 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003609 break;
3610
3611 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003612 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003613 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003614
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003615 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3616 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003617 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003618
3619 // First pass: look for tags.
3620 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003621 LookupVisibleDecls(S, LookupTagName, Consumer,
3622 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003623
Douglas Gregor8071e422010-08-15 06:18:01 +00003624 if (CodeCompleter->includeGlobals()) {
3625 // Second pass: look for nested name specifiers.
3626 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3627 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3628 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003629
Douglas Gregor52779fb2010-09-23 23:01:17 +00003630 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003631 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003632}
3633
Douglas Gregor1a480c42010-08-27 17:35:51 +00003634void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003635 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003636 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003637 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003638 Results.EnterNewScope();
3639 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3640 Results.AddResult("const");
3641 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3642 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003643 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003644 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3645 Results.AddResult("restrict");
3646 Results.ExitScope();
3647 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003648 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003649 Results.data(), Results.size());
3650}
3651
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003652void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003653 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003654 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003655
John McCall781472f2010-08-25 08:40:02 +00003656 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003657 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3658 if (!type->isEnumeralType()) {
3659 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003660 Data.IntegralConstantExpression = true;
3661 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003662 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003663 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003664
3665 // Code-complete the cases of a switch statement over an enumeration type
3666 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003667 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregorb92a4082012-06-12 13:44:08 +00003668 if (EnumDecl *Def = Enum->getDefinition())
3669 Enum = Def;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003670
3671 // Determine which enumerators we have already seen in the switch statement.
3672 // FIXME: Ideally, we would also be able to look *past* the code-completion
3673 // token, in case we are code-completing in the middle of the switch and not
3674 // at the end. However, we aren't able to do so at the moment.
3675 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003676 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003677 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3678 SC = SC->getNextSwitchCase()) {
3679 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3680 if (!Case)
3681 continue;
3682
3683 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3684 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3685 if (EnumConstantDecl *Enumerator
3686 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3687 // We look into the AST of the case statement to determine which
3688 // enumerator was named. Alternatively, we could compute the value of
3689 // the integral constant expression, then compare it against the
3690 // values of each enumerator. However, value-based approach would not
3691 // work as well with C++ templates where enumerators declared within a
3692 // template are type- and value-dependent.
3693 EnumeratorsSeen.insert(Enumerator);
3694
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003695 // If this is a qualified-id, keep track of the nested-name-specifier
3696 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003697 //
3698 // switch (TagD.getKind()) {
3699 // case TagDecl::TK_enum:
3700 // break;
3701 // case XXX
3702 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003703 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003704 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3705 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003706 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003707 }
3708 }
3709
David Blaikie4e4d0842012-03-11 07:00:24 +00003710 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003711 // If there are no prior enumerators in C++, check whether we have to
3712 // qualify the names of the enumerators that we suggest, because they
3713 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003714 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003715 }
3716
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003717 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003718 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003719 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003720 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003721 Results.EnterNewScope();
3722 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3723 EEnd = Enum->enumerator_end();
3724 E != EEnd; ++E) {
David Blaikie581deb32012-06-06 20:45:41 +00003725 if (EnumeratorsSeen.count(*E))
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003726 continue;
3727
David Blaikie581deb32012-06-06 20:45:41 +00003728 CodeCompletionResult R(*E, Qualifier);
Douglas Gregor5c722c702011-02-18 23:30:37 +00003729 R.Priority = CCP_EnumInCase;
3730 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003731 }
3732 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003733
Douglas Gregor3da626b2011-07-07 16:03:39 +00003734 //We need to make sure we're setting the right context,
3735 //so only say we include macros if the code completer says we do
3736 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3737 if (CodeCompleter->includeMacros()) {
Douglas Gregor3644d972012-10-09 16:01:50 +00003738 AddMacroResults(PP, Results, false);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003739 kind = CodeCompletionContext::CCC_OtherWithMacros;
3740 }
3741
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003742 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003743 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003744 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003745}
3746
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003747namespace {
3748 struct IsBetterOverloadCandidate {
3749 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003750 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003751
3752 public:
John McCall5769d612010-02-08 23:07:23 +00003753 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3754 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003755
3756 bool
3757 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003758 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003759 }
3760 };
3761}
3762
Ahmed Charles13a140c2012-02-25 11:00:22 +00003763static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3764 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003765 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003766
3767 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003768 if (!Args[I])
3769 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003770
Douglas Gregord28dcd72010-05-30 06:10:08 +00003771 return false;
3772}
3773
Richard Trieuf81e5a92011-09-09 02:00:50 +00003774void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charles13a140c2012-02-25 11:00:22 +00003775 llvm::ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003776 if (!CodeCompleter)
3777 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003778
3779 // When we're code-completing for a call, we fall back to ordinary
3780 // name code-completion whenever we can't produce specific
3781 // results. We may want to revisit this strategy in the future,
3782 // e.g., by merging the two kinds of results.
3783
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003784 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003785
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003786 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003787 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3788 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003789 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003790 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003791 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003792
John McCall3b4294e2009-12-16 12:17:52 +00003793 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003794 SourceLocation Loc = Fn->getExprLoc();
3795 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003796
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003797 // FIXME: What if we're calling something that isn't a function declaration?
3798 // FIXME: What if we're calling a pseudo-destructor?
3799 // FIXME: What if we're calling a member function?
3800
Douglas Gregorc0265402010-01-21 15:46:19 +00003801 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003802 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003803
John McCall3b4294e2009-12-16 12:17:52 +00003804 Expr *NakedFn = Fn->IgnoreParenCasts();
3805 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003806 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003807 /*PartialOverloading=*/ true);
3808 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3809 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003810 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003811 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003812 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003813 Results.push_back(ResultCandidate(FDecl));
3814 else
John McCall86820f52010-01-26 01:37:31 +00003815 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003816 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3817 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003818 }
John McCall3b4294e2009-12-16 12:17:52 +00003819 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003820
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003821 QualType ParamType;
3822
Douglas Gregorc0265402010-01-21 15:46:19 +00003823 if (!CandidateSet.empty()) {
3824 // Sort the overload candidate set by placing the best overloads first.
3825 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003826 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003827
Douglas Gregorc0265402010-01-21 15:46:19 +00003828 // Add the remaining viable overload candidates as code-completion reslults.
3829 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3830 CandEnd = CandidateSet.end();
3831 Cand != CandEnd; ++Cand) {
3832 if (Cand->Viable)
3833 Results.push_back(ResultCandidate(Cand->Function));
3834 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003835
3836 // From the viable candidates, try to determine the type of this parameter.
3837 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3838 if (const FunctionType *FType = Results[I].getFunctionType())
3839 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003840 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003841 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003842 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003843 else if (!Context.hasSameUnqualifiedType(
3844 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003845 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003846 ParamType = QualType();
3847 break;
3848 }
3849 }
3850 }
3851 } else {
3852 // Try to determine the parameter type from the type of the expression
3853 // being called.
3854 QualType FunctionType = Fn->getType();
3855 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3856 FunctionType = Ptr->getPointeeType();
3857 else if (const BlockPointerType *BlockPtr
3858 = FunctionType->getAs<BlockPointerType>())
3859 FunctionType = BlockPtr->getPointeeType();
3860 else if (const MemberPointerType *MemPtr
3861 = FunctionType->getAs<MemberPointerType>())
3862 FunctionType = MemPtr->getPointeeType();
3863
3864 if (const FunctionProtoType *Proto
3865 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003866 if (Args.size() < Proto->getNumArgs())
3867 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003868 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003869 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003870
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003871 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003872 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003873 else
3874 CodeCompleteExpression(S, ParamType);
3875
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003876 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003877 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003878 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003879}
3880
John McCalld226f652010-08-21 09:40:31 +00003881void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3882 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003883 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003884 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003885 return;
3886 }
3887
3888 CodeCompleteExpression(S, VD->getType());
3889}
3890
3891void Sema::CodeCompleteReturn(Scope *S) {
3892 QualType ResultType;
3893 if (isa<BlockDecl>(CurContext)) {
3894 if (BlockScopeInfo *BSI = getCurBlock())
3895 ResultType = BSI->ReturnType;
3896 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3897 ResultType = Function->getResultType();
3898 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3899 ResultType = Method->getResultType();
3900
3901 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003902 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003903 else
3904 CodeCompleteExpression(S, ResultType);
3905}
3906
Douglas Gregord2d8be62011-07-30 08:36:53 +00003907void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregord2d8be62011-07-30 08:36:53 +00003908 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003909 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord2d8be62011-07-30 08:36:53 +00003910 mapCodeCompletionContext(*this, PCC_Statement));
3911 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3912 Results.EnterNewScope();
3913
3914 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3915 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3916 CodeCompleter->includeGlobals());
3917
3918 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3919
3920 // "else" block
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003921 CodeCompletionBuilder Builder(Results.getAllocator(),
3922 Results.getCodeCompletionTUInfo());
Douglas Gregord2d8be62011-07-30 08:36:53 +00003923 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00003924 if (Results.includeCodePatterns()) {
3925 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3926 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3927 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3928 Builder.AddPlaceholderChunk("statements");
3929 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3930 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3931 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003932 Results.AddResult(Builder.TakeString());
3933
3934 // "else if" block
3935 Builder.AddTypedTextChunk("else");
3936 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3937 Builder.AddTextChunk("if");
3938 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3939 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00003940 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00003941 Builder.AddPlaceholderChunk("condition");
3942 else
3943 Builder.AddPlaceholderChunk("expression");
3944 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00003945 if (Results.includeCodePatterns()) {
3946 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3947 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3948 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3949 Builder.AddPlaceholderChunk("statements");
3950 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3951 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3952 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003953 Results.AddResult(Builder.TakeString());
3954
3955 Results.ExitScope();
3956
3957 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003958 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003959
3960 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003961 AddMacroResults(PP, Results, false);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003962
3963 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3964 Results.data(),Results.size());
3965}
3966
Richard Trieuf81e5a92011-09-09 02:00:50 +00003967void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003968 if (LHS)
3969 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3970 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003971 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003972}
3973
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003974void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003975 bool EnteringContext) {
3976 if (!SS.getScopeRep() || !CodeCompleter)
3977 return;
3978
Douglas Gregor86d9a522009-09-21 16:56:56 +00003979 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3980 if (!Ctx)
3981 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003982
3983 // Try to instantiate any non-dependent declaration contexts before
3984 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003985 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003986 return;
3987
Douglas Gregor218937c2011-02-01 19:23:04 +00003988 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003989 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003990 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003991 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003992
Douglas Gregor86d9a522009-09-21 16:56:56 +00003993 // The "template" keyword can follow "::" in the grammar, but only
3994 // put it into the grammar if the nested-name-specifier is dependent.
3995 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3996 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003997 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003998
3999 // Add calls to overridden virtual functions, if there are any.
4000 //
4001 // FIXME: This isn't wonderful, because we don't know whether we're actually
4002 // in a context that permits expressions. This is a general issue with
4003 // qualified-id completions.
4004 if (!EnteringContext)
4005 MaybeAddOverrideCalls(*this, Ctx, Results);
4006 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004007
Douglas Gregorf6961522010-08-27 21:18:54 +00004008 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4009 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
4010
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004011 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00004012 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004013 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00004014}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004015
4016void Sema::CodeCompleteUsing(Scope *S) {
4017 if (!CodeCompleter)
4018 return;
4019
Douglas Gregor218937c2011-02-01 19:23:04 +00004020 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004021 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004022 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4023 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004024 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004025
4026 // If we aren't in class scope, we could see the "namespace" keyword.
4027 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00004028 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004029
4030 // After "using", we can see anything that would start a
4031 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004032 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004033 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4034 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004035 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004036
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004037 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004038 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004039 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004040}
4041
4042void Sema::CodeCompleteUsingDirective(Scope *S) {
4043 if (!CodeCompleter)
4044 return;
4045
Douglas Gregor86d9a522009-09-21 16:56:56 +00004046 // After "using namespace", we expect to see a namespace name or namespace
4047 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004048 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004049 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004050 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004051 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004052 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004053 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004054 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4055 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004056 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004057 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004058 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004059 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004060}
4061
4062void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4063 if (!CodeCompleter)
4064 return;
4065
Douglas Gregor86d9a522009-09-21 16:56:56 +00004066 DeclContext *Ctx = (DeclContext *)S->getEntity();
4067 if (!S->getParent())
4068 Ctx = Context.getTranslationUnitDecl();
4069
Douglas Gregor52779fb2010-09-23 23:01:17 +00004070 bool SuppressedGlobalResults
4071 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4072
Douglas Gregor218937c2011-02-01 19:23:04 +00004073 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004074 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004075 SuppressedGlobalResults
4076 ? CodeCompletionContext::CCC_Namespace
4077 : CodeCompletionContext::CCC_Other,
4078 &ResultBuilder::IsNamespace);
4079
4080 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004081 // We only want to see those namespaces that have already been defined
4082 // within this scope, because its likely that the user is creating an
4083 // extended namespace declaration. Keep track of the most recent
4084 // definition of each namespace.
4085 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4086 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4087 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4088 NS != NSEnd; ++NS)
David Blaikie581deb32012-06-06 20:45:41 +00004089 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004090
4091 // Add the most recent definition (or extended definition) of each
4092 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004093 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004094 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregorba103062012-03-27 23:34:16 +00004095 NS = OrigToLatest.begin(),
4096 NSEnd = OrigToLatest.end();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004097 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004098 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004099 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004100 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004101 }
4102
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004103 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004104 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004105 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004106}
4107
4108void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4109 if (!CodeCompleter)
4110 return;
4111
Douglas Gregor86d9a522009-09-21 16:56:56 +00004112 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004113 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004114 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004115 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004116 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004117 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004118 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4119 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004120 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004121 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004122 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004123}
4124
Douglas Gregored8d3222009-09-18 20:05:18 +00004125void Sema::CodeCompleteOperatorName(Scope *S) {
4126 if (!CodeCompleter)
4127 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004128
John McCall0a2c5e22010-08-25 06:19:51 +00004129 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004130 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004131 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004132 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004133 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004134 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004135
Douglas Gregor86d9a522009-09-21 16:56:56 +00004136 // Add the names of overloadable operators.
4137#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4138 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004139 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004140#include "clang/Basic/OperatorKinds.def"
4141
4142 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004143 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004144 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004145 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4146 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004147
4148 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004149 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004150 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004151
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004152 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004153 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004154 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004155}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004156
Douglas Gregor0133f522010-08-28 00:00:50 +00004157void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004158 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004159 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004160 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004161 CXXConstructorDecl *Constructor
4162 = static_cast<CXXConstructorDecl *>(ConstructorD);
4163 if (!Constructor)
4164 return;
4165
Douglas Gregor218937c2011-02-01 19:23:04 +00004166 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004167 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004168 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004169 Results.EnterNewScope();
4170
4171 // Fill in any already-initialized fields or base classes.
4172 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4173 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4174 for (unsigned I = 0; I != NumInitializers; ++I) {
4175 if (Initializers[I]->isBaseInitializer())
4176 InitializedBases.insert(
4177 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4178 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004179 InitializedFields.insert(cast<FieldDecl>(
4180 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004181 }
4182
4183 // Add completions for base classes.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004184 CodeCompletionBuilder Builder(Results.getAllocator(),
4185 Results.getCodeCompletionTUInfo());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004186 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004187 CXXRecordDecl *ClassDecl = Constructor->getParent();
4188 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4189 BaseEnd = ClassDecl->bases_end();
4190 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004191 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4192 SawLastInitializer
4193 = NumInitializers > 0 &&
4194 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4195 Context.hasSameUnqualifiedType(Base->getType(),
4196 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004197 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004198 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004199
Douglas Gregor218937c2011-02-01 19:23:04 +00004200 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004201 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004202 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004203 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4204 Builder.AddPlaceholderChunk("args");
4205 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4206 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004207 SawLastInitializer? CCP_NextInitializer
4208 : CCP_MemberDeclaration));
4209 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004210 }
4211
4212 // Add completions for virtual base classes.
4213 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4214 BaseEnd = ClassDecl->vbases_end();
4215 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004216 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4217 SawLastInitializer
4218 = NumInitializers > 0 &&
4219 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4220 Context.hasSameUnqualifiedType(Base->getType(),
4221 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004222 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004223 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004224
Douglas Gregor218937c2011-02-01 19:23:04 +00004225 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004226 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004227 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004228 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4229 Builder.AddPlaceholderChunk("args");
4230 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4231 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004232 SawLastInitializer? CCP_NextInitializer
4233 : CCP_MemberDeclaration));
4234 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004235 }
4236
4237 // Add completions for members.
4238 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4239 FieldEnd = ClassDecl->field_end();
4240 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004241 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4242 SawLastInitializer
4243 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004244 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
David Blaikie581deb32012-06-06 20:45:41 +00004245 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004246 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004247 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004248
4249 if (!Field->getDeclName())
4250 continue;
4251
Douglas Gregordae68752011-02-01 22:57:45 +00004252 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004253 Field->getIdentifier()->getName()));
4254 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4255 Builder.AddPlaceholderChunk("args");
4256 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4257 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004258 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004259 : CCP_MemberDeclaration,
Douglas Gregorba103062012-03-27 23:34:16 +00004260 CXCursor_MemberRef,
4261 CXAvailability_Available,
David Blaikie581deb32012-06-06 20:45:41 +00004262 *Field));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004263 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004264 }
4265 Results.ExitScope();
4266
Douglas Gregor52779fb2010-09-23 23:01:17 +00004267 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004268 Results.data(), Results.size());
4269}
4270
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004271/// \brief Determine whether this scope denotes a namespace.
4272static bool isNamespaceScope(Scope *S) {
4273 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4274 if (!DC)
4275 return false;
4276
4277 return DC->isFileContext();
4278}
4279
4280void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4281 bool AfterAmpersand) {
4282 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004283 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004284 CodeCompletionContext::CCC_Other);
4285 Results.EnterNewScope();
4286
4287 // Note what has already been captured.
4288 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4289 bool IncludedThis = false;
4290 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4291 CEnd = Intro.Captures.end();
4292 C != CEnd; ++C) {
4293 if (C->Kind == LCK_This) {
4294 IncludedThis = true;
4295 continue;
4296 }
4297
4298 Known.insert(C->Id);
4299 }
4300
4301 // Look for other capturable variables.
4302 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4303 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4304 D != DEnd; ++D) {
4305 VarDecl *Var = dyn_cast<VarDecl>(*D);
4306 if (!Var ||
4307 !Var->hasLocalStorage() ||
4308 Var->hasAttr<BlocksAttr>())
4309 continue;
4310
4311 if (Known.insert(Var->getIdentifier()))
4312 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4313 }
4314 }
4315
4316 // Add 'this', if it would be valid.
4317 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4318 addThisCompletion(*this, Results);
4319
4320 Results.ExitScope();
4321
4322 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4323 Results.data(), Results.size());
4324}
4325
James Dennetta40f7922012-06-14 03:11:41 +00004326/// Macro that optionally prepends an "@" to the string literal passed in via
4327/// Keyword, depending on whether NeedAt is true or false.
4328#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4329
Douglas Gregorbca403c2010-01-13 23:51:12 +00004330static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004331 ResultBuilder &Results,
4332 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004333 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004334 // Since we have an implementation, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004335 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004336
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004337 CodeCompletionBuilder Builder(Results.getAllocator(),
4338 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004339 if (LangOpts.ObjC2) {
4340 // @dynamic
James Dennetta40f7922012-06-14 03:11:41 +00004341 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004342 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4343 Builder.AddPlaceholderChunk("property");
4344 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004345
4346 // @synthesize
James Dennetta40f7922012-06-14 03:11:41 +00004347 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004348 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4349 Builder.AddPlaceholderChunk("property");
4350 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004351 }
4352}
4353
Douglas Gregorbca403c2010-01-13 23:51:12 +00004354static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004355 ResultBuilder &Results,
4356 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004357 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004358
4359 // Since we have an interface or protocol, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004360 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004361
4362 if (LangOpts.ObjC2) {
4363 // @property
James Dennetta40f7922012-06-14 03:11:41 +00004364 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004365
4366 // @required
James Dennetta40f7922012-06-14 03:11:41 +00004367 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004368
4369 // @optional
James Dennetta40f7922012-06-14 03:11:41 +00004370 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004371 }
4372}
4373
Douglas Gregorbca403c2010-01-13 23:51:12 +00004374static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004375 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004376 CodeCompletionBuilder Builder(Results.getAllocator(),
4377 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004378
4379 // @class name ;
James Dennetta40f7922012-06-14 03:11:41 +00004380 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004381 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4382 Builder.AddPlaceholderChunk("name");
4383 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004384
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004385 if (Results.includeCodePatterns()) {
4386 // @interface name
4387 // FIXME: Could introduce the whole pattern, including superclasses and
4388 // such.
James Dennetta40f7922012-06-14 03:11:41 +00004389 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004390 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4391 Builder.AddPlaceholderChunk("class");
4392 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004393
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004394 // @protocol name
James Dennetta40f7922012-06-14 03:11:41 +00004395 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004396 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4397 Builder.AddPlaceholderChunk("protocol");
4398 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004399
4400 // @implementation name
James Dennetta40f7922012-06-14 03:11:41 +00004401 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004402 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4403 Builder.AddPlaceholderChunk("class");
4404 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004405 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004406
4407 // @compatibility_alias name
James Dennetta40f7922012-06-14 03:11:41 +00004408 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004409 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4410 Builder.AddPlaceholderChunk("alias");
4411 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4412 Builder.AddPlaceholderChunk("class");
4413 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004414}
4415
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004416void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004417 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004418 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004419 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004420 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004421 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004422 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004423 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004424 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004425 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004426 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004427 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004428 HandleCodeCompleteResults(this, CodeCompleter,
4429 CodeCompletionContext::CCC_Other,
4430 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004431}
4432
Douglas Gregorbca403c2010-01-13 23:51:12 +00004433static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004434 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004435 CodeCompletionBuilder Builder(Results.getAllocator(),
4436 Results.getCodeCompletionTUInfo());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004437
4438 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004439 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004440 if (Results.getSema().getLangOpts().CPlusPlus ||
4441 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004442 EncodeType = "const char[]";
Douglas Gregor8ca72082011-10-18 21:20:17 +00004443 Builder.AddResultTypeChunk(EncodeType);
James Dennetta40f7922012-06-14 03:11:41 +00004444 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004445 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4446 Builder.AddPlaceholderChunk("type-name");
4447 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4448 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004449
4450 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004451 Builder.AddResultTypeChunk("Protocol *");
James Dennetta40f7922012-06-14 03:11:41 +00004452 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004453 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4454 Builder.AddPlaceholderChunk("protocol-name");
4455 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4456 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004457
4458 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004459 Builder.AddResultTypeChunk("SEL");
James Dennetta40f7922012-06-14 03:11:41 +00004460 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004461 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4462 Builder.AddPlaceholderChunk("selector");
4463 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4464 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004465
4466 // @"string"
4467 Builder.AddResultTypeChunk("NSString *");
4468 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
4469 Builder.AddPlaceholderChunk("string");
4470 Builder.AddTextChunk("\"");
4471 Results.AddResult(Result(Builder.TakeString()));
4472
Douglas Gregor79615892012-07-17 23:24:47 +00004473 // @[objects, ...]
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004474 Builder.AddResultTypeChunk("NSArray *");
James Dennetta40f7922012-06-14 03:11:41 +00004475 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004476 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004477 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4478 Results.AddResult(Result(Builder.TakeString()));
4479
Douglas Gregor79615892012-07-17 23:24:47 +00004480 // @{key : object, ...}
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004481 Builder.AddResultTypeChunk("NSDictionary *");
James Dennetta40f7922012-06-14 03:11:41 +00004482 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004483 Builder.AddPlaceholderChunk("key");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004484 Builder.AddChunk(CodeCompletionString::CK_Colon);
4485 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4486 Builder.AddPlaceholderChunk("object, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004487 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4488 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004489
Douglas Gregor79615892012-07-17 23:24:47 +00004490 // @(expression)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004491 Builder.AddResultTypeChunk("id");
4492 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004493 Builder.AddPlaceholderChunk("expression");
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004494 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4495 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004496}
4497
Douglas Gregorbca403c2010-01-13 23:51:12 +00004498static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004499 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004500 CodeCompletionBuilder Builder(Results.getAllocator(),
4501 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004502
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004503 if (Results.includeCodePatterns()) {
4504 // @try { statements } @catch ( declaration ) { statements } @finally
4505 // { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004506 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004507 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4508 Builder.AddPlaceholderChunk("statements");
4509 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4510 Builder.AddTextChunk("@catch");
4511 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4512 Builder.AddPlaceholderChunk("parameter");
4513 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4514 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4515 Builder.AddPlaceholderChunk("statements");
4516 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4517 Builder.AddTextChunk("@finally");
4518 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4519 Builder.AddPlaceholderChunk("statements");
4520 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4521 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004522 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004523
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004524 // @throw
James Dennetta40f7922012-06-14 03:11:41 +00004525 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004526 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4527 Builder.AddPlaceholderChunk("expression");
4528 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004529
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004530 if (Results.includeCodePatterns()) {
4531 // @synchronized ( expression ) { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004532 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004533 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4534 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4535 Builder.AddPlaceholderChunk("expression");
4536 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4537 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4538 Builder.AddPlaceholderChunk("statements");
4539 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4540 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004541 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004542}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004543
Douglas Gregorbca403c2010-01-13 23:51:12 +00004544static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004545 ResultBuilder &Results,
4546 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004547 typedef CodeCompletionResult Result;
James Dennetta40f7922012-06-14 03:11:41 +00004548 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
4549 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
4550 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004551 if (LangOpts.ObjC2)
James Dennetta40f7922012-06-14 03:11:41 +00004552 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004553}
4554
4555void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004556 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004557 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004558 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004559 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004560 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004561 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004562 HandleCodeCompleteResults(this, CodeCompleter,
4563 CodeCompletionContext::CCC_Other,
4564 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004565}
4566
4567void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004568 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004569 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004570 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004571 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004572 AddObjCStatementResults(Results, false);
4573 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004574 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004575 HandleCodeCompleteResults(this, CodeCompleter,
4576 CodeCompletionContext::CCC_Other,
4577 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004578}
4579
4580void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004581 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004582 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004583 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004584 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004585 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004586 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004587 HandleCodeCompleteResults(this, CodeCompleter,
4588 CodeCompletionContext::CCC_Other,
4589 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004590}
4591
Douglas Gregor988358f2009-11-19 00:14:45 +00004592/// \brief Determine whether the addition of the given flag to an Objective-C
4593/// property's attributes will cause a conflict.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004594static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregor988358f2009-11-19 00:14:45 +00004595 // Check if we've already added this flag.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004596 if (Attributes & NewFlag)
Douglas Gregor988358f2009-11-19 00:14:45 +00004597 return true;
4598
Bill Wendlingad017fa2012-12-20 19:22:21 +00004599 Attributes |= NewFlag;
Douglas Gregor988358f2009-11-19 00:14:45 +00004600
4601 // Check for collisions with "readonly".
Bill Wendlingad017fa2012-12-20 19:22:21 +00004602 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4603 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregor988358f2009-11-19 00:14:45 +00004604 return true;
4605
Jordan Rosed7403a72012-08-20 20:01:13 +00004606 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004607 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004608 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004609 ObjCDeclSpec::DQ_PR_copy |
Jordan Rosed7403a72012-08-20 20:01:13 +00004610 ObjCDeclSpec::DQ_PR_retain |
4611 ObjCDeclSpec::DQ_PR_strong |
4612 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregor988358f2009-11-19 00:14:45 +00004613 if (AssignCopyRetMask &&
4614 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004615 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004616 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004617 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rosed7403a72012-08-20 20:01:13 +00004618 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
4619 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregor988358f2009-11-19 00:14:45 +00004620 return true;
4621
4622 return false;
4623}
4624
Douglas Gregora93b1082009-11-18 23:08:07 +00004625void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004626 if (!CodeCompleter)
4627 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004628
Bill Wendlingad017fa2012-12-20 19:22:21 +00004629 unsigned Attributes = ODS.getPropertyAttributes();
Steve Naroffece8e712009-10-08 21:55:05 +00004630
Douglas Gregor218937c2011-02-01 19:23:04 +00004631 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004632 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004633 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004634 Results.EnterNewScope();
Bill Wendlingad017fa2012-12-20 19:22:21 +00004635 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004636 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004637 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004638 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004639 if (!ObjCPropertyFlagConflicts(Attributes,
John McCallf85e1932011-06-15 23:02:42 +00004640 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4641 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004642 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004643 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004644 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004645 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004646 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCallf85e1932011-06-15 23:02:42 +00004647 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004648 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004649 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004650 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004651 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004652 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004653 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rosed7403a72012-08-20 20:01:13 +00004654
4655 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall0a7dd782012-08-21 02:47:43 +00004656 if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendlingad017fa2012-12-20 19:22:21 +00004657 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rosed7403a72012-08-20 20:01:13 +00004658 Results.AddResult(CodeCompletionResult("weak"));
4659
Bill Wendlingad017fa2012-12-20 19:22:21 +00004660 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004661 CodeCompletionBuilder Setter(Results.getAllocator(),
4662 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004663 Setter.AddTypedTextChunk("setter");
4664 Setter.AddTextChunk(" = ");
4665 Setter.AddPlaceholderChunk("method");
4666 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004667 }
Bill Wendlingad017fa2012-12-20 19:22:21 +00004668 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004669 CodeCompletionBuilder Getter(Results.getAllocator(),
4670 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004671 Getter.AddTypedTextChunk("getter");
4672 Getter.AddTextChunk(" = ");
4673 Getter.AddPlaceholderChunk("method");
4674 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004675 }
Steve Naroffece8e712009-10-08 21:55:05 +00004676 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004677 HandleCodeCompleteResults(this, CodeCompleter,
4678 CodeCompletionContext::CCC_Other,
4679 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004680}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004681
James Dennettde23c7e2012-06-17 05:33:25 +00004682/// \brief Describes the kind of Objective-C method that we want to find
Douglas Gregor4ad96852009-11-19 07:41:15 +00004683/// via code completion.
4684enum ObjCMethodKind {
Dmitri Gribenko49fdccb2012-06-08 23:13:42 +00004685 MK_Any, ///< Any kind of method, provided it means other specified criteria.
4686 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
4687 MK_OneArgSelector ///< One-argument selector.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004688};
4689
Douglas Gregor458433d2010-08-26 15:07:07 +00004690static bool isAcceptableObjCSelector(Selector Sel,
4691 ObjCMethodKind WantKind,
4692 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004693 unsigned NumSelIdents,
4694 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004695 if (NumSelIdents > Sel.getNumArgs())
4696 return false;
4697
4698 switch (WantKind) {
4699 case MK_Any: break;
4700 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4701 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4702 }
4703
Douglas Gregorcf544262010-11-17 21:36:08 +00004704 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4705 return false;
4706
Douglas Gregor458433d2010-08-26 15:07:07 +00004707 for (unsigned I = 0; I != NumSelIdents; ++I)
4708 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4709 return false;
4710
4711 return true;
4712}
4713
Douglas Gregor4ad96852009-11-19 07:41:15 +00004714static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4715 ObjCMethodKind WantKind,
4716 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004717 unsigned NumSelIdents,
4718 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004719 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004720 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004721}
Douglas Gregord36adf52010-09-16 16:06:31 +00004722
4723namespace {
4724 /// \brief A set of selectors, which is used to avoid introducing multiple
4725 /// completions with the same selector into the result set.
4726 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4727}
4728
Douglas Gregor36ecb042009-11-17 23:22:23 +00004729/// \brief Add all of the Objective-C methods in the given Objective-C
4730/// container to the set of results.
4731///
4732/// The container will be a class, protocol, category, or implementation of
4733/// any of the above. This mether will recurse to include methods from
4734/// the superclasses of classes along with their categories, protocols, and
4735/// implementations.
4736///
4737/// \param Container the container in which we'll look to find methods.
4738///
James Dennetta40f7922012-06-14 03:11:41 +00004739/// \param WantInstanceMethods Whether to add instance methods (only); if
4740/// false, this routine will add factory methods (only).
Douglas Gregor36ecb042009-11-17 23:22:23 +00004741///
4742/// \param CurContext the context in which we're performing the lookup that
4743/// finds methods.
4744///
Douglas Gregorcf544262010-11-17 21:36:08 +00004745/// \param AllowSameLength Whether we allow a method to be added to the list
4746/// when it has the same number of parameters as we have selector identifiers.
4747///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004748/// \param Results the structure into which we'll add results.
4749static void AddObjCMethods(ObjCContainerDecl *Container,
4750 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004751 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004752 IdentifierInfo **SelIdents,
4753 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004754 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004755 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004756 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004757 ResultBuilder &Results,
4758 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004759 typedef CodeCompletionResult Result;
Douglas Gregorb92a4082012-06-12 13:44:08 +00004760 Container = getContainerDef(Container);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004761 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4762 MEnd = Container->meth_end();
4763 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00004764 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004765 // Check whether the selector identifiers we've been given are a
4766 // subset of the identifiers for this particular method.
David Blaikie581deb32012-06-06 20:45:41 +00004767 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004768 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004769 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004770
David Blaikie262bc182012-04-30 02:36:29 +00004771 if (!Selectors.insert(M->getSelector()))
Douglas Gregord36adf52010-09-16 16:06:31 +00004772 continue;
4773
David Blaikie581deb32012-06-06 20:45:41 +00004774 Result R = Result(*M, 0);
Douglas Gregord3c68542009-11-19 01:08:35 +00004775 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004776 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004777 if (!InOriginalClass)
4778 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004779 Results.MaybeAddResult(R, CurContext);
4780 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004781 }
4782
Douglas Gregore396c7b2010-09-16 15:34:59 +00004783 // Visit the protocols of protocols.
4784 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004785 if (Protocol->hasDefinition()) {
4786 const ObjCList<ObjCProtocolDecl> &Protocols
4787 = Protocol->getReferencedProtocols();
4788 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4789 E = Protocols.end();
4790 I != E; ++I)
4791 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4792 NumSelIdents, CurContext, Selectors, AllowSameLength,
4793 Results, false);
4794 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004795 }
4796
Douglas Gregor36ecb042009-11-17 23:22:23 +00004797 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004798 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004799 return;
4800
4801 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004802 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4803 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004804 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004805 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004806 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004807
4808 // Add methods in categories.
4809 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4810 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004811 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004812 NumSelIdents, CurContext, Selectors, AllowSameLength,
4813 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004814
4815 // Add a categories protocol methods.
4816 const ObjCList<ObjCProtocolDecl> &Protocols
4817 = CatDecl->getReferencedProtocols();
4818 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4819 E = Protocols.end();
4820 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004821 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004822 NumSelIdents, CurContext, Selectors, AllowSameLength,
4823 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004824
4825 // Add methods in category implementations.
4826 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004827 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004828 NumSelIdents, CurContext, Selectors, AllowSameLength,
4829 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004830 }
4831
4832 // Add methods in superclass.
4833 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004834 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004835 SelIdents, NumSelIdents, CurContext, Selectors,
4836 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004837
4838 // Add methods in our implementation, if any.
4839 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004840 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004841 NumSelIdents, CurContext, Selectors, AllowSameLength,
4842 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004843}
4844
4845
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004846void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004847 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004848 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004849 if (!Class) {
4850 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004851 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004852 Class = Category->getClassInterface();
4853
4854 if (!Class)
4855 return;
4856 }
4857
4858 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004859 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004860 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004861 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004862 Results.EnterNewScope();
4863
Douglas Gregord36adf52010-09-16 16:06:31 +00004864 VisitedSelectorSet Selectors;
4865 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004866 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004867 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004868 HandleCodeCompleteResults(this, CodeCompleter,
4869 CodeCompletionContext::CCC_Other,
4870 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004871}
4872
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004873void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004874 // Try to find the interface where setters might live.
4875 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004876 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004877 if (!Class) {
4878 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004879 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004880 Class = Category->getClassInterface();
4881
4882 if (!Class)
4883 return;
4884 }
4885
4886 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004887 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004888 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004889 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004890 Results.EnterNewScope();
4891
Douglas Gregord36adf52010-09-16 16:06:31 +00004892 VisitedSelectorSet Selectors;
4893 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004894 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004895
4896 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004897 HandleCodeCompleteResults(this, CodeCompleter,
4898 CodeCompletionContext::CCC_Other,
4899 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004900}
4901
Douglas Gregorafc45782011-02-15 22:19:42 +00004902void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4903 bool IsParameter) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004904 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004905 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004906 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004907 Results.EnterNewScope();
4908
4909 // Add context-sensitive, Objective-C parameter-passing keywords.
4910 bool AddedInOut = false;
4911 if ((DS.getObjCDeclQualifier() &
4912 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4913 Results.AddResult("in");
4914 Results.AddResult("inout");
4915 AddedInOut = true;
4916 }
4917 if ((DS.getObjCDeclQualifier() &
4918 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4919 Results.AddResult("out");
4920 if (!AddedInOut)
4921 Results.AddResult("inout");
4922 }
4923 if ((DS.getObjCDeclQualifier() &
4924 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4925 ObjCDeclSpec::DQ_Oneway)) == 0) {
4926 Results.AddResult("bycopy");
4927 Results.AddResult("byref");
4928 Results.AddResult("oneway");
4929 }
4930
Douglas Gregorafc45782011-02-15 22:19:42 +00004931 // If we're completing the return type of an Objective-C method and the
4932 // identifier IBAction refers to a macro, provide a completion item for
4933 // an action, e.g.,
4934 // IBAction)<#selector#>:(id)sender
4935 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4936 Context.Idents.get("IBAction").hasMacroDefinition()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004937 CodeCompletionBuilder Builder(Results.getAllocator(),
4938 Results.getCodeCompletionTUInfo(),
4939 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorafc45782011-02-15 22:19:42 +00004940 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004941 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004942 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004943 Builder.AddChunk(CodeCompletionString::CK_Colon);
4944 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004945 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004946 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004947 Builder.AddTextChunk("sender");
4948 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4949 }
4950
Douglas Gregord32b0222010-08-24 01:06:58 +00004951 // Add various builtin type names and specifiers.
4952 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4953 Results.ExitScope();
4954
4955 // Add the various type names
4956 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4957 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4958 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4959 CodeCompleter->includeGlobals());
4960
4961 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00004962 AddMacroResults(PP, Results, false);
Douglas Gregord32b0222010-08-24 01:06:58 +00004963
4964 HandleCodeCompleteResults(this, CodeCompleter,
4965 CodeCompletionContext::CCC_Type,
4966 Results.data(), Results.size());
4967}
4968
Douglas Gregor22f56992010-04-06 19:22:33 +00004969/// \brief When we have an expression with type "id", we may assume
4970/// that it has some more-specific class type based on knowledge of
4971/// common uses of Objective-C. This routine returns that class type,
4972/// or NULL if no better result could be determined.
4973static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004974 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004975 if (!Msg)
4976 return 0;
4977
4978 Selector Sel = Msg->getSelector();
4979 if (Sel.isNull())
4980 return 0;
4981
4982 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4983 if (!Id)
4984 return 0;
4985
4986 ObjCMethodDecl *Method = Msg->getMethodDecl();
4987 if (!Method)
4988 return 0;
4989
4990 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004991 ObjCInterfaceDecl *IFace = 0;
4992 switch (Msg->getReceiverKind()) {
4993 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004994 if (const ObjCObjectType *ObjType
4995 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4996 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004997 break;
4998
4999 case ObjCMessageExpr::Instance: {
5000 QualType T = Msg->getInstanceReceiver()->getType();
5001 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5002 IFace = Ptr->getInterfaceDecl();
5003 break;
5004 }
5005
5006 case ObjCMessageExpr::SuperInstance:
5007 case ObjCMessageExpr::SuperClass:
5008 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00005009 }
5010
5011 if (!IFace)
5012 return 0;
5013
5014 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5015 if (Method->isInstanceMethod())
5016 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5017 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00005018 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00005019 .Case("autorelease", IFace)
5020 .Case("copy", IFace)
5021 .Case("copyWithZone", IFace)
5022 .Case("mutableCopy", IFace)
5023 .Case("mutableCopyWithZone", IFace)
5024 .Case("awakeFromCoder", IFace)
5025 .Case("replacementObjectFromCoder", IFace)
5026 .Case("class", IFace)
5027 .Case("classForCoder", IFace)
5028 .Case("superclass", Super)
5029 .Default(0);
5030
5031 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5032 .Case("new", IFace)
5033 .Case("alloc", IFace)
5034 .Case("allocWithZone", IFace)
5035 .Case("class", IFace)
5036 .Case("superclass", Super)
5037 .Default(0);
5038}
5039
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005040// Add a special completion for a message send to "super", which fills in the
5041// most likely case of forwarding all of our arguments to the superclass
5042// function.
5043///
5044/// \param S The semantic analysis object.
5045///
Dmitri Gribenko70517ca2012-08-23 17:58:28 +00005046/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005047/// the "super" keyword. Otherwise, we just need to provide the arguments.
5048///
5049/// \param SelIdents The identifiers in the selector that have already been
5050/// provided as arguments for a send to "super".
5051///
5052/// \param NumSelIdents The number of identifiers in \p SelIdents.
5053///
5054/// \param Results The set of results to augment.
5055///
5056/// \returns the Objective-C method declaration that would be invoked by
5057/// this "super" completion. If NULL, no completion was added.
5058static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
5059 IdentifierInfo **SelIdents,
5060 unsigned NumSelIdents,
5061 ResultBuilder &Results) {
5062 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5063 if (!CurMethod)
5064 return 0;
5065
5066 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5067 if (!Class)
5068 return 0;
5069
5070 // Try to find a superclass method with the same selector.
5071 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00005072 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5073 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005074 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5075 CurMethod->isInstanceMethod());
5076
Douglas Gregor78bcd912011-02-16 00:51:18 +00005077 // Check in categories or class extensions.
5078 if (!SuperMethod) {
5079 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5080 Category = Category->getNextClassCategory())
5081 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
5082 CurMethod->isInstanceMethod())))
5083 break;
5084 }
5085 }
5086
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005087 if (!SuperMethod)
5088 return 0;
5089
5090 // Check whether the superclass method has the same signature.
5091 if (CurMethod->param_size() != SuperMethod->param_size() ||
5092 CurMethod->isVariadic() != SuperMethod->isVariadic())
5093 return 0;
5094
5095 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5096 CurPEnd = CurMethod->param_end(),
5097 SuperP = SuperMethod->param_begin();
5098 CurP != CurPEnd; ++CurP, ++SuperP) {
5099 // Make sure the parameter types are compatible.
5100 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5101 (*SuperP)->getType()))
5102 return 0;
5103
5104 // Make sure we have a parameter name to forward!
5105 if (!(*CurP)->getIdentifier())
5106 return 0;
5107 }
5108
5109 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005110 CodeCompletionBuilder Builder(Results.getAllocator(),
5111 Results.getCodeCompletionTUInfo());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005112
5113 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005114 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5115 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005116
5117 // If we need the "super" keyword, add it (plus some spacing).
5118 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005119 Builder.AddTypedTextChunk("super");
5120 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005121 }
5122
5123 Selector Sel = CurMethod->getSelector();
5124 if (Sel.isUnarySelector()) {
5125 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005126 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005127 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005128 else
Douglas Gregordae68752011-02-01 22:57:45 +00005129 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005130 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005131 } else {
5132 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5133 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5134 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005135 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005136
5137 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005138 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005139 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005140 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005141 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005142 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005143 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005144 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005145 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005146 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005147 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005148 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005149 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005150 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005151 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005152 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005153 }
5154 }
5155 }
5156
Douglas Gregorba103062012-03-27 23:34:16 +00005157 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5158 CCP_SuperCompletion));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005159 return SuperMethod;
5160}
5161
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005162void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005163 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005164 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005165 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005166 CodeCompletionContext::CCC_ObjCMessageReceiver,
David Blaikie4e4d0842012-03-11 07:00:24 +00005167 getLangOpts().CPlusPlus0x
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005168 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5169 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005170
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005171 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5172 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005173 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5174 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005175
5176 // If we are in an Objective-C method inside a class that has a superclass,
5177 // add "super" as an option.
5178 if (ObjCMethodDecl *Method = getCurMethodDecl())
5179 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005180 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005181 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005182
5183 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5184 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005185
David Blaikie4e4d0842012-03-11 07:00:24 +00005186 if (getLangOpts().CPlusPlus0x)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005187 addThisCompletion(*this, Results);
5188
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005189 Results.ExitScope();
5190
5191 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00005192 AddMacroResults(PP, Results, false);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005193 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005194 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005195
5196}
5197
Douglas Gregor2725ca82010-04-21 19:57:20 +00005198void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5199 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005200 unsigned NumSelIdents,
5201 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005202 ObjCInterfaceDecl *CDecl = 0;
5203 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5204 // Figure out which interface we're in.
5205 CDecl = CurMethod->getClassInterface();
5206 if (!CDecl)
5207 return;
5208
5209 // Find the superclass of this class.
5210 CDecl = CDecl->getSuperClass();
5211 if (!CDecl)
5212 return;
5213
5214 if (CurMethod->isInstanceMethod()) {
5215 // We are inside an instance method, which means that the message
5216 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005217 // current object.
5218 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005219 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005220 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005221 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005222 }
5223
5224 // Fall through to send to the superclass in CDecl.
5225 } else {
5226 // "super" may be the name of a type or variable. Figure out which
5227 // it is.
5228 IdentifierInfo *Super = &Context.Idents.get("super");
5229 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5230 LookupOrdinaryName);
5231 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5232 // "super" names an interface. Use it.
5233 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005234 if (const ObjCObjectType *Iface
5235 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5236 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005237 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5238 // "super" names an unresolved type; we can't be more specific.
5239 } else {
5240 // Assume that "super" names some kind of value and parse that way.
5241 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005242 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005243 UnqualifiedId id;
5244 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005245 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5246 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005247 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005248 SelIdents, NumSelIdents,
5249 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005250 }
5251
5252 // Fall through
5253 }
5254
John McCallb3d87482010-08-24 05:47:05 +00005255 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005256 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005257 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005258 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005259 NumSelIdents, AtArgumentExpression,
5260 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005261}
5262
Douglas Gregorb9d77572010-09-21 00:03:25 +00005263/// \brief Given a set of code-completion results for the argument of a message
5264/// send, determine the preferred type (if any) for that argument expression.
5265static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5266 unsigned NumSelIdents) {
5267 typedef CodeCompletionResult Result;
5268 ASTContext &Context = Results.getSema().Context;
5269
5270 QualType PreferredType;
5271 unsigned BestPriority = CCP_Unlikely * 2;
5272 Result *ResultsData = Results.data();
5273 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5274 Result &R = ResultsData[I];
5275 if (R.Kind == Result::RK_Declaration &&
5276 isa<ObjCMethodDecl>(R.Declaration)) {
5277 if (R.Priority <= BestPriority) {
5278 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5279 if (NumSelIdents <= Method->param_size()) {
5280 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5281 ->getType();
5282 if (R.Priority < BestPriority || PreferredType.isNull()) {
5283 BestPriority = R.Priority;
5284 PreferredType = MyPreferredType;
5285 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5286 MyPreferredType)) {
5287 PreferredType = QualType();
5288 }
5289 }
5290 }
5291 }
5292 }
5293
5294 return PreferredType;
5295}
5296
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005297static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5298 ParsedType Receiver,
5299 IdentifierInfo **SelIdents,
5300 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005301 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005302 bool IsSuper,
5303 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005304 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005305 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005306
Douglas Gregor24a069f2009-11-17 17:59:40 +00005307 // If the given name refers to an interface type, retrieve the
5308 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005309 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005310 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005311 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005312 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5313 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005314 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005315
Douglas Gregor36ecb042009-11-17 23:22:23 +00005316 // Add all of the factory methods in this Objective-C class, its protocols,
5317 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005318 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005319
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005320 // If this is a send-to-super, try to add the special "super" send
5321 // completion.
5322 if (IsSuper) {
5323 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005324 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5325 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005326 Results.Ignore(SuperMethod);
5327 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005328
Douglas Gregor265f7492010-08-27 15:29:55 +00005329 // If we're inside an Objective-C method definition, prefer its selector to
5330 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005331 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005332 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005333
Douglas Gregord36adf52010-09-16 16:06:31 +00005334 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005335 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005336 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005337 SemaRef.CurContext, Selectors, AtArgumentExpression,
5338 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005339 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005340 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005341
Douglas Gregor719770d2010-04-06 17:30:22 +00005342 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005343 // pool from the AST file.
Axel Naumann0ec56b72012-10-18 19:05:02 +00005344 if (SemaRef.getExternalSource()) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005345 for (uint32_t I = 0,
Axel Naumann0ec56b72012-10-18 19:05:02 +00005346 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005347 I != N; ++I) {
Axel Naumann0ec56b72012-10-18 19:05:02 +00005348 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005349 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005350 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005351
5352 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005353 }
5354 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005355
5356 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5357 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005358 M != MEnd; ++M) {
5359 for (ObjCMethodList *MethList = &M->second.second;
5360 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005361 MethList = MethList->Next) {
5362 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5363 NumSelIdents))
5364 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005365
Douglas Gregor13438f92010-04-06 16:40:00 +00005366 Result R(MethList->Method, 0);
5367 R.StartParameter = NumSelIdents;
5368 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005369 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005370 }
5371 }
5372 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005373
5374 Results.ExitScope();
5375}
Douglas Gregor13438f92010-04-06 16:40:00 +00005376
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005377void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5378 IdentifierInfo **SelIdents,
5379 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005380 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005381 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005382
5383 QualType T = this->GetTypeFromParser(Receiver);
5384
Douglas Gregor218937c2011-02-01 19:23:04 +00005385 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005386 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005387 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005388 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005389
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005390 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5391 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005392
5393 // If we're actually at the argument expression (rather than prior to the
5394 // selector), we're actually performing code completion for an expression.
5395 // Determine whether we have a single, best method. If so, we can
5396 // code-complete the expression using the corresponding parameter type as
5397 // our preferred type, improving completion results.
5398 if (AtArgumentExpression) {
5399 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005400 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005401 if (PreferredType.isNull())
5402 CodeCompleteOrdinaryName(S, PCC_Expression);
5403 else
5404 CodeCompleteExpression(S, PreferredType);
5405 return;
5406 }
5407
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005408 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005409 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005410 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005411}
5412
Richard Trieuf81e5a92011-09-09 02:00:50 +00005413void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005414 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005415 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005416 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005417 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005418 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005419
5420 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005421
Douglas Gregor36ecb042009-11-17 23:22:23 +00005422 // If necessary, apply function/array conversion to the receiver.
5423 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005424 if (RecExpr) {
5425 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5426 if (Conv.isInvalid()) // conversion failed. bail.
5427 return;
5428 RecExpr = Conv.take();
5429 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005430 QualType ReceiverType = RecExpr? RecExpr->getType()
5431 : Super? Context.getObjCObjectPointerType(
5432 Context.getObjCInterfaceType(Super))
5433 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005434
Douglas Gregorda892642010-11-08 21:12:30 +00005435 // If we're messaging an expression with type "id" or "Class", check
5436 // whether we know something special about the receiver that allows
5437 // us to assume a more-specific receiver type.
5438 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5439 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5440 if (ReceiverType->isObjCClassType())
5441 return CodeCompleteObjCClassMessage(S,
5442 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5443 SelIdents, NumSelIdents,
5444 AtArgumentExpression, Super);
5445
5446 ReceiverType = Context.getObjCObjectPointerType(
5447 Context.getObjCInterfaceType(IFace));
5448 }
5449
Douglas Gregor36ecb042009-11-17 23:22:23 +00005450 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005451 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005452 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005453 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005454 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005455
Douglas Gregor36ecb042009-11-17 23:22:23 +00005456 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005457
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005458 // If this is a send-to-super, try to add the special "super" send
5459 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005460 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005461 if (ObjCMethodDecl *SuperMethod
5462 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5463 Results))
5464 Results.Ignore(SuperMethod);
5465 }
5466
Douglas Gregor265f7492010-08-27 15:29:55 +00005467 // If we're inside an Objective-C method definition, prefer its selector to
5468 // others.
5469 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5470 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005471
Douglas Gregord36adf52010-09-16 16:06:31 +00005472 // Keep track of the selectors we've already added.
5473 VisitedSelectorSet Selectors;
5474
Douglas Gregorf74a4192009-11-18 00:06:18 +00005475 // Handle messages to Class. This really isn't a message to an instance
5476 // method, so we treat it the same way we would treat a message send to a
5477 // class method.
5478 if (ReceiverType->isObjCClassType() ||
5479 ReceiverType->isObjCQualifiedClassType()) {
5480 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5481 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005482 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005483 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005484 }
5485 }
5486 // Handle messages to a qualified ID ("id<foo>").
5487 else if (const ObjCObjectPointerType *QualID
5488 = ReceiverType->getAsObjCQualifiedIdType()) {
5489 // Search protocols for instance methods.
5490 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5491 E = QualID->qual_end();
5492 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005493 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005494 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005495 }
5496 // Handle messages to a pointer to interface type.
5497 else if (const ObjCObjectPointerType *IFacePtr
5498 = ReceiverType->getAsObjCInterfacePointerType()) {
5499 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005500 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005501 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5502 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005503
5504 // Search protocols for instance methods.
5505 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5506 E = IFacePtr->qual_end();
5507 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005508 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005509 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005510 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005511 // Handle messages to "id".
5512 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005513 // We're messaging "id", so provide all instance methods we know
5514 // about as code-completion results.
5515
5516 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005517 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005518 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005519 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5520 I != N; ++I) {
5521 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005522 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005523 continue;
5524
Sebastian Redldb9d2142010-08-02 23:18:59 +00005525 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005526 }
5527 }
5528
Sebastian Redldb9d2142010-08-02 23:18:59 +00005529 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5530 MEnd = MethodPool.end();
5531 M != MEnd; ++M) {
5532 for (ObjCMethodList *MethList = &M->second.first;
5533 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005534 MethList = MethList->Next) {
5535 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5536 NumSelIdents))
5537 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005538
5539 if (!Selectors.insert(MethList->Method->getSelector()))
5540 continue;
5541
Douglas Gregor13438f92010-04-06 16:40:00 +00005542 Result R(MethList->Method, 0);
5543 R.StartParameter = NumSelIdents;
5544 R.AllParametersAreInformative = false;
5545 Results.MaybeAddResult(R, CurContext);
5546 }
5547 }
5548 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005549 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005550
5551
5552 // If we're actually at the argument expression (rather than prior to the
5553 // selector), we're actually performing code completion for an expression.
5554 // Determine whether we have a single, best method. If so, we can
5555 // code-complete the expression using the corresponding parameter type as
5556 // our preferred type, improving completion results.
5557 if (AtArgumentExpression) {
5558 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5559 NumSelIdents);
5560 if (PreferredType.isNull())
5561 CodeCompleteOrdinaryName(S, PCC_Expression);
5562 else
5563 CodeCompleteExpression(S, PreferredType);
5564 return;
5565 }
5566
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005567 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005568 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005569 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005570}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005571
Douglas Gregorfb629412010-08-23 21:17:50 +00005572void Sema::CodeCompleteObjCForCollection(Scope *S,
5573 DeclGroupPtrTy IterationVar) {
5574 CodeCompleteExpressionData Data;
5575 Data.ObjCCollection = true;
5576
5577 if (IterationVar.getAsOpaquePtr()) {
5578 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5579 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5580 if (*I)
5581 Data.IgnoreDecls.push_back(*I);
5582 }
5583 }
5584
5585 CodeCompleteExpression(S, Data);
5586}
5587
Douglas Gregor458433d2010-08-26 15:07:07 +00005588void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5589 unsigned NumSelIdents) {
5590 // If we have an external source, load the entire class method
5591 // pool from the AST file.
5592 if (ExternalSource) {
5593 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5594 I != N; ++I) {
5595 Selector Sel = ExternalSource->GetExternalSelector(I);
5596 if (Sel.isNull() || MethodPool.count(Sel))
5597 continue;
5598
5599 ReadMethodPool(Sel);
5600 }
5601 }
5602
Douglas Gregor218937c2011-02-01 19:23:04 +00005603 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005604 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005605 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005606 Results.EnterNewScope();
5607 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5608 MEnd = MethodPool.end();
5609 M != MEnd; ++M) {
5610
5611 Selector Sel = M->first;
5612 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5613 continue;
5614
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005615 CodeCompletionBuilder Builder(Results.getAllocator(),
5616 Results.getCodeCompletionTUInfo());
Douglas Gregor458433d2010-08-26 15:07:07 +00005617 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005618 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005619 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005620 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005621 continue;
5622 }
5623
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005624 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005625 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005626 if (I == NumSelIdents) {
5627 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005628 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005629 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005630 Accumulator.clear();
5631 }
5632 }
5633
Benjamin Kramera0651c52011-07-26 16:59:25 +00005634 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005635 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005636 }
Douglas Gregordae68752011-02-01 22:57:45 +00005637 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005638 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005639 }
5640 Results.ExitScope();
5641
5642 HandleCodeCompleteResults(this, CodeCompleter,
5643 CodeCompletionContext::CCC_SelectorName,
5644 Results.data(), Results.size());
5645}
5646
Douglas Gregor55385fe2009-11-18 04:19:12 +00005647/// \brief Add all of the protocol declarations that we find in the given
5648/// (translation unit) context.
5649static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005650 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005651 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005652 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005653
5654 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5655 DEnd = Ctx->decls_end();
5656 D != DEnd; ++D) {
5657 // Record any protocols we find.
5658 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005659 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005660 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005661 }
5662}
5663
5664void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5665 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005666 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005667 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005668 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005669
Douglas Gregor70c23352010-12-09 21:44:02 +00005670 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5671 Results.EnterNewScope();
5672
5673 // Tell the result set to ignore all of the protocols we have
5674 // already seen.
5675 // FIXME: This doesn't work when caching code-completion results.
5676 for (unsigned I = 0; I != NumProtocols; ++I)
5677 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5678 Protocols[I].second))
5679 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005680
Douglas Gregor70c23352010-12-09 21:44:02 +00005681 // Add all protocols.
5682 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5683 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005684
Douglas Gregor70c23352010-12-09 21:44:02 +00005685 Results.ExitScope();
5686 }
5687
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005688 HandleCodeCompleteResults(this, CodeCompleter,
5689 CodeCompletionContext::CCC_ObjCProtocolName,
5690 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005691}
5692
5693void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005694 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005695 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005696 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005697
Douglas Gregor70c23352010-12-09 21:44:02 +00005698 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5699 Results.EnterNewScope();
5700
5701 // Add all protocols.
5702 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5703 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005704
Douglas Gregor70c23352010-12-09 21:44:02 +00005705 Results.ExitScope();
5706 }
5707
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005708 HandleCodeCompleteResults(this, CodeCompleter,
5709 CodeCompletionContext::CCC_ObjCProtocolName,
5710 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005711}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005712
5713/// \brief Add all of the Objective-C interface declarations that we find in
5714/// the given (translation unit) context.
5715static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5716 bool OnlyForwardDeclarations,
5717 bool OnlyUnimplemented,
5718 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005719 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005720
5721 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5722 DEnd = Ctx->decls_end();
5723 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005724 // Record any interfaces we find.
5725 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005726 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005727 (!OnlyUnimplemented || !Class->getImplementation()))
5728 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005729 }
5730}
5731
5732void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005733 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005734 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005735 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005736 Results.EnterNewScope();
5737
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005738 if (CodeCompleter->includeGlobals()) {
5739 // Add all classes.
5740 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5741 false, Results);
5742 }
5743
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005744 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005745
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005746 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005747 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005748 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005749}
5750
Douglas Gregorc83c6872010-04-15 22:33:43 +00005751void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5752 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005753 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005754 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005755 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005756 Results.EnterNewScope();
5757
5758 // Make sure that we ignore the class we're currently defining.
5759 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005760 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005761 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005762 Results.Ignore(CurClass);
5763
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005764 if (CodeCompleter->includeGlobals()) {
5765 // Add all classes.
5766 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5767 false, Results);
5768 }
5769
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005770 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005771
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005772 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005773 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005774 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005775}
5776
5777void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005778 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005779 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005780 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005781 Results.EnterNewScope();
5782
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005783 if (CodeCompleter->includeGlobals()) {
5784 // Add all unimplemented classes.
5785 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5786 true, Results);
5787 }
5788
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005789 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005790
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005791 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005792 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005793 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005794}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005795
5796void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005797 IdentifierInfo *ClassName,
5798 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005799 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005800
Douglas Gregor218937c2011-02-01 19:23:04 +00005801 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005802 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005803 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005804
5805 // Ignore any categories we find that have already been implemented by this
5806 // interface.
5807 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5808 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005809 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005810 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5811 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5812 Category = Category->getNextClassCategory())
5813 CategoryNames.insert(Category->getIdentifier());
5814
5815 // Add all of the categories we know about.
5816 Results.EnterNewScope();
5817 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5818 for (DeclContext::decl_iterator D = TU->decls_begin(),
5819 DEnd = TU->decls_end();
5820 D != DEnd; ++D)
5821 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5822 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005823 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005824 Results.ExitScope();
5825
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005826 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005827 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005828 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005829}
5830
5831void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005832 IdentifierInfo *ClassName,
5833 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005834 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005835
5836 // Find the corresponding interface. If we couldn't find the interface, the
5837 // program itself is ill-formed. However, we'll try to be helpful still by
5838 // providing the list of all of the categories we know about.
5839 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005840 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005841 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5842 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005843 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005844
Douglas Gregor218937c2011-02-01 19:23:04 +00005845 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005846 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005847 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005848
5849 // Add all of the categories that have have corresponding interface
5850 // declarations in this class and any of its superclasses, except for
5851 // already-implemented categories in the class itself.
5852 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5853 Results.EnterNewScope();
5854 bool IgnoreImplemented = true;
5855 while (Class) {
5856 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5857 Category = Category->getNextClassCategory())
5858 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5859 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005860 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005861
5862 Class = Class->getSuperClass();
5863 IgnoreImplemented = false;
5864 }
5865 Results.ExitScope();
5866
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005867 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005868 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005869 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005870}
Douglas Gregor322328b2009-11-18 22:32:06 +00005871
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005872void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005873 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005874 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005875 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005876
5877 // Figure out where this @synthesize lives.
5878 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005879 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005880 if (!Container ||
5881 (!isa<ObjCImplementationDecl>(Container) &&
5882 !isa<ObjCCategoryImplDecl>(Container)))
5883 return;
5884
5885 // Ignore any properties that have already been implemented.
Douglas Gregorb92a4082012-06-12 13:44:08 +00005886 Container = getContainerDef(Container);
5887 for (DeclContext::decl_iterator D = Container->decls_begin(),
Douglas Gregor322328b2009-11-18 22:32:06 +00005888 DEnd = Container->decls_end();
5889 D != DEnd; ++D)
5890 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5891 Results.Ignore(PropertyImpl->getPropertyDecl());
5892
5893 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005894 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005895 Results.EnterNewScope();
5896 if (ObjCImplementationDecl *ClassImpl
5897 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005898 AddObjCProperties(ClassImpl->getClassInterface(), false,
5899 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005900 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005901 else
5902 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005903 false, /*AllowNullaryMethods=*/false, CurContext,
5904 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005905 Results.ExitScope();
5906
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005907 HandleCodeCompleteResults(this, CodeCompleter,
5908 CodeCompletionContext::CCC_Other,
5909 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005910}
5911
5912void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005913 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005914 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005915 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005916 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005917 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005918
5919 // Figure out where this @synthesize lives.
5920 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005921 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005922 if (!Container ||
5923 (!isa<ObjCImplementationDecl>(Container) &&
5924 !isa<ObjCCategoryImplDecl>(Container)))
5925 return;
5926
5927 // Figure out which interface we're looking into.
5928 ObjCInterfaceDecl *Class = 0;
5929 if (ObjCImplementationDecl *ClassImpl
5930 = dyn_cast<ObjCImplementationDecl>(Container))
5931 Class = ClassImpl->getClassInterface();
5932 else
5933 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5934 ->getClassInterface();
5935
Douglas Gregore8426052011-04-18 14:40:46 +00005936 // Determine the type of the property we're synthesizing.
5937 QualType PropertyType = Context.getObjCIdType();
5938 if (Class) {
5939 if (ObjCPropertyDecl *Property
5940 = Class->FindPropertyDeclaration(PropertyName)) {
5941 PropertyType
5942 = Property->getType().getNonReferenceType().getUnqualifiedType();
5943
5944 // Give preference to ivars
5945 Results.setPreferredType(PropertyType);
5946 }
5947 }
5948
Douglas Gregor322328b2009-11-18 22:32:06 +00005949 // Add all of the instance variables in this class and its superclasses.
5950 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005951 bool SawSimilarlyNamedIvar = false;
5952 std::string NameWithPrefix;
5953 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005954 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005955 std::string NameWithSuffix = PropertyName->getName().str();
5956 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005957 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005958 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5959 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005960 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5961
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005962 // Determine whether we've seen an ivar with a name similar to the
5963 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005964 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005965 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005966 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005967 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005968
5969 // Reduce the priority of this result by one, to give it a slight
5970 // advantage over other results whose names don't match so closely.
5971 if (Results.size() &&
5972 Results.data()[Results.size() - 1].Kind
5973 == CodeCompletionResult::RK_Declaration &&
5974 Results.data()[Results.size() - 1].Declaration == Ivar)
5975 Results.data()[Results.size() - 1].Priority--;
5976 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005977 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005978 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005979
5980 if (!SawSimilarlyNamedIvar) {
5981 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005982 // an ivar of the appropriate type.
5983 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005984 typedef CodeCompletionResult Result;
5985 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005986 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
5987 Priority,CXAvailability_Available);
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005988
Douglas Gregor8987b232011-09-27 23:30:47 +00005989 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00005990 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005991 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005992 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5993 Results.AddResult(Result(Builder.TakeString(), Priority,
5994 CXCursor_ObjCIvarDecl));
5995 }
5996
Douglas Gregor322328b2009-11-18 22:32:06 +00005997 Results.ExitScope();
5998
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005999 HandleCodeCompleteResults(this, CodeCompleter,
6000 CodeCompletionContext::CCC_Other,
6001 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00006002}
Douglas Gregore8f5a172010-04-07 00:21:17 +00006003
Douglas Gregor408be5a2010-08-25 01:08:01 +00006004// Mapping from selectors to the methods that implement that selector, along
6005// with the "in original class" flag.
6006typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
6007 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006008
6009/// \brief Find all of the methods that reside in the given container
6010/// (and its superclasses, protocols, etc.) that meet the given
6011/// criteria. Insert those methods into the map of known methods,
6012/// indexed by selector so they can be easily found.
6013static void FindImplementableMethods(ASTContext &Context,
6014 ObjCContainerDecl *Container,
6015 bool WantInstanceMethods,
6016 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00006017 KnownMethodsMap &KnownMethods,
6018 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006019 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006020 // Make sure we have a definition; that's what we'll walk.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006021 if (!IFace->hasDefinition())
6022 return;
Douglas Gregorb92a4082012-06-12 13:44:08 +00006023
6024 IFace = IFace->getDefinition();
6025 Container = IFace;
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006026
Douglas Gregore8f5a172010-04-07 00:21:17 +00006027 const ObjCList<ObjCProtocolDecl> &Protocols
6028 = IFace->getReferencedProtocols();
6029 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006030 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006031 I != E; ++I)
6032 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006033 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006034
Douglas Gregorea766182010-10-18 18:21:28 +00006035 // Add methods from any class extensions and categories.
6036 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
6037 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00006038 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
6039 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006040 KnownMethods, false);
6041
6042 // Visit the superclass.
6043 if (IFace->getSuperClass())
6044 FindImplementableMethods(Context, IFace->getSuperClass(),
6045 WantInstanceMethods, ReturnType,
6046 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006047 }
6048
6049 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6050 // Recurse into protocols.
6051 const ObjCList<ObjCProtocolDecl> &Protocols
6052 = Category->getReferencedProtocols();
6053 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006054 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006055 I != E; ++I)
6056 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006057 KnownMethods, InOriginalClass);
6058
6059 // If this category is the original class, jump to the interface.
6060 if (InOriginalClass && Category->getClassInterface())
6061 FindImplementableMethods(Context, Category->getClassInterface(),
6062 WantInstanceMethods, ReturnType, KnownMethods,
6063 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006064 }
6065
6066 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006067 // Make sure we have a definition; that's what we'll walk.
6068 if (!Protocol->hasDefinition())
6069 return;
6070 Protocol = Protocol->getDefinition();
6071 Container = Protocol;
6072
6073 // Recurse into protocols.
6074 const ObjCList<ObjCProtocolDecl> &Protocols
6075 = Protocol->getReferencedProtocols();
6076 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6077 E = Protocols.end();
6078 I != E; ++I)
6079 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6080 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006081 }
6082
6083 // Add methods in this container. This operation occurs last because
6084 // we want the methods from this container to override any methods
6085 // we've previously seen with the same selector.
6086 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
6087 MEnd = Container->meth_end();
6088 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00006089 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006090 if (!ReturnType.isNull() &&
David Blaikie262bc182012-04-30 02:36:29 +00006091 !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006092 continue;
6093
David Blaikie581deb32012-06-06 20:45:41 +00006094 KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006095 }
6096 }
6097}
6098
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006099/// \brief Add the parenthesized return or parameter type chunk to a code
6100/// completion string.
6101static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor90f5f472012-04-10 18:35:07 +00006102 unsigned ObjCDeclQuals,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006103 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006104 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006105 CodeCompletionBuilder &Builder) {
6106 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor90f5f472012-04-10 18:35:07 +00006107 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
6108 if (!Quals.empty())
6109 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor8987b232011-09-27 23:30:47 +00006110 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006111 Builder.getAllocator()));
6112 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6113}
6114
6115/// \brief Determine whether the given class is or inherits from a class by
6116/// the given name.
6117static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00006118 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006119 if (!Class)
6120 return false;
6121
6122 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6123 return true;
6124
6125 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6126}
6127
6128/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6129/// Key-Value Observing (KVO).
6130static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6131 bool IsInstanceMethod,
6132 QualType ReturnType,
6133 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006134 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006135 ResultBuilder &Results) {
6136 IdentifierInfo *PropName = Property->getIdentifier();
6137 if (!PropName || PropName->getLength() == 0)
6138 return;
6139
Douglas Gregor8987b232011-09-27 23:30:47 +00006140 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6141
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006142 // Builder that will create each code completion.
6143 typedef CodeCompletionResult Result;
6144 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006145 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006146
6147 // The selector table.
6148 SelectorTable &Selectors = Context.Selectors;
6149
6150 // The property name, copied into the code completion allocation region
6151 // on demand.
6152 struct KeyHolder {
6153 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006154 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006155 const char *CopiedKey;
6156
Chris Lattner5f9e2722011-07-23 10:55:15 +00006157 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006158 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6159
6160 operator const char *() {
6161 if (CopiedKey)
6162 return CopiedKey;
6163
6164 return CopiedKey = Allocator.CopyString(Key);
6165 }
6166 } Key(Allocator, PropName->getName());
6167
6168 // The uppercased name of the property name.
6169 std::string UpperKey = PropName->getName();
6170 if (!UpperKey.empty())
6171 UpperKey[0] = toupper(UpperKey[0]);
6172
6173 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6174 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6175 Property->getType());
6176 bool ReturnTypeMatchesVoid
6177 = ReturnType.isNull() || ReturnType->isVoidType();
6178
6179 // Add the normal accessor -(type)key.
6180 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006181 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006182 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6183 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006184 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6185 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006186
6187 Builder.AddTypedTextChunk(Key);
6188 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6189 CXCursor_ObjCInstanceMethodDecl));
6190 }
6191
6192 // If we have an integral or boolean property (or the user has provided
6193 // an integral or boolean return type), add the accessor -(type)isKey.
6194 if (IsInstanceMethod &&
6195 ((!ReturnType.isNull() &&
6196 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6197 (ReturnType.isNull() &&
6198 (Property->getType()->isIntegerType() ||
6199 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006200 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006201 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006202 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006203 if (ReturnType.isNull()) {
6204 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6205 Builder.AddTextChunk("BOOL");
6206 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6207 }
6208
6209 Builder.AddTypedTextChunk(
6210 Allocator.CopyString(SelectorId->getName()));
6211 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6212 CXCursor_ObjCInstanceMethodDecl));
6213 }
6214 }
6215
6216 // Add the normal mutator.
6217 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6218 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006219 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006220 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006221 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006222 if (ReturnType.isNull()) {
6223 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6224 Builder.AddTextChunk("void");
6225 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6226 }
6227
6228 Builder.AddTypedTextChunk(
6229 Allocator.CopyString(SelectorId->getName()));
6230 Builder.AddTypedTextChunk(":");
Douglas Gregor90f5f472012-04-10 18:35:07 +00006231 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6232 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006233 Builder.AddTextChunk(Key);
6234 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6235 CXCursor_ObjCInstanceMethodDecl));
6236 }
6237 }
6238
6239 // Indexed and unordered accessors
6240 unsigned IndexedGetterPriority = CCP_CodePattern;
6241 unsigned IndexedSetterPriority = CCP_CodePattern;
6242 unsigned UnorderedGetterPriority = CCP_CodePattern;
6243 unsigned UnorderedSetterPriority = CCP_CodePattern;
6244 if (const ObjCObjectPointerType *ObjCPointer
6245 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6246 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6247 // If this interface type is not provably derived from a known
6248 // collection, penalize the corresponding completions.
6249 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6250 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6251 if (!InheritsFromClassNamed(IFace, "NSArray"))
6252 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6253 }
6254
6255 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6256 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6257 if (!InheritsFromClassNamed(IFace, "NSSet"))
6258 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6259 }
6260 }
6261 } else {
6262 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6263 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6264 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6265 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6266 }
6267
6268 // Add -(NSUInteger)countOf<key>
6269 if (IsInstanceMethod &&
6270 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006271 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006272 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006273 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006274 if (ReturnType.isNull()) {
6275 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6276 Builder.AddTextChunk("NSUInteger");
6277 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6278 }
6279
6280 Builder.AddTypedTextChunk(
6281 Allocator.CopyString(SelectorId->getName()));
6282 Results.AddResult(Result(Builder.TakeString(),
6283 std::min(IndexedGetterPriority,
6284 UnorderedGetterPriority),
6285 CXCursor_ObjCInstanceMethodDecl));
6286 }
6287 }
6288
6289 // Indexed getters
6290 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6291 if (IsInstanceMethod &&
6292 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006293 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006294 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006295 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006296 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006297 if (ReturnType.isNull()) {
6298 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6299 Builder.AddTextChunk("id");
6300 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6301 }
6302
6303 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6304 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6305 Builder.AddTextChunk("NSUInteger");
6306 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6307 Builder.AddTextChunk("index");
6308 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6309 CXCursor_ObjCInstanceMethodDecl));
6310 }
6311 }
6312
6313 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6314 if (IsInstanceMethod &&
6315 (ReturnType.isNull() ||
6316 (ReturnType->isObjCObjectPointerType() &&
6317 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6318 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6319 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006320 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006321 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006322 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006323 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006324 if (ReturnType.isNull()) {
6325 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6326 Builder.AddTextChunk("NSArray *");
6327 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6328 }
6329
6330 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6331 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6332 Builder.AddTextChunk("NSIndexSet *");
6333 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6334 Builder.AddTextChunk("indexes");
6335 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6336 CXCursor_ObjCInstanceMethodDecl));
6337 }
6338 }
6339
6340 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6341 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006342 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006343 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006344 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006345 &Context.Idents.get("range")
6346 };
6347
Douglas Gregore74c25c2011-05-04 23:50:46 +00006348 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006349 if (ReturnType.isNull()) {
6350 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6351 Builder.AddTextChunk("void");
6352 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6353 }
6354
6355 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6356 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6357 Builder.AddPlaceholderChunk("object-type");
6358 Builder.AddTextChunk(" **");
6359 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6360 Builder.AddTextChunk("buffer");
6361 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6362 Builder.AddTypedTextChunk("range:");
6363 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6364 Builder.AddTextChunk("NSRange");
6365 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6366 Builder.AddTextChunk("inRange");
6367 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6368 CXCursor_ObjCInstanceMethodDecl));
6369 }
6370 }
6371
6372 // Mutable indexed accessors
6373
6374 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6375 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006376 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006377 IdentifierInfo *SelectorIds[2] = {
6378 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006379 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006380 };
6381
Douglas Gregore74c25c2011-05-04 23:50:46 +00006382 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006383 if (ReturnType.isNull()) {
6384 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6385 Builder.AddTextChunk("void");
6386 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6387 }
6388
6389 Builder.AddTypedTextChunk("insertObject:");
6390 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6391 Builder.AddPlaceholderChunk("object-type");
6392 Builder.AddTextChunk(" *");
6393 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6394 Builder.AddTextChunk("object");
6395 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6396 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6397 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6398 Builder.AddPlaceholderChunk("NSUInteger");
6399 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6400 Builder.AddTextChunk("index");
6401 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6402 CXCursor_ObjCInstanceMethodDecl));
6403 }
6404 }
6405
6406 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6407 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006408 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006409 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006410 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006411 &Context.Idents.get("atIndexes")
6412 };
6413
Douglas Gregore74c25c2011-05-04 23:50:46 +00006414 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006415 if (ReturnType.isNull()) {
6416 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6417 Builder.AddTextChunk("void");
6418 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6419 }
6420
6421 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6422 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6423 Builder.AddTextChunk("NSArray *");
6424 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6425 Builder.AddTextChunk("array");
6426 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6427 Builder.AddTypedTextChunk("atIndexes:");
6428 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6429 Builder.AddPlaceholderChunk("NSIndexSet *");
6430 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6431 Builder.AddTextChunk("indexes");
6432 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6433 CXCursor_ObjCInstanceMethodDecl));
6434 }
6435 }
6436
6437 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6438 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006439 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006440 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006441 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006442 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006443 if (ReturnType.isNull()) {
6444 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6445 Builder.AddTextChunk("void");
6446 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6447 }
6448
6449 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6450 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6451 Builder.AddTextChunk("NSUInteger");
6452 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6453 Builder.AddTextChunk("index");
6454 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6455 CXCursor_ObjCInstanceMethodDecl));
6456 }
6457 }
6458
6459 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6460 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006461 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006462 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006463 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006464 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006465 if (ReturnType.isNull()) {
6466 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6467 Builder.AddTextChunk("void");
6468 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6469 }
6470
6471 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6472 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6473 Builder.AddTextChunk("NSIndexSet *");
6474 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6475 Builder.AddTextChunk("indexes");
6476 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6477 CXCursor_ObjCInstanceMethodDecl));
6478 }
6479 }
6480
6481 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6482 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006483 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006484 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006485 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006486 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006487 &Context.Idents.get("withObject")
6488 };
6489
Douglas Gregore74c25c2011-05-04 23:50:46 +00006490 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006491 if (ReturnType.isNull()) {
6492 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6493 Builder.AddTextChunk("void");
6494 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6495 }
6496
6497 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6498 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6499 Builder.AddPlaceholderChunk("NSUInteger");
6500 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6501 Builder.AddTextChunk("index");
6502 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6503 Builder.AddTypedTextChunk("withObject:");
6504 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6505 Builder.AddTextChunk("id");
6506 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6507 Builder.AddTextChunk("object");
6508 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6509 CXCursor_ObjCInstanceMethodDecl));
6510 }
6511 }
6512
6513 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6514 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006515 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006516 = (Twine("replace") + UpperKey + "AtIndexes").str();
6517 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006518 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006519 &Context.Idents.get(SelectorName1),
6520 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006521 };
6522
Douglas Gregore74c25c2011-05-04 23:50:46 +00006523 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006524 if (ReturnType.isNull()) {
6525 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6526 Builder.AddTextChunk("void");
6527 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6528 }
6529
6530 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6531 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6532 Builder.AddPlaceholderChunk("NSIndexSet *");
6533 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6534 Builder.AddTextChunk("indexes");
6535 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6536 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6537 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6538 Builder.AddTextChunk("NSArray *");
6539 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6540 Builder.AddTextChunk("array");
6541 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6542 CXCursor_ObjCInstanceMethodDecl));
6543 }
6544 }
6545
6546 // Unordered getters
6547 // - (NSEnumerator *)enumeratorOfKey
6548 if (IsInstanceMethod &&
6549 (ReturnType.isNull() ||
6550 (ReturnType->isObjCObjectPointerType() &&
6551 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6552 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6553 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006554 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006555 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006556 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006557 if (ReturnType.isNull()) {
6558 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6559 Builder.AddTextChunk("NSEnumerator *");
6560 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6561 }
6562
6563 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6564 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6565 CXCursor_ObjCInstanceMethodDecl));
6566 }
6567 }
6568
6569 // - (type *)memberOfKey:(type *)object
6570 if (IsInstanceMethod &&
6571 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006572 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006573 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006574 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006575 if (ReturnType.isNull()) {
6576 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6577 Builder.AddPlaceholderChunk("object-type");
6578 Builder.AddTextChunk(" *");
6579 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6580 }
6581
6582 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6583 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6584 if (ReturnType.isNull()) {
6585 Builder.AddPlaceholderChunk("object-type");
6586 Builder.AddTextChunk(" *");
6587 } else {
6588 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006589 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006590 Builder.getAllocator()));
6591 }
6592 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6593 Builder.AddTextChunk("object");
6594 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6595 CXCursor_ObjCInstanceMethodDecl));
6596 }
6597 }
6598
6599 // Mutable unordered accessors
6600 // - (void)addKeyObject:(type *)object
6601 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006602 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006603 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006604 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006605 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006606 if (ReturnType.isNull()) {
6607 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6608 Builder.AddTextChunk("void");
6609 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6610 }
6611
6612 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6613 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6614 Builder.AddPlaceholderChunk("object-type");
6615 Builder.AddTextChunk(" *");
6616 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6617 Builder.AddTextChunk("object");
6618 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6619 CXCursor_ObjCInstanceMethodDecl));
6620 }
6621 }
6622
6623 // - (void)addKey:(NSSet *)objects
6624 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006625 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006626 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006627 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006628 if (ReturnType.isNull()) {
6629 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6630 Builder.AddTextChunk("void");
6631 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6632 }
6633
6634 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6635 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6636 Builder.AddTextChunk("NSSet *");
6637 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6638 Builder.AddTextChunk("objects");
6639 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6640 CXCursor_ObjCInstanceMethodDecl));
6641 }
6642 }
6643
6644 // - (void)removeKeyObject:(type *)object
6645 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006646 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006647 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006648 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006649 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006650 if (ReturnType.isNull()) {
6651 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6652 Builder.AddTextChunk("void");
6653 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6654 }
6655
6656 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6657 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6658 Builder.AddPlaceholderChunk("object-type");
6659 Builder.AddTextChunk(" *");
6660 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6661 Builder.AddTextChunk("object");
6662 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6663 CXCursor_ObjCInstanceMethodDecl));
6664 }
6665 }
6666
6667 // - (void)removeKey:(NSSet *)objects
6668 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006669 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006670 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006671 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006672 if (ReturnType.isNull()) {
6673 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6674 Builder.AddTextChunk("void");
6675 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6676 }
6677
6678 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6679 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6680 Builder.AddTextChunk("NSSet *");
6681 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6682 Builder.AddTextChunk("objects");
6683 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6684 CXCursor_ObjCInstanceMethodDecl));
6685 }
6686 }
6687
6688 // - (void)intersectKey:(NSSet *)objects
6689 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006690 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006691 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006692 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006693 if (ReturnType.isNull()) {
6694 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6695 Builder.AddTextChunk("void");
6696 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6697 }
6698
6699 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6700 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6701 Builder.AddTextChunk("NSSet *");
6702 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6703 Builder.AddTextChunk("objects");
6704 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6705 CXCursor_ObjCInstanceMethodDecl));
6706 }
6707 }
6708
6709 // Key-Value Observing
6710 // + (NSSet *)keyPathsForValuesAffectingKey
6711 if (!IsInstanceMethod &&
6712 (ReturnType.isNull() ||
6713 (ReturnType->isObjCObjectPointerType() &&
6714 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6715 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6716 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006717 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006718 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006719 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006720 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006721 if (ReturnType.isNull()) {
6722 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6723 Builder.AddTextChunk("NSSet *");
6724 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6725 }
6726
6727 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6728 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006729 CXCursor_ObjCClassMethodDecl));
6730 }
6731 }
6732
6733 // + (BOOL)automaticallyNotifiesObserversForKey
6734 if (!IsInstanceMethod &&
6735 (ReturnType.isNull() ||
6736 ReturnType->isIntegerType() ||
6737 ReturnType->isBooleanType())) {
6738 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006739 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006740 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6741 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6742 if (ReturnType.isNull()) {
6743 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6744 Builder.AddTextChunk("BOOL");
6745 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6746 }
6747
6748 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6749 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6750 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006751 }
6752 }
6753}
6754
Douglas Gregore8f5a172010-04-07 00:21:17 +00006755void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6756 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006757 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006758 // Determine the return type of the method we're declaring, if
6759 // provided.
6760 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006761 Decl *IDecl = 0;
6762 if (CurContext->isObjCContainer()) {
6763 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6764 IDecl = cast<Decl>(OCD);
6765 }
Douglas Gregorea766182010-10-18 18:21:28 +00006766 // Determine where we should start searching for methods.
6767 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006768 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006769 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006770 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6771 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006772 IsInImplementation = true;
6773 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006774 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006775 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006776 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006777 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006778 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006779 }
6780
6781 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006782 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006783 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006784 }
6785
Douglas Gregorea766182010-10-18 18:21:28 +00006786 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006787 HandleCodeCompleteResults(this, CodeCompleter,
6788 CodeCompletionContext::CCC_Other,
6789 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006790 return;
6791 }
6792
6793 // Find all of the methods that we could declare/implement here.
6794 KnownMethodsMap KnownMethods;
6795 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006796 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006797
Douglas Gregore8f5a172010-04-07 00:21:17 +00006798 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006799 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006800 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006801 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006802 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006803 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006804 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006805 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6806 MEnd = KnownMethods.end();
6807 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006808 ObjCMethodDecl *Method = M->second.first;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006809 CodeCompletionBuilder Builder(Results.getAllocator(),
6810 Results.getCodeCompletionTUInfo());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006811
6812 // If the result type was not already provided, add it to the
6813 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006814 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006815 AddObjCPassingTypeChunk(Method->getResultType(),
6816 Method->getObjCDeclQualifier(),
6817 Context, Policy,
6818 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006819
6820 Selector Sel = Method->getSelector();
6821
6822 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006823 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006824 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006825
6826 // Add parameters to the pattern.
6827 unsigned I = 0;
6828 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6829 PEnd = Method->param_end();
6830 P != PEnd; (void)++P, ++I) {
6831 // Add the part of the selector name.
6832 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006833 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006834 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006835 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6836 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006837 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006838 } else
6839 break;
6840
6841 // Add the parameter type.
Douglas Gregor90f5f472012-04-10 18:35:07 +00006842 AddObjCPassingTypeChunk((*P)->getOriginalType(),
6843 (*P)->getObjCDeclQualifier(),
6844 Context, Policy,
Douglas Gregor8987b232011-09-27 23:30:47 +00006845 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006846
6847 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006848 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006849 }
6850
6851 if (Method->isVariadic()) {
6852 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006853 Builder.AddChunk(CodeCompletionString::CK_Comma);
6854 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006855 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006856
Douglas Gregor447107d2010-05-28 00:57:46 +00006857 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006858 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006859 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6860 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6861 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006862 if (!Method->getResultType()->isVoidType()) {
6863 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006864 Builder.AddTextChunk("return");
6865 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6866 Builder.AddPlaceholderChunk("expression");
6867 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006868 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006869 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006870
Douglas Gregor218937c2011-02-01 19:23:04 +00006871 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6872 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006873 }
6874
Douglas Gregor408be5a2010-08-25 01:08:01 +00006875 unsigned Priority = CCP_CodePattern;
6876 if (!M->second.second)
6877 Priority += CCD_InBaseClass;
6878
Douglas Gregorba103062012-03-27 23:34:16 +00006879 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006880 }
6881
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006882 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6883 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006884 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006885 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006886 Containers.push_back(SearchDecl);
6887
Douglas Gregore74c25c2011-05-04 23:50:46 +00006888 VisitedSelectorSet KnownSelectors;
6889 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6890 MEnd = KnownMethods.end();
6891 M != MEnd; ++M)
6892 KnownSelectors.insert(M->first);
6893
6894
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006895 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6896 if (!IFace)
6897 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6898 IFace = Category->getClassInterface();
6899
6900 if (IFace) {
6901 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6902 Category = Category->getNextClassCategory())
6903 Containers.push_back(Category);
6904 }
6905
6906 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6907 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6908 PEnd = Containers[I]->prop_end();
6909 P != PEnd; ++P) {
David Blaikie581deb32012-06-06 20:45:41 +00006910 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006911 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006912 }
6913 }
6914 }
6915
Douglas Gregore8f5a172010-04-07 00:21:17 +00006916 Results.ExitScope();
6917
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006918 HandleCodeCompleteResults(this, CodeCompleter,
6919 CodeCompletionContext::CCC_Other,
6920 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006921}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006922
6923void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6924 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006925 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006926 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006927 IdentifierInfo **SelIdents,
6928 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006929 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006930 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006931 if (ExternalSource) {
6932 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6933 I != N; ++I) {
6934 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006935 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006936 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006937
6938 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006939 }
6940 }
6941
6942 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006943 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006944 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006945 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006946 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006947
6948 if (ReturnTy)
6949 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006950
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006951 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006952 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6953 MEnd = MethodPool.end();
6954 M != MEnd; ++M) {
6955 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6956 &M->second.second;
6957 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006958 MethList = MethList->Next) {
6959 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6960 NumSelIdents))
6961 continue;
6962
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006963 if (AtParameterName) {
6964 // Suggest parameter names we've seen before.
6965 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6966 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6967 if (Param->getIdentifier()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006968 CodeCompletionBuilder Builder(Results.getAllocator(),
6969 Results.getCodeCompletionTUInfo());
Douglas Gregordae68752011-02-01 22:57:45 +00006970 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006971 Param->getIdentifier()->getName()));
6972 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006973 }
6974 }
6975
6976 continue;
6977 }
6978
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006979 Result R(MethList->Method, 0);
6980 R.StartParameter = NumSelIdents;
6981 R.AllParametersAreInformative = false;
6982 R.DeclaringEntity = true;
6983 Results.MaybeAddResult(R, CurContext);
6984 }
6985 }
6986
6987 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006988 HandleCodeCompleteResults(this, CodeCompleter,
6989 CodeCompletionContext::CCC_Other,
6990 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006991}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006992
Douglas Gregorf29c5232010-08-24 22:20:20 +00006993void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006994 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006995 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006996 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006997 Results.EnterNewScope();
6998
6999 // #if <condition>
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007000 CodeCompletionBuilder Builder(Results.getAllocator(),
7001 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007002 Builder.AddTypedTextChunk("if");
7003 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7004 Builder.AddPlaceholderChunk("condition");
7005 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007006
7007 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007008 Builder.AddTypedTextChunk("ifdef");
7009 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7010 Builder.AddPlaceholderChunk("macro");
7011 Results.AddResult(Builder.TakeString());
7012
Douglas Gregorf44e8542010-08-24 19:08:16 +00007013 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007014 Builder.AddTypedTextChunk("ifndef");
7015 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7016 Builder.AddPlaceholderChunk("macro");
7017 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007018
7019 if (InConditional) {
7020 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00007021 Builder.AddTypedTextChunk("elif");
7022 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7023 Builder.AddPlaceholderChunk("condition");
7024 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007025
7026 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00007027 Builder.AddTypedTextChunk("else");
7028 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007029
7030 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00007031 Builder.AddTypedTextChunk("endif");
7032 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007033 }
7034
7035 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007036 Builder.AddTypedTextChunk("include");
7037 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7038 Builder.AddTextChunk("\"");
7039 Builder.AddPlaceholderChunk("header");
7040 Builder.AddTextChunk("\"");
7041 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007042
7043 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007044 Builder.AddTypedTextChunk("include");
7045 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7046 Builder.AddTextChunk("<");
7047 Builder.AddPlaceholderChunk("header");
7048 Builder.AddTextChunk(">");
7049 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007050
7051 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007052 Builder.AddTypedTextChunk("define");
7053 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7054 Builder.AddPlaceholderChunk("macro");
7055 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007056
7057 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00007058 Builder.AddTypedTextChunk("define");
7059 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7060 Builder.AddPlaceholderChunk("macro");
7061 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7062 Builder.AddPlaceholderChunk("args");
7063 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7064 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007065
7066 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007067 Builder.AddTypedTextChunk("undef");
7068 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7069 Builder.AddPlaceholderChunk("macro");
7070 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007071
7072 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00007073 Builder.AddTypedTextChunk("line");
7074 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7075 Builder.AddPlaceholderChunk("number");
7076 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007077
7078 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00007079 Builder.AddTypedTextChunk("line");
7080 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7081 Builder.AddPlaceholderChunk("number");
7082 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7083 Builder.AddTextChunk("\"");
7084 Builder.AddPlaceholderChunk("filename");
7085 Builder.AddTextChunk("\"");
7086 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007087
7088 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007089 Builder.AddTypedTextChunk("error");
7090 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7091 Builder.AddPlaceholderChunk("message");
7092 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007093
7094 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00007095 Builder.AddTypedTextChunk("pragma");
7096 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7097 Builder.AddPlaceholderChunk("arguments");
7098 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007099
David Blaikie4e4d0842012-03-11 07:00:24 +00007100 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00007101 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007102 Builder.AddTypedTextChunk("import");
7103 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7104 Builder.AddTextChunk("\"");
7105 Builder.AddPlaceholderChunk("header");
7106 Builder.AddTextChunk("\"");
7107 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007108
7109 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007110 Builder.AddTypedTextChunk("import");
7111 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7112 Builder.AddTextChunk("<");
7113 Builder.AddPlaceholderChunk("header");
7114 Builder.AddTextChunk(">");
7115 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007116 }
7117
7118 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007119 Builder.AddTypedTextChunk("include_next");
7120 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7121 Builder.AddTextChunk("\"");
7122 Builder.AddPlaceholderChunk("header");
7123 Builder.AddTextChunk("\"");
7124 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007125
7126 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007127 Builder.AddTypedTextChunk("include_next");
7128 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7129 Builder.AddTextChunk("<");
7130 Builder.AddPlaceholderChunk("header");
7131 Builder.AddTextChunk(">");
7132 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007133
7134 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007135 Builder.AddTypedTextChunk("warning");
7136 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7137 Builder.AddPlaceholderChunk("message");
7138 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007139
7140 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7141 // completions for them. And __include_macros is a Clang-internal extension
7142 // that we don't want to encourage anyone to use.
7143
7144 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7145 Results.ExitScope();
7146
Douglas Gregorf44e8542010-08-24 19:08:16 +00007147 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00007148 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00007149 Results.data(), Results.size());
7150}
7151
7152void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007153 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007154 S->getFnParent()? Sema::PCC_RecoveryInFunction
7155 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007156}
7157
Douglas Gregorf29c5232010-08-24 22:20:20 +00007158void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007159 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007160 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007161 IsDefinition? CodeCompletionContext::CCC_MacroName
7162 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007163 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7164 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007165 CodeCompletionBuilder Builder(Results.getAllocator(),
7166 Results.getCodeCompletionTUInfo());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007167 Results.EnterNewScope();
7168 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7169 MEnd = PP.macro_end();
7170 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007171 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007172 M->first->getName()));
Argyrios Kyrtzidisc04bb922012-09-27 00:24:09 +00007173 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7174 CCP_CodePattern,
7175 CXCursor_MacroDefinition));
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007176 }
7177 Results.ExitScope();
7178 } else if (IsDefinition) {
7179 // FIXME: Can we detect when the user just wrote an include guard above?
7180 }
7181
Douglas Gregor52779fb2010-09-23 23:01:17 +00007182 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007183 Results.data(), Results.size());
7184}
7185
Douglas Gregorf29c5232010-08-24 22:20:20 +00007186void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007187 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007188 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007189 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007190
7191 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00007192 AddMacroResults(PP, Results, true);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007193
7194 // defined (<macro>)
7195 Results.EnterNewScope();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007196 CodeCompletionBuilder Builder(Results.getAllocator(),
7197 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007198 Builder.AddTypedTextChunk("defined");
7199 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7200 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7201 Builder.AddPlaceholderChunk("macro");
7202 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7203 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007204 Results.ExitScope();
7205
7206 HandleCodeCompleteResults(this, CodeCompleter,
7207 CodeCompletionContext::CCC_PreprocessorExpression,
7208 Results.data(), Results.size());
7209}
7210
7211void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7212 IdentifierInfo *Macro,
7213 MacroInfo *MacroInfo,
7214 unsigned Argument) {
7215 // FIXME: In the future, we could provide "overload" results, much like we
7216 // do for function calls.
7217
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007218 // Now just ignore this. There will be another code-completion callback
7219 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007220}
7221
Douglas Gregor55817af2010-08-25 17:04:25 +00007222void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007223 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007224 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007225 0, 0);
7226}
7227
Douglas Gregordae68752011-02-01 22:57:45 +00007228void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007229 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007230 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007231 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7232 CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007233 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7234 CodeCompletionDeclConsumer Consumer(Builder,
7235 Context.getTranslationUnitDecl());
7236 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7237 Consumer);
7238 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007239
7240 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00007241 AddMacroResults(PP, Builder, true);
Douglas Gregor87c08a52010-08-13 22:48:40 +00007242
7243 Results.clear();
7244 Results.insert(Results.end(),
7245 Builder.data(), Builder.data() + Builder.size());
7246}