blob: 5cbba239be1a20ada87a029debca95b5650a2a6c [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
Richard Smith80ad52f2013-01-02 11:42:31 +00001260 if (LangOpts.CPlusPlus11) {
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
Richard Smith80ad52f2013-01-02 11:42:31 +00001910 if (SemaRef.getLangOpts().CPlusPlus11) {
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
Dmitri Gribenko06d8c602013-01-11 20:32:41 +00002831CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002832 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:
Dmitri Gribenko06d8c602013-01-11 20:32:41 +00002891 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002892 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));
Richard Smith80ad52f2013-01-02 11:42:31 +00002934 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002935 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.
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00003096 SmallVector<Module *, 8> Modules;
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003097 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.
Douglas Gregord3297242013-01-16 23:00:23 +00003436 for (ObjCInterfaceDecl::known_categories_iterator
3437 Cat = IFace->known_categories_begin(),
3438 CatEnd = IFace->known_categories_end();
3439 Cat != CatEnd; ++Cat)
3440 AddObjCProperties(*Cat, AllowCategories, AllowNullaryMethods,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003441 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003442 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003443
3444 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003445 for (ObjCInterfaceDecl::all_protocol_iterator
3446 I = IFace->all_referenced_protocol_begin(),
3447 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003448 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3449 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003450
3451 // Look in the superclass.
3452 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003453 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3454 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003455 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003456 } else if (const ObjCCategoryDecl *Category
3457 = dyn_cast<ObjCCategoryDecl>(Container)) {
3458 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003459 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3460 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003461 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003462 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3463 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003464 }
3465}
3466
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003467void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003468 SourceLocation OpLoc,
3469 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003470 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003471 return;
3472
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003473 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3474 if (ConvertedBase.isInvalid())
3475 return;
3476 Base = ConvertedBase.get();
3477
John McCall0a2c5e22010-08-25 06:19:51 +00003478 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003479
Douglas Gregor81b747b2009-09-17 21:32:03 +00003480 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003481
3482 if (IsArrow) {
3483 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3484 BaseType = Ptr->getPointeeType();
3485 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003486 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003487 else
3488 return;
3489 }
3490
Douglas Gregor3da626b2011-07-07 16:03:39 +00003491 enum CodeCompletionContext::Kind contextKind;
3492
3493 if (IsArrow) {
3494 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3495 }
3496 else {
3497 if (BaseType->isObjCObjectPointerType() ||
3498 BaseType->isObjCObjectOrInterfaceType()) {
3499 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3500 }
3501 else {
3502 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3503 }
3504 }
3505
Douglas Gregor218937c2011-02-01 19:23:04 +00003506 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003507 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003508 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003509 BaseType),
3510 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003511 Results.EnterNewScope();
3512 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003513 // Indicate that we are performing a member access, and the cv-qualifiers
3514 // for the base object type.
3515 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3516
Douglas Gregor95ac6552009-11-18 01:29:26 +00003517 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003518 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003519 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003520 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3521 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003522
David Blaikie4e4d0842012-03-11 07:00:24 +00003523 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003524 if (!Results.empty()) {
3525 // The "template" keyword can follow "->" or "." in the grammar.
3526 // However, we only want to suggest the template keyword if something
3527 // is dependent.
3528 bool IsDependent = BaseType->isDependentType();
3529 if (!IsDependent) {
3530 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3531 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3532 IsDependent = Ctx->isDependentContext();
3533 break;
3534 }
3535 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003536
Douglas Gregor95ac6552009-11-18 01:29:26 +00003537 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003538 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003539 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003540 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003541 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3542 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003543 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003544
3545 // Add property results based on our interface.
3546 const ObjCObjectPointerType *ObjCPtr
3547 = BaseType->getAsObjCInterfacePointerType();
3548 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003549 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3550 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003551 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003552
3553 // Add properties from the protocols in a qualified interface.
3554 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3555 E = ObjCPtr->qual_end();
3556 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003557 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3558 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003559 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003560 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003561 // Objective-C instance variable access.
3562 ObjCInterfaceDecl *Class = 0;
3563 if (const ObjCObjectPointerType *ObjCPtr
3564 = BaseType->getAs<ObjCObjectPointerType>())
3565 Class = ObjCPtr->getInterfaceDecl();
3566 else
John McCallc12c5bb2010-05-15 11:32:37 +00003567 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003568
3569 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003570 if (Class) {
3571 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3572 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003573 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3574 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003575 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003576 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003577
3578 // FIXME: How do we cope with isa?
3579
3580 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003581
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003582 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003583 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003584 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003585 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003586}
3587
Douglas Gregor374929f2009-09-18 15:37:17 +00003588void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3589 if (!CodeCompleter)
3590 return;
3591
Douglas Gregor86d9a522009-09-21 16:56:56 +00003592 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003593 enum CodeCompletionContext::Kind ContextKind
3594 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003595 switch ((DeclSpec::TST)TagSpec) {
3596 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003597 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003598 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003599 break;
3600
3601 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003602 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003603 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003604 break;
3605
3606 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003607 case DeclSpec::TST_class:
Joao Matos6666ed42012-08-31 18:45:21 +00003608 case DeclSpec::TST_interface:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003609 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003610 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003611 break;
3612
3613 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003614 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003615 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003616
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003617 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3618 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003619 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003620
3621 // First pass: look for tags.
3622 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003623 LookupVisibleDecls(S, LookupTagName, Consumer,
3624 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003625
Douglas Gregor8071e422010-08-15 06:18:01 +00003626 if (CodeCompleter->includeGlobals()) {
3627 // Second pass: look for nested name specifiers.
3628 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3629 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3630 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003631
Douglas Gregor52779fb2010-09-23 23:01:17 +00003632 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003633 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003634}
3635
Douglas Gregor1a480c42010-08-27 17:35:51 +00003636void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003637 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003638 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003639 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003640 Results.EnterNewScope();
3641 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3642 Results.AddResult("const");
3643 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3644 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003645 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003646 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3647 Results.AddResult("restrict");
3648 Results.ExitScope();
3649 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003650 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003651 Results.data(), Results.size());
3652}
3653
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003654void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003655 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003656 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003657
John McCall781472f2010-08-25 08:40:02 +00003658 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003659 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3660 if (!type->isEnumeralType()) {
3661 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003662 Data.IntegralConstantExpression = true;
3663 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003664 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003665 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003666
3667 // Code-complete the cases of a switch statement over an enumeration type
3668 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003669 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregorb92a4082012-06-12 13:44:08 +00003670 if (EnumDecl *Def = Enum->getDefinition())
3671 Enum = Def;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003672
3673 // Determine which enumerators we have already seen in the switch statement.
3674 // FIXME: Ideally, we would also be able to look *past* the code-completion
3675 // token, in case we are code-completing in the middle of the switch and not
3676 // at the end. However, we aren't able to do so at the moment.
3677 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003678 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003679 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3680 SC = SC->getNextSwitchCase()) {
3681 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3682 if (!Case)
3683 continue;
3684
3685 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3686 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3687 if (EnumConstantDecl *Enumerator
3688 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3689 // We look into the AST of the case statement to determine which
3690 // enumerator was named. Alternatively, we could compute the value of
3691 // the integral constant expression, then compare it against the
3692 // values of each enumerator. However, value-based approach would not
3693 // work as well with C++ templates where enumerators declared within a
3694 // template are type- and value-dependent.
3695 EnumeratorsSeen.insert(Enumerator);
3696
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003697 // If this is a qualified-id, keep track of the nested-name-specifier
3698 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003699 //
3700 // switch (TagD.getKind()) {
3701 // case TagDecl::TK_enum:
3702 // break;
3703 // case XXX
3704 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003705 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003706 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3707 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003708 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003709 }
3710 }
3711
David Blaikie4e4d0842012-03-11 07:00:24 +00003712 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003713 // If there are no prior enumerators in C++, check whether we have to
3714 // qualify the names of the enumerators that we suggest, because they
3715 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003716 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003717 }
3718
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003719 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003720 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003721 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003722 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003723 Results.EnterNewScope();
3724 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3725 EEnd = Enum->enumerator_end();
3726 E != EEnd; ++E) {
David Blaikie581deb32012-06-06 20:45:41 +00003727 if (EnumeratorsSeen.count(*E))
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003728 continue;
3729
David Blaikie581deb32012-06-06 20:45:41 +00003730 CodeCompletionResult R(*E, Qualifier);
Douglas Gregor5c722c702011-02-18 23:30:37 +00003731 R.Priority = CCP_EnumInCase;
3732 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003733 }
3734 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003735
Douglas Gregor3da626b2011-07-07 16:03:39 +00003736 //We need to make sure we're setting the right context,
3737 //so only say we include macros if the code completer says we do
3738 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3739 if (CodeCompleter->includeMacros()) {
Douglas Gregor3644d972012-10-09 16:01:50 +00003740 AddMacroResults(PP, Results, false);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003741 kind = CodeCompletionContext::CCC_OtherWithMacros;
3742 }
3743
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003744 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003745 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003746 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003747}
3748
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003749namespace {
3750 struct IsBetterOverloadCandidate {
3751 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003752 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003753
3754 public:
John McCall5769d612010-02-08 23:07:23 +00003755 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3756 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003757
3758 bool
3759 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003760 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003761 }
3762 };
3763}
3764
Ahmed Charles13a140c2012-02-25 11:00:22 +00003765static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3766 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003767 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003768
3769 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003770 if (!Args[I])
3771 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003772
Douglas Gregord28dcd72010-05-30 06:10:08 +00003773 return false;
3774}
3775
Richard Trieuf81e5a92011-09-09 02:00:50 +00003776void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charles13a140c2012-02-25 11:00:22 +00003777 llvm::ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003778 if (!CodeCompleter)
3779 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003780
3781 // When we're code-completing for a call, we fall back to ordinary
3782 // name code-completion whenever we can't produce specific
3783 // results. We may want to revisit this strategy in the future,
3784 // e.g., by merging the two kinds of results.
3785
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003786 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003787
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003788 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003789 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3790 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003791 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003792 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003793 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003794
John McCall3b4294e2009-12-16 12:17:52 +00003795 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003796 SourceLocation Loc = Fn->getExprLoc();
3797 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003798
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003799 // FIXME: What if we're calling something that isn't a function declaration?
3800 // FIXME: What if we're calling a pseudo-destructor?
3801 // FIXME: What if we're calling a member function?
3802
Douglas Gregorc0265402010-01-21 15:46:19 +00003803 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003804 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003805
John McCall3b4294e2009-12-16 12:17:52 +00003806 Expr *NakedFn = Fn->IgnoreParenCasts();
3807 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003808 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003809 /*PartialOverloading=*/ true);
3810 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3811 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003812 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003813 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003814 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003815 Results.push_back(ResultCandidate(FDecl));
3816 else
John McCall86820f52010-01-26 01:37:31 +00003817 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003818 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3819 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003820 }
John McCall3b4294e2009-12-16 12:17:52 +00003821 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003822
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003823 QualType ParamType;
3824
Douglas Gregorc0265402010-01-21 15:46:19 +00003825 if (!CandidateSet.empty()) {
3826 // Sort the overload candidate set by placing the best overloads first.
3827 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003828 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003829
Douglas Gregorc0265402010-01-21 15:46:19 +00003830 // Add the remaining viable overload candidates as code-completion reslults.
3831 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3832 CandEnd = CandidateSet.end();
3833 Cand != CandEnd; ++Cand) {
3834 if (Cand->Viable)
3835 Results.push_back(ResultCandidate(Cand->Function));
3836 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003837
3838 // From the viable candidates, try to determine the type of this parameter.
3839 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3840 if (const FunctionType *FType = Results[I].getFunctionType())
3841 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003842 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003843 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003844 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003845 else if (!Context.hasSameUnqualifiedType(
3846 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003847 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003848 ParamType = QualType();
3849 break;
3850 }
3851 }
3852 }
3853 } else {
3854 // Try to determine the parameter type from the type of the expression
3855 // being called.
3856 QualType FunctionType = Fn->getType();
3857 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3858 FunctionType = Ptr->getPointeeType();
3859 else if (const BlockPointerType *BlockPtr
3860 = FunctionType->getAs<BlockPointerType>())
3861 FunctionType = BlockPtr->getPointeeType();
3862 else if (const MemberPointerType *MemPtr
3863 = FunctionType->getAs<MemberPointerType>())
3864 FunctionType = MemPtr->getPointeeType();
3865
3866 if (const FunctionProtoType *Proto
3867 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003868 if (Args.size() < Proto->getNumArgs())
3869 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003870 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003871 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003872
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003873 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003874 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003875 else
3876 CodeCompleteExpression(S, ParamType);
3877
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003878 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003879 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003880 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003881}
3882
John McCalld226f652010-08-21 09:40:31 +00003883void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3884 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003885 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003886 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003887 return;
3888 }
3889
3890 CodeCompleteExpression(S, VD->getType());
3891}
3892
3893void Sema::CodeCompleteReturn(Scope *S) {
3894 QualType ResultType;
3895 if (isa<BlockDecl>(CurContext)) {
3896 if (BlockScopeInfo *BSI = getCurBlock())
3897 ResultType = BSI->ReturnType;
3898 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3899 ResultType = Function->getResultType();
3900 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3901 ResultType = Method->getResultType();
3902
3903 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003904 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003905 else
3906 CodeCompleteExpression(S, ResultType);
3907}
3908
Douglas Gregord2d8be62011-07-30 08:36:53 +00003909void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregord2d8be62011-07-30 08:36:53 +00003910 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003911 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord2d8be62011-07-30 08:36:53 +00003912 mapCodeCompletionContext(*this, PCC_Statement));
3913 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3914 Results.EnterNewScope();
3915
3916 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3917 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3918 CodeCompleter->includeGlobals());
3919
3920 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3921
3922 // "else" block
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003923 CodeCompletionBuilder Builder(Results.getAllocator(),
3924 Results.getCodeCompletionTUInfo());
Douglas Gregord2d8be62011-07-30 08:36:53 +00003925 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00003926 if (Results.includeCodePatterns()) {
3927 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3928 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3929 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3930 Builder.AddPlaceholderChunk("statements");
3931 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3932 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3933 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003934 Results.AddResult(Builder.TakeString());
3935
3936 // "else if" block
3937 Builder.AddTypedTextChunk("else");
3938 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3939 Builder.AddTextChunk("if");
3940 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3941 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00003942 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00003943 Builder.AddPlaceholderChunk("condition");
3944 else
3945 Builder.AddPlaceholderChunk("expression");
3946 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00003947 if (Results.includeCodePatterns()) {
3948 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3949 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3950 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3951 Builder.AddPlaceholderChunk("statements");
3952 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3953 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3954 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003955 Results.AddResult(Builder.TakeString());
3956
3957 Results.ExitScope();
3958
3959 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003960 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003961
3962 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003963 AddMacroResults(PP, Results, false);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003964
3965 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3966 Results.data(),Results.size());
3967}
3968
Richard Trieuf81e5a92011-09-09 02:00:50 +00003969void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003970 if (LHS)
3971 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3972 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003973 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003974}
3975
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003976void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003977 bool EnteringContext) {
3978 if (!SS.getScopeRep() || !CodeCompleter)
3979 return;
3980
Douglas Gregor86d9a522009-09-21 16:56:56 +00003981 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3982 if (!Ctx)
3983 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003984
3985 // Try to instantiate any non-dependent declaration contexts before
3986 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003987 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003988 return;
3989
Douglas Gregor218937c2011-02-01 19:23:04 +00003990 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003991 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003992 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003993 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003994
Douglas Gregor86d9a522009-09-21 16:56:56 +00003995 // The "template" keyword can follow "::" in the grammar, but only
3996 // put it into the grammar if the nested-name-specifier is dependent.
3997 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3998 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003999 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00004000
4001 // Add calls to overridden virtual functions, if there are any.
4002 //
4003 // FIXME: This isn't wonderful, because we don't know whether we're actually
4004 // in a context that permits expressions. This is a general issue with
4005 // qualified-id completions.
4006 if (!EnteringContext)
4007 MaybeAddOverrideCalls(*this, Ctx, Results);
4008 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004009
Douglas Gregorf6961522010-08-27 21:18:54 +00004010 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4011 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
4012
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004013 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00004014 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004015 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00004016}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004017
4018void Sema::CodeCompleteUsing(Scope *S) {
4019 if (!CodeCompleter)
4020 return;
4021
Douglas Gregor218937c2011-02-01 19:23:04 +00004022 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004023 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004024 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4025 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004026 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004027
4028 // If we aren't in class scope, we could see the "namespace" keyword.
4029 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00004030 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004031
4032 // After "using", we can see anything that would start a
4033 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004034 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004035 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4036 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004037 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004038
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004039 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004040 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004041 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004042}
4043
4044void Sema::CodeCompleteUsingDirective(Scope *S) {
4045 if (!CodeCompleter)
4046 return;
4047
Douglas Gregor86d9a522009-09-21 16:56:56 +00004048 // After "using namespace", we expect to see a namespace name or namespace
4049 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004050 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004051 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004052 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004053 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004054 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004055 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004056 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4057 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004058 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004059 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004060 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004061 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004062}
4063
4064void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4065 if (!CodeCompleter)
4066 return;
4067
Douglas Gregor86d9a522009-09-21 16:56:56 +00004068 DeclContext *Ctx = (DeclContext *)S->getEntity();
4069 if (!S->getParent())
4070 Ctx = Context.getTranslationUnitDecl();
4071
Douglas Gregor52779fb2010-09-23 23:01:17 +00004072 bool SuppressedGlobalResults
4073 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4074
Douglas Gregor218937c2011-02-01 19:23:04 +00004075 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004076 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004077 SuppressedGlobalResults
4078 ? CodeCompletionContext::CCC_Namespace
4079 : CodeCompletionContext::CCC_Other,
4080 &ResultBuilder::IsNamespace);
4081
4082 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004083 // We only want to see those namespaces that have already been defined
4084 // within this scope, because its likely that the user is creating an
4085 // extended namespace declaration. Keep track of the most recent
4086 // definition of each namespace.
4087 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4088 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4089 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4090 NS != NSEnd; ++NS)
David Blaikie581deb32012-06-06 20:45:41 +00004091 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004092
4093 // Add the most recent definition (or extended definition) of each
4094 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004095 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004096 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregorba103062012-03-27 23:34:16 +00004097 NS = OrigToLatest.begin(),
4098 NSEnd = OrigToLatest.end();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004099 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004100 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004101 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004102 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004103 }
4104
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004105 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004106 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004107 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004108}
4109
4110void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4111 if (!CodeCompleter)
4112 return;
4113
Douglas Gregor86d9a522009-09-21 16:56:56 +00004114 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004115 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004116 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004117 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004118 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004119 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004120 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4121 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004122 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004123 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004124 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004125}
4126
Douglas Gregored8d3222009-09-18 20:05:18 +00004127void Sema::CodeCompleteOperatorName(Scope *S) {
4128 if (!CodeCompleter)
4129 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004130
John McCall0a2c5e22010-08-25 06:19:51 +00004131 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004132 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004133 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004134 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004135 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004136 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004137
Douglas Gregor86d9a522009-09-21 16:56:56 +00004138 // Add the names of overloadable operators.
4139#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4140 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004141 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004142#include "clang/Basic/OperatorKinds.def"
4143
4144 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004145 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004146 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004147 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4148 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004149
4150 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004151 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004152 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004153
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004154 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004155 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004156 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004157}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004158
Douglas Gregor0133f522010-08-28 00:00:50 +00004159void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004160 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004161 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004162 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004163 CXXConstructorDecl *Constructor
4164 = static_cast<CXXConstructorDecl *>(ConstructorD);
4165 if (!Constructor)
4166 return;
4167
Douglas Gregor218937c2011-02-01 19:23:04 +00004168 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004169 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004170 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004171 Results.EnterNewScope();
4172
4173 // Fill in any already-initialized fields or base classes.
4174 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4175 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4176 for (unsigned I = 0; I != NumInitializers; ++I) {
4177 if (Initializers[I]->isBaseInitializer())
4178 InitializedBases.insert(
4179 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4180 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004181 InitializedFields.insert(cast<FieldDecl>(
4182 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004183 }
4184
4185 // Add completions for base classes.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004186 CodeCompletionBuilder Builder(Results.getAllocator(),
4187 Results.getCodeCompletionTUInfo());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004188 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004189 CXXRecordDecl *ClassDecl = Constructor->getParent();
4190 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4191 BaseEnd = ClassDecl->bases_end();
4192 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004193 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4194 SawLastInitializer
4195 = NumInitializers > 0 &&
4196 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4197 Context.hasSameUnqualifiedType(Base->getType(),
4198 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004199 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004200 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004201
Douglas Gregor218937c2011-02-01 19:23:04 +00004202 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004203 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004204 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004205 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4206 Builder.AddPlaceholderChunk("args");
4207 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4208 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004209 SawLastInitializer? CCP_NextInitializer
4210 : CCP_MemberDeclaration));
4211 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004212 }
4213
4214 // Add completions for virtual base classes.
4215 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4216 BaseEnd = ClassDecl->vbases_end();
4217 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004218 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4219 SawLastInitializer
4220 = NumInitializers > 0 &&
4221 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4222 Context.hasSameUnqualifiedType(Base->getType(),
4223 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004224 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004225 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004226
Douglas Gregor218937c2011-02-01 19:23:04 +00004227 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004228 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004229 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004230 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4231 Builder.AddPlaceholderChunk("args");
4232 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4233 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004234 SawLastInitializer? CCP_NextInitializer
4235 : CCP_MemberDeclaration));
4236 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004237 }
4238
4239 // Add completions for members.
4240 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4241 FieldEnd = ClassDecl->field_end();
4242 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004243 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4244 SawLastInitializer
4245 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004246 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
David Blaikie581deb32012-06-06 20:45:41 +00004247 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004248 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004249 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004250
4251 if (!Field->getDeclName())
4252 continue;
4253
Douglas Gregordae68752011-02-01 22:57:45 +00004254 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004255 Field->getIdentifier()->getName()));
4256 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4257 Builder.AddPlaceholderChunk("args");
4258 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4259 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004260 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004261 : CCP_MemberDeclaration,
Douglas Gregorba103062012-03-27 23:34:16 +00004262 CXCursor_MemberRef,
4263 CXAvailability_Available,
David Blaikie581deb32012-06-06 20:45:41 +00004264 *Field));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004265 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004266 }
4267 Results.ExitScope();
4268
Douglas Gregor52779fb2010-09-23 23:01:17 +00004269 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004270 Results.data(), Results.size());
4271}
4272
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004273/// \brief Determine whether this scope denotes a namespace.
4274static bool isNamespaceScope(Scope *S) {
4275 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4276 if (!DC)
4277 return false;
4278
4279 return DC->isFileContext();
4280}
4281
4282void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4283 bool AfterAmpersand) {
4284 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004285 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004286 CodeCompletionContext::CCC_Other);
4287 Results.EnterNewScope();
4288
4289 // Note what has already been captured.
4290 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4291 bool IncludedThis = false;
4292 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4293 CEnd = Intro.Captures.end();
4294 C != CEnd; ++C) {
4295 if (C->Kind == LCK_This) {
4296 IncludedThis = true;
4297 continue;
4298 }
4299
4300 Known.insert(C->Id);
4301 }
4302
4303 // Look for other capturable variables.
4304 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4305 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4306 D != DEnd; ++D) {
4307 VarDecl *Var = dyn_cast<VarDecl>(*D);
4308 if (!Var ||
4309 !Var->hasLocalStorage() ||
4310 Var->hasAttr<BlocksAttr>())
4311 continue;
4312
4313 if (Known.insert(Var->getIdentifier()))
4314 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4315 }
4316 }
4317
4318 // Add 'this', if it would be valid.
4319 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4320 addThisCompletion(*this, Results);
4321
4322 Results.ExitScope();
4323
4324 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4325 Results.data(), Results.size());
4326}
4327
James Dennetta40f7922012-06-14 03:11:41 +00004328/// Macro that optionally prepends an "@" to the string literal passed in via
4329/// Keyword, depending on whether NeedAt is true or false.
4330#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4331
Douglas Gregorbca403c2010-01-13 23:51:12 +00004332static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004333 ResultBuilder &Results,
4334 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004335 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004336 // Since we have an implementation, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004337 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004338
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004339 CodeCompletionBuilder Builder(Results.getAllocator(),
4340 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004341 if (LangOpts.ObjC2) {
4342 // @dynamic
James Dennetta40f7922012-06-14 03:11:41 +00004343 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004344 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4345 Builder.AddPlaceholderChunk("property");
4346 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004347
4348 // @synthesize
James Dennetta40f7922012-06-14 03:11:41 +00004349 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004350 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4351 Builder.AddPlaceholderChunk("property");
4352 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004353 }
4354}
4355
Douglas Gregorbca403c2010-01-13 23:51:12 +00004356static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004357 ResultBuilder &Results,
4358 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004359 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004360
4361 // Since we have an interface or protocol, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004362 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004363
4364 if (LangOpts.ObjC2) {
4365 // @property
James Dennetta40f7922012-06-14 03:11:41 +00004366 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004367
4368 // @required
James Dennetta40f7922012-06-14 03:11:41 +00004369 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004370
4371 // @optional
James Dennetta40f7922012-06-14 03:11:41 +00004372 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004373 }
4374}
4375
Douglas Gregorbca403c2010-01-13 23:51:12 +00004376static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004377 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004378 CodeCompletionBuilder Builder(Results.getAllocator(),
4379 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004380
4381 // @class name ;
James Dennetta40f7922012-06-14 03:11:41 +00004382 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004383 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4384 Builder.AddPlaceholderChunk("name");
4385 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004386
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004387 if (Results.includeCodePatterns()) {
4388 // @interface name
4389 // FIXME: Could introduce the whole pattern, including superclasses and
4390 // such.
James Dennetta40f7922012-06-14 03:11:41 +00004391 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004392 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4393 Builder.AddPlaceholderChunk("class");
4394 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004395
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004396 // @protocol name
James Dennetta40f7922012-06-14 03:11:41 +00004397 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004398 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4399 Builder.AddPlaceholderChunk("protocol");
4400 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004401
4402 // @implementation name
James Dennetta40f7922012-06-14 03:11:41 +00004403 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004404 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4405 Builder.AddPlaceholderChunk("class");
4406 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004407 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004408
4409 // @compatibility_alias name
James Dennetta40f7922012-06-14 03:11:41 +00004410 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004411 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4412 Builder.AddPlaceholderChunk("alias");
4413 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4414 Builder.AddPlaceholderChunk("class");
4415 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004416}
4417
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004418void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004419 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004420 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004421 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004422 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004423 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004424 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004425 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004426 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004427 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004428 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004429 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004430 HandleCodeCompleteResults(this, CodeCompleter,
4431 CodeCompletionContext::CCC_Other,
4432 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004433}
4434
Douglas Gregorbca403c2010-01-13 23:51:12 +00004435static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004436 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004437 CodeCompletionBuilder Builder(Results.getAllocator(),
4438 Results.getCodeCompletionTUInfo());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004439
4440 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004441 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004442 if (Results.getSema().getLangOpts().CPlusPlus ||
4443 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004444 EncodeType = "const char[]";
Douglas Gregor8ca72082011-10-18 21:20:17 +00004445 Builder.AddResultTypeChunk(EncodeType);
James Dennetta40f7922012-06-14 03:11:41 +00004446 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004447 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4448 Builder.AddPlaceholderChunk("type-name");
4449 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4450 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004451
4452 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004453 Builder.AddResultTypeChunk("Protocol *");
James Dennetta40f7922012-06-14 03:11:41 +00004454 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004455 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4456 Builder.AddPlaceholderChunk("protocol-name");
4457 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4458 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004459
4460 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004461 Builder.AddResultTypeChunk("SEL");
James Dennetta40f7922012-06-14 03:11:41 +00004462 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004463 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4464 Builder.AddPlaceholderChunk("selector");
4465 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4466 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004467
4468 // @"string"
4469 Builder.AddResultTypeChunk("NSString *");
4470 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
4471 Builder.AddPlaceholderChunk("string");
4472 Builder.AddTextChunk("\"");
4473 Results.AddResult(Result(Builder.TakeString()));
4474
Douglas Gregor79615892012-07-17 23:24:47 +00004475 // @[objects, ...]
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004476 Builder.AddResultTypeChunk("NSArray *");
James Dennetta40f7922012-06-14 03:11:41 +00004477 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004478 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004479 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4480 Results.AddResult(Result(Builder.TakeString()));
4481
Douglas Gregor79615892012-07-17 23:24:47 +00004482 // @{key : object, ...}
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004483 Builder.AddResultTypeChunk("NSDictionary *");
James Dennetta40f7922012-06-14 03:11:41 +00004484 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004485 Builder.AddPlaceholderChunk("key");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004486 Builder.AddChunk(CodeCompletionString::CK_Colon);
4487 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4488 Builder.AddPlaceholderChunk("object, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004489 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4490 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004491
Douglas Gregor79615892012-07-17 23:24:47 +00004492 // @(expression)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004493 Builder.AddResultTypeChunk("id");
4494 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004495 Builder.AddPlaceholderChunk("expression");
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004496 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4497 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004498}
4499
Douglas Gregorbca403c2010-01-13 23:51:12 +00004500static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004501 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004502 CodeCompletionBuilder Builder(Results.getAllocator(),
4503 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004504
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004505 if (Results.includeCodePatterns()) {
4506 // @try { statements } @catch ( declaration ) { statements } @finally
4507 // { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004508 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004509 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4510 Builder.AddPlaceholderChunk("statements");
4511 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4512 Builder.AddTextChunk("@catch");
4513 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4514 Builder.AddPlaceholderChunk("parameter");
4515 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4516 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4517 Builder.AddPlaceholderChunk("statements");
4518 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4519 Builder.AddTextChunk("@finally");
4520 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4521 Builder.AddPlaceholderChunk("statements");
4522 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4523 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004524 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004525
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004526 // @throw
James Dennetta40f7922012-06-14 03:11:41 +00004527 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004528 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4529 Builder.AddPlaceholderChunk("expression");
4530 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004531
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004532 if (Results.includeCodePatterns()) {
4533 // @synchronized ( expression ) { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004534 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004535 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4536 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4537 Builder.AddPlaceholderChunk("expression");
4538 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4539 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4540 Builder.AddPlaceholderChunk("statements");
4541 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4542 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004543 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004544}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004545
Douglas Gregorbca403c2010-01-13 23:51:12 +00004546static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004547 ResultBuilder &Results,
4548 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004549 typedef CodeCompletionResult Result;
James Dennetta40f7922012-06-14 03:11:41 +00004550 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
4551 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
4552 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004553 if (LangOpts.ObjC2)
James Dennetta40f7922012-06-14 03:11:41 +00004554 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004555}
4556
4557void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004558 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004559 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004560 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004561 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004562 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004563 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004564 HandleCodeCompleteResults(this, CodeCompleter,
4565 CodeCompletionContext::CCC_Other,
4566 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004567}
4568
4569void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004570 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004571 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004572 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004573 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004574 AddObjCStatementResults(Results, false);
4575 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004576 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004577 HandleCodeCompleteResults(this, CodeCompleter,
4578 CodeCompletionContext::CCC_Other,
4579 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004580}
4581
4582void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004583 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004584 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004585 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004586 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004587 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004588 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004589 HandleCodeCompleteResults(this, CodeCompleter,
4590 CodeCompletionContext::CCC_Other,
4591 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004592}
4593
Douglas Gregor988358f2009-11-19 00:14:45 +00004594/// \brief Determine whether the addition of the given flag to an Objective-C
4595/// property's attributes will cause a conflict.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004596static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregor988358f2009-11-19 00:14:45 +00004597 // Check if we've already added this flag.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004598 if (Attributes & NewFlag)
Douglas Gregor988358f2009-11-19 00:14:45 +00004599 return true;
4600
Bill Wendlingad017fa2012-12-20 19:22:21 +00004601 Attributes |= NewFlag;
Douglas Gregor988358f2009-11-19 00:14:45 +00004602
4603 // Check for collisions with "readonly".
Bill Wendlingad017fa2012-12-20 19:22:21 +00004604 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4605 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregor988358f2009-11-19 00:14:45 +00004606 return true;
4607
Jordan Rosed7403a72012-08-20 20:01:13 +00004608 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004609 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004610 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004611 ObjCDeclSpec::DQ_PR_copy |
Jordan Rosed7403a72012-08-20 20:01:13 +00004612 ObjCDeclSpec::DQ_PR_retain |
4613 ObjCDeclSpec::DQ_PR_strong |
4614 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregor988358f2009-11-19 00:14:45 +00004615 if (AssignCopyRetMask &&
4616 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004617 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004618 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004619 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rosed7403a72012-08-20 20:01:13 +00004620 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
4621 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregor988358f2009-11-19 00:14:45 +00004622 return true;
4623
4624 return false;
4625}
4626
Douglas Gregora93b1082009-11-18 23:08:07 +00004627void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004628 if (!CodeCompleter)
4629 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004630
Bill Wendlingad017fa2012-12-20 19:22:21 +00004631 unsigned Attributes = ODS.getPropertyAttributes();
Steve Naroffece8e712009-10-08 21:55:05 +00004632
Douglas Gregor218937c2011-02-01 19:23:04 +00004633 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004634 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004635 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004636 Results.EnterNewScope();
Bill Wendlingad017fa2012-12-20 19:22:21 +00004637 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004638 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004639 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004640 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004641 if (!ObjCPropertyFlagConflicts(Attributes,
John McCallf85e1932011-06-15 23:02:42 +00004642 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4643 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004644 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004645 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004646 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004647 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004648 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCallf85e1932011-06-15 23:02:42 +00004649 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004650 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004651 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004652 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004653 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004654 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004655 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rosed7403a72012-08-20 20:01:13 +00004656
4657 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall0a7dd782012-08-21 02:47:43 +00004658 if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendlingad017fa2012-12-20 19:22:21 +00004659 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rosed7403a72012-08-20 20:01:13 +00004660 Results.AddResult(CodeCompletionResult("weak"));
4661
Bill Wendlingad017fa2012-12-20 19:22:21 +00004662 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004663 CodeCompletionBuilder Setter(Results.getAllocator(),
4664 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004665 Setter.AddTypedTextChunk("setter");
4666 Setter.AddTextChunk(" = ");
4667 Setter.AddPlaceholderChunk("method");
4668 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004669 }
Bill Wendlingad017fa2012-12-20 19:22:21 +00004670 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004671 CodeCompletionBuilder Getter(Results.getAllocator(),
4672 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004673 Getter.AddTypedTextChunk("getter");
4674 Getter.AddTextChunk(" = ");
4675 Getter.AddPlaceholderChunk("method");
4676 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004677 }
Steve Naroffece8e712009-10-08 21:55:05 +00004678 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004679 HandleCodeCompleteResults(this, CodeCompleter,
4680 CodeCompletionContext::CCC_Other,
4681 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004682}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004683
James Dennettde23c7e2012-06-17 05:33:25 +00004684/// \brief Describes the kind of Objective-C method that we want to find
Douglas Gregor4ad96852009-11-19 07:41:15 +00004685/// via code completion.
4686enum ObjCMethodKind {
Dmitri Gribenko49fdccb2012-06-08 23:13:42 +00004687 MK_Any, ///< Any kind of method, provided it means other specified criteria.
4688 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
4689 MK_OneArgSelector ///< One-argument selector.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004690};
4691
Douglas Gregor458433d2010-08-26 15:07:07 +00004692static bool isAcceptableObjCSelector(Selector Sel,
4693 ObjCMethodKind WantKind,
4694 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004695 unsigned NumSelIdents,
4696 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004697 if (NumSelIdents > Sel.getNumArgs())
4698 return false;
4699
4700 switch (WantKind) {
4701 case MK_Any: break;
4702 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4703 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4704 }
4705
Douglas Gregorcf544262010-11-17 21:36:08 +00004706 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4707 return false;
4708
Douglas Gregor458433d2010-08-26 15:07:07 +00004709 for (unsigned I = 0; I != NumSelIdents; ++I)
4710 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4711 return false;
4712
4713 return true;
4714}
4715
Douglas Gregor4ad96852009-11-19 07:41:15 +00004716static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4717 ObjCMethodKind WantKind,
4718 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004719 unsigned NumSelIdents,
4720 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004721 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004722 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004723}
Douglas Gregord36adf52010-09-16 16:06:31 +00004724
4725namespace {
4726 /// \brief A set of selectors, which is used to avoid introducing multiple
4727 /// completions with the same selector into the result set.
4728 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4729}
4730
Douglas Gregor36ecb042009-11-17 23:22:23 +00004731/// \brief Add all of the Objective-C methods in the given Objective-C
4732/// container to the set of results.
4733///
4734/// The container will be a class, protocol, category, or implementation of
4735/// any of the above. This mether will recurse to include methods from
4736/// the superclasses of classes along with their categories, protocols, and
4737/// implementations.
4738///
4739/// \param Container the container in which we'll look to find methods.
4740///
James Dennetta40f7922012-06-14 03:11:41 +00004741/// \param WantInstanceMethods Whether to add instance methods (only); if
4742/// false, this routine will add factory methods (only).
Douglas Gregor36ecb042009-11-17 23:22:23 +00004743///
4744/// \param CurContext the context in which we're performing the lookup that
4745/// finds methods.
4746///
Douglas Gregorcf544262010-11-17 21:36:08 +00004747/// \param AllowSameLength Whether we allow a method to be added to the list
4748/// when it has the same number of parameters as we have selector identifiers.
4749///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004750/// \param Results the structure into which we'll add results.
4751static void AddObjCMethods(ObjCContainerDecl *Container,
4752 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004753 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004754 IdentifierInfo **SelIdents,
4755 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004756 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004757 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004758 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004759 ResultBuilder &Results,
4760 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004761 typedef CodeCompletionResult Result;
Douglas Gregorb92a4082012-06-12 13:44:08 +00004762 Container = getContainerDef(Container);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004763 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4764 MEnd = Container->meth_end();
4765 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00004766 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004767 // Check whether the selector identifiers we've been given are a
4768 // subset of the identifiers for this particular method.
David Blaikie581deb32012-06-06 20:45:41 +00004769 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004770 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004771 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004772
David Blaikie262bc182012-04-30 02:36:29 +00004773 if (!Selectors.insert(M->getSelector()))
Douglas Gregord36adf52010-09-16 16:06:31 +00004774 continue;
4775
David Blaikie581deb32012-06-06 20:45:41 +00004776 Result R = Result(*M, 0);
Douglas Gregord3c68542009-11-19 01:08:35 +00004777 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004778 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004779 if (!InOriginalClass)
4780 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004781 Results.MaybeAddResult(R, CurContext);
4782 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004783 }
4784
Douglas Gregore396c7b2010-09-16 15:34:59 +00004785 // Visit the protocols of protocols.
4786 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004787 if (Protocol->hasDefinition()) {
4788 const ObjCList<ObjCProtocolDecl> &Protocols
4789 = Protocol->getReferencedProtocols();
4790 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4791 E = Protocols.end();
4792 I != E; ++I)
4793 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4794 NumSelIdents, CurContext, Selectors, AllowSameLength,
4795 Results, false);
4796 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004797 }
4798
Douglas Gregor36ecb042009-11-17 23:22:23 +00004799 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004800 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004801 return;
4802
4803 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004804 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4805 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004806 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004807 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004808 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004809
4810 // Add methods in categories.
Douglas Gregord3297242013-01-16 23:00:23 +00004811 for (ObjCInterfaceDecl::known_categories_iterator
4812 Cat = IFace->known_categories_begin(),
4813 CatEnd = IFace->known_categories_end();
4814 Cat != CatEnd; ++Cat) {
4815 ObjCCategoryDecl *CatDecl = *Cat;
4816
4817 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004818 NumSelIdents, CurContext, Selectors, AllowSameLength,
4819 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004820
4821 // Add a categories protocol methods.
4822 const ObjCList<ObjCProtocolDecl> &Protocols
4823 = CatDecl->getReferencedProtocols();
4824 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4825 E = Protocols.end();
4826 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004827 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004828 NumSelIdents, CurContext, Selectors, AllowSameLength,
4829 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004830
4831 // Add methods in category implementations.
4832 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004833 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004834 NumSelIdents, CurContext, Selectors, AllowSameLength,
4835 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004836 }
4837
4838 // Add methods in superclass.
4839 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004840 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004841 SelIdents, NumSelIdents, CurContext, Selectors,
4842 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004843
4844 // Add methods in our implementation, if any.
4845 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004846 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004847 NumSelIdents, CurContext, Selectors, AllowSameLength,
4848 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004849}
4850
4851
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004852void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004853 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004854 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004855 if (!Class) {
4856 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004857 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004858 Class = Category->getClassInterface();
4859
4860 if (!Class)
4861 return;
4862 }
4863
4864 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004865 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004866 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004867 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004868 Results.EnterNewScope();
4869
Douglas Gregord36adf52010-09-16 16:06:31 +00004870 VisitedSelectorSet Selectors;
4871 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004872 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004873 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004874 HandleCodeCompleteResults(this, CodeCompleter,
4875 CodeCompletionContext::CCC_Other,
4876 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004877}
4878
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004879void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004880 // Try to find the interface where setters might live.
4881 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004882 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004883 if (!Class) {
4884 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004885 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004886 Class = Category->getClassInterface();
4887
4888 if (!Class)
4889 return;
4890 }
4891
4892 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004893 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004894 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004895 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004896 Results.EnterNewScope();
4897
Douglas Gregord36adf52010-09-16 16:06:31 +00004898 VisitedSelectorSet Selectors;
4899 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004900 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004901
4902 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004903 HandleCodeCompleteResults(this, CodeCompleter,
4904 CodeCompletionContext::CCC_Other,
4905 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004906}
4907
Douglas Gregorafc45782011-02-15 22:19:42 +00004908void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4909 bool IsParameter) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004910 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004911 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004912 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004913 Results.EnterNewScope();
4914
4915 // Add context-sensitive, Objective-C parameter-passing keywords.
4916 bool AddedInOut = false;
4917 if ((DS.getObjCDeclQualifier() &
4918 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4919 Results.AddResult("in");
4920 Results.AddResult("inout");
4921 AddedInOut = true;
4922 }
4923 if ((DS.getObjCDeclQualifier() &
4924 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4925 Results.AddResult("out");
4926 if (!AddedInOut)
4927 Results.AddResult("inout");
4928 }
4929 if ((DS.getObjCDeclQualifier() &
4930 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4931 ObjCDeclSpec::DQ_Oneway)) == 0) {
4932 Results.AddResult("bycopy");
4933 Results.AddResult("byref");
4934 Results.AddResult("oneway");
4935 }
4936
Douglas Gregorafc45782011-02-15 22:19:42 +00004937 // If we're completing the return type of an Objective-C method and the
4938 // identifier IBAction refers to a macro, provide a completion item for
4939 // an action, e.g.,
4940 // IBAction)<#selector#>:(id)sender
4941 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4942 Context.Idents.get("IBAction").hasMacroDefinition()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004943 CodeCompletionBuilder Builder(Results.getAllocator(),
4944 Results.getCodeCompletionTUInfo(),
4945 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorafc45782011-02-15 22:19:42 +00004946 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004947 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004948 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004949 Builder.AddChunk(CodeCompletionString::CK_Colon);
4950 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004951 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004952 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004953 Builder.AddTextChunk("sender");
4954 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4955 }
4956
Douglas Gregord32b0222010-08-24 01:06:58 +00004957 // Add various builtin type names and specifiers.
4958 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4959 Results.ExitScope();
4960
4961 // Add the various type names
4962 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4963 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4964 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4965 CodeCompleter->includeGlobals());
4966
4967 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00004968 AddMacroResults(PP, Results, false);
Douglas Gregord32b0222010-08-24 01:06:58 +00004969
4970 HandleCodeCompleteResults(this, CodeCompleter,
4971 CodeCompletionContext::CCC_Type,
4972 Results.data(), Results.size());
4973}
4974
Douglas Gregor22f56992010-04-06 19:22:33 +00004975/// \brief When we have an expression with type "id", we may assume
4976/// that it has some more-specific class type based on knowledge of
4977/// common uses of Objective-C. This routine returns that class type,
4978/// or NULL if no better result could be determined.
4979static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004980 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004981 if (!Msg)
4982 return 0;
4983
4984 Selector Sel = Msg->getSelector();
4985 if (Sel.isNull())
4986 return 0;
4987
4988 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4989 if (!Id)
4990 return 0;
4991
4992 ObjCMethodDecl *Method = Msg->getMethodDecl();
4993 if (!Method)
4994 return 0;
4995
4996 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004997 ObjCInterfaceDecl *IFace = 0;
4998 switch (Msg->getReceiverKind()) {
4999 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00005000 if (const ObjCObjectType *ObjType
5001 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5002 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00005003 break;
5004
5005 case ObjCMessageExpr::Instance: {
5006 QualType T = Msg->getInstanceReceiver()->getType();
5007 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5008 IFace = Ptr->getInterfaceDecl();
5009 break;
5010 }
5011
5012 case ObjCMessageExpr::SuperInstance:
5013 case ObjCMessageExpr::SuperClass:
5014 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00005015 }
5016
5017 if (!IFace)
5018 return 0;
5019
5020 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5021 if (Method->isInstanceMethod())
5022 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5023 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00005024 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00005025 .Case("autorelease", IFace)
5026 .Case("copy", IFace)
5027 .Case("copyWithZone", IFace)
5028 .Case("mutableCopy", IFace)
5029 .Case("mutableCopyWithZone", IFace)
5030 .Case("awakeFromCoder", IFace)
5031 .Case("replacementObjectFromCoder", IFace)
5032 .Case("class", IFace)
5033 .Case("classForCoder", IFace)
5034 .Case("superclass", Super)
5035 .Default(0);
5036
5037 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5038 .Case("new", IFace)
5039 .Case("alloc", IFace)
5040 .Case("allocWithZone", IFace)
5041 .Case("class", IFace)
5042 .Case("superclass", Super)
5043 .Default(0);
5044}
5045
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005046// Add a special completion for a message send to "super", which fills in the
5047// most likely case of forwarding all of our arguments to the superclass
5048// function.
5049///
5050/// \param S The semantic analysis object.
5051///
Dmitri Gribenko70517ca2012-08-23 17:58:28 +00005052/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005053/// the "super" keyword. Otherwise, we just need to provide the arguments.
5054///
5055/// \param SelIdents The identifiers in the selector that have already been
5056/// provided as arguments for a send to "super".
5057///
5058/// \param NumSelIdents The number of identifiers in \p SelIdents.
5059///
5060/// \param Results The set of results to augment.
5061///
5062/// \returns the Objective-C method declaration that would be invoked by
5063/// this "super" completion. If NULL, no completion was added.
5064static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
5065 IdentifierInfo **SelIdents,
5066 unsigned NumSelIdents,
5067 ResultBuilder &Results) {
5068 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5069 if (!CurMethod)
5070 return 0;
5071
5072 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5073 if (!Class)
5074 return 0;
5075
5076 // Try to find a superclass method with the same selector.
5077 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00005078 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5079 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005080 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5081 CurMethod->isInstanceMethod());
5082
Douglas Gregor78bcd912011-02-16 00:51:18 +00005083 // Check in categories or class extensions.
5084 if (!SuperMethod) {
Douglas Gregord3297242013-01-16 23:00:23 +00005085 for (ObjCInterfaceDecl::known_categories_iterator
5086 Cat = Class->known_categories_begin(),
5087 CatEnd = Class->known_categories_end();
5088 Cat != CatEnd; ++Cat) {
5089 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregor78bcd912011-02-16 00:51:18 +00005090 CurMethod->isInstanceMethod())))
5091 break;
Douglas Gregord3297242013-01-16 23:00:23 +00005092 }
Douglas Gregor78bcd912011-02-16 00:51:18 +00005093 }
5094 }
5095
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005096 if (!SuperMethod)
5097 return 0;
5098
5099 // Check whether the superclass method has the same signature.
5100 if (CurMethod->param_size() != SuperMethod->param_size() ||
5101 CurMethod->isVariadic() != SuperMethod->isVariadic())
5102 return 0;
5103
5104 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5105 CurPEnd = CurMethod->param_end(),
5106 SuperP = SuperMethod->param_begin();
5107 CurP != CurPEnd; ++CurP, ++SuperP) {
5108 // Make sure the parameter types are compatible.
5109 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5110 (*SuperP)->getType()))
5111 return 0;
5112
5113 // Make sure we have a parameter name to forward!
5114 if (!(*CurP)->getIdentifier())
5115 return 0;
5116 }
5117
5118 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005119 CodeCompletionBuilder Builder(Results.getAllocator(),
5120 Results.getCodeCompletionTUInfo());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005121
5122 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005123 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5124 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005125
5126 // If we need the "super" keyword, add it (plus some spacing).
5127 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005128 Builder.AddTypedTextChunk("super");
5129 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005130 }
5131
5132 Selector Sel = CurMethod->getSelector();
5133 if (Sel.isUnarySelector()) {
5134 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005135 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005136 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005137 else
Douglas Gregordae68752011-02-01 22:57:45 +00005138 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005139 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005140 } else {
5141 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5142 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5143 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005144 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005145
5146 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005147 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005148 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005149 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005150 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005151 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005152 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005153 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005154 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005155 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005156 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005157 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005158 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005159 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005160 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005161 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005162 }
5163 }
5164 }
5165
Douglas Gregorba103062012-03-27 23:34:16 +00005166 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5167 CCP_SuperCompletion));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005168 return SuperMethod;
5169}
5170
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005171void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005172 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005173 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005174 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005175 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith80ad52f2013-01-02 11:42:31 +00005176 getLangOpts().CPlusPlus11
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005177 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5178 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005179
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005180 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5181 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005182 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5183 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005184
5185 // If we are in an Objective-C method inside a class that has a superclass,
5186 // add "super" as an option.
5187 if (ObjCMethodDecl *Method = getCurMethodDecl())
5188 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005189 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005190 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005191
5192 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5193 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005194
Richard Smith80ad52f2013-01-02 11:42:31 +00005195 if (getLangOpts().CPlusPlus11)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005196 addThisCompletion(*this, Results);
5197
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005198 Results.ExitScope();
5199
5200 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00005201 AddMacroResults(PP, Results, false);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005202 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005203 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005204
5205}
5206
Douglas Gregor2725ca82010-04-21 19:57:20 +00005207void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5208 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005209 unsigned NumSelIdents,
5210 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005211 ObjCInterfaceDecl *CDecl = 0;
5212 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5213 // Figure out which interface we're in.
5214 CDecl = CurMethod->getClassInterface();
5215 if (!CDecl)
5216 return;
5217
5218 // Find the superclass of this class.
5219 CDecl = CDecl->getSuperClass();
5220 if (!CDecl)
5221 return;
5222
5223 if (CurMethod->isInstanceMethod()) {
5224 // We are inside an instance method, which means that the message
5225 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005226 // current object.
5227 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005228 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005229 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005230 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005231 }
5232
5233 // Fall through to send to the superclass in CDecl.
5234 } else {
5235 // "super" may be the name of a type or variable. Figure out which
5236 // it is.
5237 IdentifierInfo *Super = &Context.Idents.get("super");
5238 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5239 LookupOrdinaryName);
5240 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5241 // "super" names an interface. Use it.
5242 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005243 if (const ObjCObjectType *Iface
5244 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5245 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005246 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5247 // "super" names an unresolved type; we can't be more specific.
5248 } else {
5249 // Assume that "super" names some kind of value and parse that way.
5250 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005251 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005252 UnqualifiedId id;
5253 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005254 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5255 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005256 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005257 SelIdents, NumSelIdents,
5258 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005259 }
5260
5261 // Fall through
5262 }
5263
John McCallb3d87482010-08-24 05:47:05 +00005264 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005265 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005266 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005267 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005268 NumSelIdents, AtArgumentExpression,
5269 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005270}
5271
Douglas Gregorb9d77572010-09-21 00:03:25 +00005272/// \brief Given a set of code-completion results for the argument of a message
5273/// send, determine the preferred type (if any) for that argument expression.
5274static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5275 unsigned NumSelIdents) {
5276 typedef CodeCompletionResult Result;
5277 ASTContext &Context = Results.getSema().Context;
5278
5279 QualType PreferredType;
5280 unsigned BestPriority = CCP_Unlikely * 2;
5281 Result *ResultsData = Results.data();
5282 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5283 Result &R = ResultsData[I];
5284 if (R.Kind == Result::RK_Declaration &&
5285 isa<ObjCMethodDecl>(R.Declaration)) {
5286 if (R.Priority <= BestPriority) {
5287 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5288 if (NumSelIdents <= Method->param_size()) {
5289 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5290 ->getType();
5291 if (R.Priority < BestPriority || PreferredType.isNull()) {
5292 BestPriority = R.Priority;
5293 PreferredType = MyPreferredType;
5294 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5295 MyPreferredType)) {
5296 PreferredType = QualType();
5297 }
5298 }
5299 }
5300 }
5301 }
5302
5303 return PreferredType;
5304}
5305
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005306static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5307 ParsedType Receiver,
5308 IdentifierInfo **SelIdents,
5309 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005310 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005311 bool IsSuper,
5312 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005313 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005314 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005315
Douglas Gregor24a069f2009-11-17 17:59:40 +00005316 // If the given name refers to an interface type, retrieve the
5317 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005318 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005319 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005320 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005321 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5322 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005323 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005324
Douglas Gregor36ecb042009-11-17 23:22:23 +00005325 // Add all of the factory methods in this Objective-C class, its protocols,
5326 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005327 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005328
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005329 // If this is a send-to-super, try to add the special "super" send
5330 // completion.
5331 if (IsSuper) {
5332 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005333 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5334 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005335 Results.Ignore(SuperMethod);
5336 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005337
Douglas Gregor265f7492010-08-27 15:29:55 +00005338 // If we're inside an Objective-C method definition, prefer its selector to
5339 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005340 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005341 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005342
Douglas Gregord36adf52010-09-16 16:06:31 +00005343 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005344 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005345 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005346 SemaRef.CurContext, Selectors, AtArgumentExpression,
5347 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005348 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005349 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005350
Douglas Gregor719770d2010-04-06 17:30:22 +00005351 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005352 // pool from the AST file.
Axel Naumann0ec56b72012-10-18 19:05:02 +00005353 if (SemaRef.getExternalSource()) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005354 for (uint32_t I = 0,
Axel Naumann0ec56b72012-10-18 19:05:02 +00005355 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005356 I != N; ++I) {
Axel Naumann0ec56b72012-10-18 19:05:02 +00005357 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005358 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005359 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005360
5361 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005362 }
5363 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005364
5365 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5366 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005367 M != MEnd; ++M) {
5368 for (ObjCMethodList *MethList = &M->second.second;
5369 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005370 MethList = MethList->Next) {
5371 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5372 NumSelIdents))
5373 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005374
Douglas Gregor13438f92010-04-06 16:40:00 +00005375 Result R(MethList->Method, 0);
5376 R.StartParameter = NumSelIdents;
5377 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005378 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005379 }
5380 }
5381 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005382
5383 Results.ExitScope();
5384}
Douglas Gregor13438f92010-04-06 16:40:00 +00005385
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005386void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5387 IdentifierInfo **SelIdents,
5388 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005389 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005390 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005391
5392 QualType T = this->GetTypeFromParser(Receiver);
5393
Douglas Gregor218937c2011-02-01 19:23:04 +00005394 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005395 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005396 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005397 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005398
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005399 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5400 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005401
5402 // If we're actually at the argument expression (rather than prior to the
5403 // selector), we're actually performing code completion for an expression.
5404 // Determine whether we have a single, best method. If so, we can
5405 // code-complete the expression using the corresponding parameter type as
5406 // our preferred type, improving completion results.
5407 if (AtArgumentExpression) {
5408 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005409 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005410 if (PreferredType.isNull())
5411 CodeCompleteOrdinaryName(S, PCC_Expression);
5412 else
5413 CodeCompleteExpression(S, PreferredType);
5414 return;
5415 }
5416
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005417 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005418 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005419 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005420}
5421
Richard Trieuf81e5a92011-09-09 02:00:50 +00005422void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005423 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005424 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005425 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005426 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005427 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005428
5429 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005430
Douglas Gregor36ecb042009-11-17 23:22:23 +00005431 // If necessary, apply function/array conversion to the receiver.
5432 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005433 if (RecExpr) {
5434 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5435 if (Conv.isInvalid()) // conversion failed. bail.
5436 return;
5437 RecExpr = Conv.take();
5438 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005439 QualType ReceiverType = RecExpr? RecExpr->getType()
5440 : Super? Context.getObjCObjectPointerType(
5441 Context.getObjCInterfaceType(Super))
5442 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005443
Douglas Gregorda892642010-11-08 21:12:30 +00005444 // If we're messaging an expression with type "id" or "Class", check
5445 // whether we know something special about the receiver that allows
5446 // us to assume a more-specific receiver type.
5447 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5448 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5449 if (ReceiverType->isObjCClassType())
5450 return CodeCompleteObjCClassMessage(S,
5451 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5452 SelIdents, NumSelIdents,
5453 AtArgumentExpression, Super);
5454
5455 ReceiverType = Context.getObjCObjectPointerType(
5456 Context.getObjCInterfaceType(IFace));
5457 }
5458
Douglas Gregor36ecb042009-11-17 23:22:23 +00005459 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005460 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005461 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005462 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005463 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005464
Douglas Gregor36ecb042009-11-17 23:22:23 +00005465 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005466
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005467 // If this is a send-to-super, try to add the special "super" send
5468 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005469 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005470 if (ObjCMethodDecl *SuperMethod
5471 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5472 Results))
5473 Results.Ignore(SuperMethod);
5474 }
5475
Douglas Gregor265f7492010-08-27 15:29:55 +00005476 // If we're inside an Objective-C method definition, prefer its selector to
5477 // others.
5478 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5479 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005480
Douglas Gregord36adf52010-09-16 16:06:31 +00005481 // Keep track of the selectors we've already added.
5482 VisitedSelectorSet Selectors;
5483
Douglas Gregorf74a4192009-11-18 00:06:18 +00005484 // Handle messages to Class. This really isn't a message to an instance
5485 // method, so we treat it the same way we would treat a message send to a
5486 // class method.
5487 if (ReceiverType->isObjCClassType() ||
5488 ReceiverType->isObjCQualifiedClassType()) {
5489 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5490 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005491 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005492 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005493 }
5494 }
5495 // Handle messages to a qualified ID ("id<foo>").
5496 else if (const ObjCObjectPointerType *QualID
5497 = ReceiverType->getAsObjCQualifiedIdType()) {
5498 // Search protocols for instance methods.
5499 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5500 E = QualID->qual_end();
5501 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005502 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005503 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005504 }
5505 // Handle messages to a pointer to interface type.
5506 else if (const ObjCObjectPointerType *IFacePtr
5507 = ReceiverType->getAsObjCInterfacePointerType()) {
5508 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005509 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005510 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5511 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005512
5513 // Search protocols for instance methods.
5514 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5515 E = IFacePtr->qual_end();
5516 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005517 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005518 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005519 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005520 // Handle messages to "id".
5521 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005522 // We're messaging "id", so provide all instance methods we know
5523 // about as code-completion results.
5524
5525 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005526 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005527 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005528 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5529 I != N; ++I) {
5530 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005531 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005532 continue;
5533
Sebastian Redldb9d2142010-08-02 23:18:59 +00005534 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005535 }
5536 }
5537
Sebastian Redldb9d2142010-08-02 23:18:59 +00005538 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5539 MEnd = MethodPool.end();
5540 M != MEnd; ++M) {
5541 for (ObjCMethodList *MethList = &M->second.first;
5542 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005543 MethList = MethList->Next) {
5544 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5545 NumSelIdents))
5546 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005547
5548 if (!Selectors.insert(MethList->Method->getSelector()))
5549 continue;
5550
Douglas Gregor13438f92010-04-06 16:40:00 +00005551 Result R(MethList->Method, 0);
5552 R.StartParameter = NumSelIdents;
5553 R.AllParametersAreInformative = false;
5554 Results.MaybeAddResult(R, CurContext);
5555 }
5556 }
5557 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005558 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005559
5560
5561 // If we're actually at the argument expression (rather than prior to the
5562 // selector), we're actually performing code completion for an expression.
5563 // Determine whether we have a single, best method. If so, we can
5564 // code-complete the expression using the corresponding parameter type as
5565 // our preferred type, improving completion results.
5566 if (AtArgumentExpression) {
5567 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5568 NumSelIdents);
5569 if (PreferredType.isNull())
5570 CodeCompleteOrdinaryName(S, PCC_Expression);
5571 else
5572 CodeCompleteExpression(S, PreferredType);
5573 return;
5574 }
5575
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005576 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005577 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005578 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005579}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005580
Douglas Gregorfb629412010-08-23 21:17:50 +00005581void Sema::CodeCompleteObjCForCollection(Scope *S,
5582 DeclGroupPtrTy IterationVar) {
5583 CodeCompleteExpressionData Data;
5584 Data.ObjCCollection = true;
5585
5586 if (IterationVar.getAsOpaquePtr()) {
5587 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5588 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5589 if (*I)
5590 Data.IgnoreDecls.push_back(*I);
5591 }
5592 }
5593
5594 CodeCompleteExpression(S, Data);
5595}
5596
Douglas Gregor458433d2010-08-26 15:07:07 +00005597void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5598 unsigned NumSelIdents) {
5599 // If we have an external source, load the entire class method
5600 // pool from the AST file.
5601 if (ExternalSource) {
5602 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5603 I != N; ++I) {
5604 Selector Sel = ExternalSource->GetExternalSelector(I);
5605 if (Sel.isNull() || MethodPool.count(Sel))
5606 continue;
5607
5608 ReadMethodPool(Sel);
5609 }
5610 }
5611
Douglas Gregor218937c2011-02-01 19:23:04 +00005612 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005613 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005614 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005615 Results.EnterNewScope();
5616 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5617 MEnd = MethodPool.end();
5618 M != MEnd; ++M) {
5619
5620 Selector Sel = M->first;
5621 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5622 continue;
5623
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005624 CodeCompletionBuilder Builder(Results.getAllocator(),
5625 Results.getCodeCompletionTUInfo());
Douglas Gregor458433d2010-08-26 15:07:07 +00005626 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005627 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005628 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005629 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005630 continue;
5631 }
5632
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005633 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005634 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005635 if (I == NumSelIdents) {
5636 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005637 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005638 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005639 Accumulator.clear();
5640 }
5641 }
5642
Benjamin Kramera0651c52011-07-26 16:59:25 +00005643 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005644 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005645 }
Douglas Gregordae68752011-02-01 22:57:45 +00005646 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005647 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005648 }
5649 Results.ExitScope();
5650
5651 HandleCodeCompleteResults(this, CodeCompleter,
5652 CodeCompletionContext::CCC_SelectorName,
5653 Results.data(), Results.size());
5654}
5655
Douglas Gregor55385fe2009-11-18 04:19:12 +00005656/// \brief Add all of the protocol declarations that we find in the given
5657/// (translation unit) context.
5658static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005659 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005660 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005661 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005662
5663 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5664 DEnd = Ctx->decls_end();
5665 D != DEnd; ++D) {
5666 // Record any protocols we find.
5667 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005668 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005669 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005670 }
5671}
5672
5673void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5674 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005675 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005676 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005677 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005678
Douglas Gregor70c23352010-12-09 21:44:02 +00005679 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5680 Results.EnterNewScope();
5681
5682 // Tell the result set to ignore all of the protocols we have
5683 // already seen.
5684 // FIXME: This doesn't work when caching code-completion results.
5685 for (unsigned I = 0; I != NumProtocols; ++I)
5686 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5687 Protocols[I].second))
5688 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005689
Douglas Gregor70c23352010-12-09 21:44:02 +00005690 // Add all protocols.
5691 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5692 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005693
Douglas Gregor70c23352010-12-09 21:44:02 +00005694 Results.ExitScope();
5695 }
5696
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005697 HandleCodeCompleteResults(this, CodeCompleter,
5698 CodeCompletionContext::CCC_ObjCProtocolName,
5699 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005700}
5701
5702void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005703 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005704 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005705 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005706
Douglas Gregor70c23352010-12-09 21:44:02 +00005707 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5708 Results.EnterNewScope();
5709
5710 // Add all protocols.
5711 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5712 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005713
Douglas Gregor70c23352010-12-09 21:44:02 +00005714 Results.ExitScope();
5715 }
5716
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005717 HandleCodeCompleteResults(this, CodeCompleter,
5718 CodeCompletionContext::CCC_ObjCProtocolName,
5719 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005720}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005721
5722/// \brief Add all of the Objective-C interface declarations that we find in
5723/// the given (translation unit) context.
5724static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5725 bool OnlyForwardDeclarations,
5726 bool OnlyUnimplemented,
5727 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005728 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005729
5730 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5731 DEnd = Ctx->decls_end();
5732 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005733 // Record any interfaces we find.
5734 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005735 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005736 (!OnlyUnimplemented || !Class->getImplementation()))
5737 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005738 }
5739}
5740
5741void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005742 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005743 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005744 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005745 Results.EnterNewScope();
5746
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005747 if (CodeCompleter->includeGlobals()) {
5748 // Add all classes.
5749 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5750 false, Results);
5751 }
5752
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005753 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005754
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005755 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005756 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005757 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005758}
5759
Douglas Gregorc83c6872010-04-15 22:33:43 +00005760void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5761 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005762 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005763 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005764 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005765 Results.EnterNewScope();
5766
5767 // Make sure that we ignore the class we're currently defining.
5768 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005769 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005770 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005771 Results.Ignore(CurClass);
5772
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005773 if (CodeCompleter->includeGlobals()) {
5774 // Add all classes.
5775 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5776 false, Results);
5777 }
5778
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005779 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005780
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005781 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005782 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005783 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005784}
5785
5786void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005787 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005788 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005789 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005790 Results.EnterNewScope();
5791
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005792 if (CodeCompleter->includeGlobals()) {
5793 // Add all unimplemented classes.
5794 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5795 true, Results);
5796 }
5797
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005798 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005799
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005800 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005801 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005802 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005803}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005804
5805void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005806 IdentifierInfo *ClassName,
5807 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005808 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005809
Douglas Gregor218937c2011-02-01 19:23:04 +00005810 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005811 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005812 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005813
5814 // Ignore any categories we find that have already been implemented by this
5815 // interface.
5816 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5817 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005818 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregord3297242013-01-16 23:00:23 +00005819 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
5820 for (ObjCInterfaceDecl::visible_categories_iterator
5821 Cat = Class->visible_categories_begin(),
5822 CatEnd = Class->visible_categories_end();
5823 Cat != CatEnd; ++Cat) {
5824 CategoryNames.insert(Cat->getIdentifier());
5825 }
5826 }
5827
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005828 // Add all of the categories we know about.
5829 Results.EnterNewScope();
5830 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5831 for (DeclContext::decl_iterator D = TU->decls_begin(),
5832 DEnd = TU->decls_end();
5833 D != DEnd; ++D)
5834 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5835 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005836 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005837 Results.ExitScope();
5838
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005839 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005840 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005841 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005842}
5843
5844void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005845 IdentifierInfo *ClassName,
5846 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005847 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005848
5849 // Find the corresponding interface. If we couldn't find the interface, the
5850 // program itself is ill-formed. However, we'll try to be helpful still by
5851 // providing the list of all of the categories we know about.
5852 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005853 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005854 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5855 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005856 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005857
Douglas Gregor218937c2011-02-01 19:23:04 +00005858 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005859 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005860 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005861
5862 // Add all of the categories that have have corresponding interface
5863 // declarations in this class and any of its superclasses, except for
5864 // already-implemented categories in the class itself.
5865 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5866 Results.EnterNewScope();
5867 bool IgnoreImplemented = true;
5868 while (Class) {
Douglas Gregord3297242013-01-16 23:00:23 +00005869 for (ObjCInterfaceDecl::visible_categories_iterator
5870 Cat = Class->visible_categories_begin(),
5871 CatEnd = Class->visible_categories_end();
5872 Cat != CatEnd; ++Cat) {
5873 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
5874 CategoryNames.insert(Cat->getIdentifier()))
5875 Results.AddResult(Result(*Cat, 0), CurContext, 0, false);
5876 }
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005877
5878 Class = Class->getSuperClass();
5879 IgnoreImplemented = false;
5880 }
5881 Results.ExitScope();
5882
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005883 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005884 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005885 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005886}
Douglas Gregor322328b2009-11-18 22:32:06 +00005887
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005888void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005889 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005890 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005891 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005892
5893 // Figure out where this @synthesize lives.
5894 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005895 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005896 if (!Container ||
5897 (!isa<ObjCImplementationDecl>(Container) &&
5898 !isa<ObjCCategoryImplDecl>(Container)))
5899 return;
5900
5901 // Ignore any properties that have already been implemented.
Douglas Gregorb92a4082012-06-12 13:44:08 +00005902 Container = getContainerDef(Container);
5903 for (DeclContext::decl_iterator D = Container->decls_begin(),
Douglas Gregor322328b2009-11-18 22:32:06 +00005904 DEnd = Container->decls_end();
5905 D != DEnd; ++D)
5906 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5907 Results.Ignore(PropertyImpl->getPropertyDecl());
5908
5909 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005910 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005911 Results.EnterNewScope();
5912 if (ObjCImplementationDecl *ClassImpl
5913 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005914 AddObjCProperties(ClassImpl->getClassInterface(), false,
5915 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005916 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005917 else
5918 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005919 false, /*AllowNullaryMethods=*/false, CurContext,
5920 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005921 Results.ExitScope();
5922
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005923 HandleCodeCompleteResults(this, CodeCompleter,
5924 CodeCompletionContext::CCC_Other,
5925 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005926}
5927
5928void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005929 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005930 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005931 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005932 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005933 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005934
5935 // Figure out where this @synthesize lives.
5936 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005937 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005938 if (!Container ||
5939 (!isa<ObjCImplementationDecl>(Container) &&
5940 !isa<ObjCCategoryImplDecl>(Container)))
5941 return;
5942
5943 // Figure out which interface we're looking into.
5944 ObjCInterfaceDecl *Class = 0;
5945 if (ObjCImplementationDecl *ClassImpl
5946 = dyn_cast<ObjCImplementationDecl>(Container))
5947 Class = ClassImpl->getClassInterface();
5948 else
5949 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5950 ->getClassInterface();
5951
Douglas Gregore8426052011-04-18 14:40:46 +00005952 // Determine the type of the property we're synthesizing.
5953 QualType PropertyType = Context.getObjCIdType();
5954 if (Class) {
5955 if (ObjCPropertyDecl *Property
5956 = Class->FindPropertyDeclaration(PropertyName)) {
5957 PropertyType
5958 = Property->getType().getNonReferenceType().getUnqualifiedType();
5959
5960 // Give preference to ivars
5961 Results.setPreferredType(PropertyType);
5962 }
5963 }
5964
Douglas Gregor322328b2009-11-18 22:32:06 +00005965 // Add all of the instance variables in this class and its superclasses.
5966 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005967 bool SawSimilarlyNamedIvar = false;
5968 std::string NameWithPrefix;
5969 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005970 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005971 std::string NameWithSuffix = PropertyName->getName().str();
5972 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005973 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005974 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5975 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005976 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5977
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005978 // Determine whether we've seen an ivar with a name similar to the
5979 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005980 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005981 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005982 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005983 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005984
5985 // Reduce the priority of this result by one, to give it a slight
5986 // advantage over other results whose names don't match so closely.
5987 if (Results.size() &&
5988 Results.data()[Results.size() - 1].Kind
5989 == CodeCompletionResult::RK_Declaration &&
5990 Results.data()[Results.size() - 1].Declaration == Ivar)
5991 Results.data()[Results.size() - 1].Priority--;
5992 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005993 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005994 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005995
5996 if (!SawSimilarlyNamedIvar) {
5997 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005998 // an ivar of the appropriate type.
5999 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006000 typedef CodeCompletionResult Result;
6001 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006002 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6003 Priority,CXAvailability_Available);
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006004
Douglas Gregor8987b232011-09-27 23:30:47 +00006005 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00006006 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006007 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006008 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
6009 Results.AddResult(Result(Builder.TakeString(), Priority,
6010 CXCursor_ObjCIvarDecl));
6011 }
6012
Douglas Gregor322328b2009-11-18 22:32:06 +00006013 Results.ExitScope();
6014
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006015 HandleCodeCompleteResults(this, CodeCompleter,
6016 CodeCompletionContext::CCC_Other,
6017 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00006018}
Douglas Gregore8f5a172010-04-07 00:21:17 +00006019
Douglas Gregor408be5a2010-08-25 01:08:01 +00006020// Mapping from selectors to the methods that implement that selector, along
6021// with the "in original class" flag.
6022typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
6023 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006024
6025/// \brief Find all of the methods that reside in the given container
6026/// (and its superclasses, protocols, etc.) that meet the given
6027/// criteria. Insert those methods into the map of known methods,
6028/// indexed by selector so they can be easily found.
6029static void FindImplementableMethods(ASTContext &Context,
6030 ObjCContainerDecl *Container,
6031 bool WantInstanceMethods,
6032 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00006033 KnownMethodsMap &KnownMethods,
6034 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006035 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006036 // Make sure we have a definition; that's what we'll walk.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006037 if (!IFace->hasDefinition())
6038 return;
Douglas Gregorb92a4082012-06-12 13:44:08 +00006039
6040 IFace = IFace->getDefinition();
6041 Container = IFace;
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006042
Douglas Gregore8f5a172010-04-07 00:21:17 +00006043 const ObjCList<ObjCProtocolDecl> &Protocols
6044 = IFace->getReferencedProtocols();
6045 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006046 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006047 I != E; ++I)
6048 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006049 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006050
Douglas Gregorea766182010-10-18 18:21:28 +00006051 // Add methods from any class extensions and categories.
Douglas Gregord3297242013-01-16 23:00:23 +00006052 for (ObjCInterfaceDecl::visible_categories_iterator
6053 Cat = IFace->visible_categories_begin(),
6054 CatEnd = IFace->visible_categories_end();
6055 Cat != CatEnd; ++Cat) {
6056 FindImplementableMethods(Context, *Cat, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006057 KnownMethods, false);
Douglas Gregord3297242013-01-16 23:00:23 +00006058 }
6059
Douglas Gregorea766182010-10-18 18:21:28 +00006060 // Visit the superclass.
6061 if (IFace->getSuperClass())
6062 FindImplementableMethods(Context, IFace->getSuperClass(),
6063 WantInstanceMethods, ReturnType,
6064 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006065 }
6066
6067 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6068 // Recurse into protocols.
6069 const ObjCList<ObjCProtocolDecl> &Protocols
6070 = Category->getReferencedProtocols();
6071 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006072 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006073 I != E; ++I)
6074 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006075 KnownMethods, InOriginalClass);
6076
6077 // If this category is the original class, jump to the interface.
6078 if (InOriginalClass && Category->getClassInterface())
6079 FindImplementableMethods(Context, Category->getClassInterface(),
6080 WantInstanceMethods, ReturnType, KnownMethods,
6081 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006082 }
6083
6084 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006085 // Make sure we have a definition; that's what we'll walk.
6086 if (!Protocol->hasDefinition())
6087 return;
6088 Protocol = Protocol->getDefinition();
6089 Container = Protocol;
6090
6091 // Recurse into protocols.
6092 const ObjCList<ObjCProtocolDecl> &Protocols
6093 = Protocol->getReferencedProtocols();
6094 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6095 E = Protocols.end();
6096 I != E; ++I)
6097 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6098 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006099 }
6100
6101 // Add methods in this container. This operation occurs last because
6102 // we want the methods from this container to override any methods
6103 // we've previously seen with the same selector.
6104 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
6105 MEnd = Container->meth_end();
6106 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00006107 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006108 if (!ReturnType.isNull() &&
David Blaikie262bc182012-04-30 02:36:29 +00006109 !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006110 continue;
6111
David Blaikie581deb32012-06-06 20:45:41 +00006112 KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006113 }
6114 }
6115}
6116
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006117/// \brief Add the parenthesized return or parameter type chunk to a code
6118/// completion string.
6119static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor90f5f472012-04-10 18:35:07 +00006120 unsigned ObjCDeclQuals,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006121 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006122 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006123 CodeCompletionBuilder &Builder) {
6124 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor90f5f472012-04-10 18:35:07 +00006125 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
6126 if (!Quals.empty())
6127 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor8987b232011-09-27 23:30:47 +00006128 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006129 Builder.getAllocator()));
6130 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6131}
6132
6133/// \brief Determine whether the given class is or inherits from a class by
6134/// the given name.
6135static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00006136 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006137 if (!Class)
6138 return false;
6139
6140 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6141 return true;
6142
6143 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6144}
6145
6146/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6147/// Key-Value Observing (KVO).
6148static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6149 bool IsInstanceMethod,
6150 QualType ReturnType,
6151 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006152 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006153 ResultBuilder &Results) {
6154 IdentifierInfo *PropName = Property->getIdentifier();
6155 if (!PropName || PropName->getLength() == 0)
6156 return;
6157
Douglas Gregor8987b232011-09-27 23:30:47 +00006158 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6159
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006160 // Builder that will create each code completion.
6161 typedef CodeCompletionResult Result;
6162 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006163 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006164
6165 // The selector table.
6166 SelectorTable &Selectors = Context.Selectors;
6167
6168 // The property name, copied into the code completion allocation region
6169 // on demand.
6170 struct KeyHolder {
6171 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006172 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006173 const char *CopiedKey;
6174
Chris Lattner5f9e2722011-07-23 10:55:15 +00006175 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006176 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6177
6178 operator const char *() {
6179 if (CopiedKey)
6180 return CopiedKey;
6181
6182 return CopiedKey = Allocator.CopyString(Key);
6183 }
6184 } Key(Allocator, PropName->getName());
6185
6186 // The uppercased name of the property name.
6187 std::string UpperKey = PropName->getName();
6188 if (!UpperKey.empty())
6189 UpperKey[0] = toupper(UpperKey[0]);
6190
6191 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6192 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6193 Property->getType());
6194 bool ReturnTypeMatchesVoid
6195 = ReturnType.isNull() || ReturnType->isVoidType();
6196
6197 // Add the normal accessor -(type)key.
6198 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006199 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006200 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6201 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006202 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6203 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006204
6205 Builder.AddTypedTextChunk(Key);
6206 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6207 CXCursor_ObjCInstanceMethodDecl));
6208 }
6209
6210 // If we have an integral or boolean property (or the user has provided
6211 // an integral or boolean return type), add the accessor -(type)isKey.
6212 if (IsInstanceMethod &&
6213 ((!ReturnType.isNull() &&
6214 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6215 (ReturnType.isNull() &&
6216 (Property->getType()->isIntegerType() ||
6217 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006218 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006219 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006220 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006221 if (ReturnType.isNull()) {
6222 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6223 Builder.AddTextChunk("BOOL");
6224 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6225 }
6226
6227 Builder.AddTypedTextChunk(
6228 Allocator.CopyString(SelectorId->getName()));
6229 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6230 CXCursor_ObjCInstanceMethodDecl));
6231 }
6232 }
6233
6234 // Add the normal mutator.
6235 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6236 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006237 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006238 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006239 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006240 if (ReturnType.isNull()) {
6241 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6242 Builder.AddTextChunk("void");
6243 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6244 }
6245
6246 Builder.AddTypedTextChunk(
6247 Allocator.CopyString(SelectorId->getName()));
6248 Builder.AddTypedTextChunk(":");
Douglas Gregor90f5f472012-04-10 18:35:07 +00006249 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6250 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006251 Builder.AddTextChunk(Key);
6252 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6253 CXCursor_ObjCInstanceMethodDecl));
6254 }
6255 }
6256
6257 // Indexed and unordered accessors
6258 unsigned IndexedGetterPriority = CCP_CodePattern;
6259 unsigned IndexedSetterPriority = CCP_CodePattern;
6260 unsigned UnorderedGetterPriority = CCP_CodePattern;
6261 unsigned UnorderedSetterPriority = CCP_CodePattern;
6262 if (const ObjCObjectPointerType *ObjCPointer
6263 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6264 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6265 // If this interface type is not provably derived from a known
6266 // collection, penalize the corresponding completions.
6267 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6268 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6269 if (!InheritsFromClassNamed(IFace, "NSArray"))
6270 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6271 }
6272
6273 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6274 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6275 if (!InheritsFromClassNamed(IFace, "NSSet"))
6276 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6277 }
6278 }
6279 } else {
6280 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6281 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6282 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6283 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6284 }
6285
6286 // Add -(NSUInteger)countOf<key>
6287 if (IsInstanceMethod &&
6288 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006289 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006290 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006291 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006292 if (ReturnType.isNull()) {
6293 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6294 Builder.AddTextChunk("NSUInteger");
6295 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6296 }
6297
6298 Builder.AddTypedTextChunk(
6299 Allocator.CopyString(SelectorId->getName()));
6300 Results.AddResult(Result(Builder.TakeString(),
6301 std::min(IndexedGetterPriority,
6302 UnorderedGetterPriority),
6303 CXCursor_ObjCInstanceMethodDecl));
6304 }
6305 }
6306
6307 // Indexed getters
6308 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6309 if (IsInstanceMethod &&
6310 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006311 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006312 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006313 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006314 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006315 if (ReturnType.isNull()) {
6316 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6317 Builder.AddTextChunk("id");
6318 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6319 }
6320
6321 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6322 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6323 Builder.AddTextChunk("NSUInteger");
6324 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6325 Builder.AddTextChunk("index");
6326 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6327 CXCursor_ObjCInstanceMethodDecl));
6328 }
6329 }
6330
6331 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6332 if (IsInstanceMethod &&
6333 (ReturnType.isNull() ||
6334 (ReturnType->isObjCObjectPointerType() &&
6335 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6336 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6337 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006338 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006339 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006340 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006341 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006342 if (ReturnType.isNull()) {
6343 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6344 Builder.AddTextChunk("NSArray *");
6345 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6346 }
6347
6348 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6349 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6350 Builder.AddTextChunk("NSIndexSet *");
6351 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6352 Builder.AddTextChunk("indexes");
6353 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6354 CXCursor_ObjCInstanceMethodDecl));
6355 }
6356 }
6357
6358 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6359 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006360 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006361 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006362 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006363 &Context.Idents.get("range")
6364 };
6365
Douglas Gregore74c25c2011-05-04 23:50:46 +00006366 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006367 if (ReturnType.isNull()) {
6368 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6369 Builder.AddTextChunk("void");
6370 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6371 }
6372
6373 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6374 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6375 Builder.AddPlaceholderChunk("object-type");
6376 Builder.AddTextChunk(" **");
6377 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6378 Builder.AddTextChunk("buffer");
6379 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6380 Builder.AddTypedTextChunk("range:");
6381 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6382 Builder.AddTextChunk("NSRange");
6383 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6384 Builder.AddTextChunk("inRange");
6385 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6386 CXCursor_ObjCInstanceMethodDecl));
6387 }
6388 }
6389
6390 // Mutable indexed accessors
6391
6392 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6393 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006394 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006395 IdentifierInfo *SelectorIds[2] = {
6396 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006397 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006398 };
6399
Douglas Gregore74c25c2011-05-04 23:50:46 +00006400 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006401 if (ReturnType.isNull()) {
6402 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6403 Builder.AddTextChunk("void");
6404 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6405 }
6406
6407 Builder.AddTypedTextChunk("insertObject:");
6408 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6409 Builder.AddPlaceholderChunk("object-type");
6410 Builder.AddTextChunk(" *");
6411 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6412 Builder.AddTextChunk("object");
6413 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6414 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6415 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6416 Builder.AddPlaceholderChunk("NSUInteger");
6417 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6418 Builder.AddTextChunk("index");
6419 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6420 CXCursor_ObjCInstanceMethodDecl));
6421 }
6422 }
6423
6424 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6425 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006426 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006427 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006428 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006429 &Context.Idents.get("atIndexes")
6430 };
6431
Douglas Gregore74c25c2011-05-04 23:50:46 +00006432 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006433 if (ReturnType.isNull()) {
6434 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6435 Builder.AddTextChunk("void");
6436 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6437 }
6438
6439 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6440 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6441 Builder.AddTextChunk("NSArray *");
6442 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6443 Builder.AddTextChunk("array");
6444 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6445 Builder.AddTypedTextChunk("atIndexes:");
6446 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6447 Builder.AddPlaceholderChunk("NSIndexSet *");
6448 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6449 Builder.AddTextChunk("indexes");
6450 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6451 CXCursor_ObjCInstanceMethodDecl));
6452 }
6453 }
6454
6455 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6456 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006457 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006458 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006459 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006460 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006461 if (ReturnType.isNull()) {
6462 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6463 Builder.AddTextChunk("void");
6464 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6465 }
6466
6467 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6468 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6469 Builder.AddTextChunk("NSUInteger");
6470 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6471 Builder.AddTextChunk("index");
6472 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6473 CXCursor_ObjCInstanceMethodDecl));
6474 }
6475 }
6476
6477 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6478 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006479 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006480 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006481 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006482 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006483 if (ReturnType.isNull()) {
6484 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6485 Builder.AddTextChunk("void");
6486 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6487 }
6488
6489 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6490 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6491 Builder.AddTextChunk("NSIndexSet *");
6492 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6493 Builder.AddTextChunk("indexes");
6494 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6495 CXCursor_ObjCInstanceMethodDecl));
6496 }
6497 }
6498
6499 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6500 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006501 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006502 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006503 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006504 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006505 &Context.Idents.get("withObject")
6506 };
6507
Douglas Gregore74c25c2011-05-04 23:50:46 +00006508 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006509 if (ReturnType.isNull()) {
6510 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6511 Builder.AddTextChunk("void");
6512 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6513 }
6514
6515 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6516 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6517 Builder.AddPlaceholderChunk("NSUInteger");
6518 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6519 Builder.AddTextChunk("index");
6520 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6521 Builder.AddTypedTextChunk("withObject:");
6522 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6523 Builder.AddTextChunk("id");
6524 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6525 Builder.AddTextChunk("object");
6526 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6527 CXCursor_ObjCInstanceMethodDecl));
6528 }
6529 }
6530
6531 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6532 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006533 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006534 = (Twine("replace") + UpperKey + "AtIndexes").str();
6535 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006536 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006537 &Context.Idents.get(SelectorName1),
6538 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006539 };
6540
Douglas Gregore74c25c2011-05-04 23:50:46 +00006541 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006542 if (ReturnType.isNull()) {
6543 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6544 Builder.AddTextChunk("void");
6545 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6546 }
6547
6548 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6549 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6550 Builder.AddPlaceholderChunk("NSIndexSet *");
6551 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6552 Builder.AddTextChunk("indexes");
6553 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6554 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6555 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6556 Builder.AddTextChunk("NSArray *");
6557 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6558 Builder.AddTextChunk("array");
6559 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6560 CXCursor_ObjCInstanceMethodDecl));
6561 }
6562 }
6563
6564 // Unordered getters
6565 // - (NSEnumerator *)enumeratorOfKey
6566 if (IsInstanceMethod &&
6567 (ReturnType.isNull() ||
6568 (ReturnType->isObjCObjectPointerType() &&
6569 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6570 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6571 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006572 std::string SelectorName = (Twine("enumeratorOf") + 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.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006575 if (ReturnType.isNull()) {
6576 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6577 Builder.AddTextChunk("NSEnumerator *");
6578 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6579 }
6580
6581 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6582 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6583 CXCursor_ObjCInstanceMethodDecl));
6584 }
6585 }
6586
6587 // - (type *)memberOfKey:(type *)object
6588 if (IsInstanceMethod &&
6589 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006590 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006591 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006592 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006593 if (ReturnType.isNull()) {
6594 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6595 Builder.AddPlaceholderChunk("object-type");
6596 Builder.AddTextChunk(" *");
6597 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6598 }
6599
6600 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6601 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6602 if (ReturnType.isNull()) {
6603 Builder.AddPlaceholderChunk("object-type");
6604 Builder.AddTextChunk(" *");
6605 } else {
6606 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006607 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006608 Builder.getAllocator()));
6609 }
6610 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6611 Builder.AddTextChunk("object");
6612 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6613 CXCursor_ObjCInstanceMethodDecl));
6614 }
6615 }
6616
6617 // Mutable unordered accessors
6618 // - (void)addKeyObject:(type *)object
6619 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006620 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006621 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006622 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006623 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006624 if (ReturnType.isNull()) {
6625 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6626 Builder.AddTextChunk("void");
6627 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6628 }
6629
6630 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6631 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6632 Builder.AddPlaceholderChunk("object-type");
6633 Builder.AddTextChunk(" *");
6634 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6635 Builder.AddTextChunk("object");
6636 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6637 CXCursor_ObjCInstanceMethodDecl));
6638 }
6639 }
6640
6641 // - (void)addKey:(NSSet *)objects
6642 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006643 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006644 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006645 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006646 if (ReturnType.isNull()) {
6647 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6648 Builder.AddTextChunk("void");
6649 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6650 }
6651
6652 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6653 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6654 Builder.AddTextChunk("NSSet *");
6655 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6656 Builder.AddTextChunk("objects");
6657 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6658 CXCursor_ObjCInstanceMethodDecl));
6659 }
6660 }
6661
6662 // - (void)removeKeyObject:(type *)object
6663 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006664 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006665 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006666 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006667 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006668 if (ReturnType.isNull()) {
6669 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6670 Builder.AddTextChunk("void");
6671 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6672 }
6673
6674 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6675 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6676 Builder.AddPlaceholderChunk("object-type");
6677 Builder.AddTextChunk(" *");
6678 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6679 Builder.AddTextChunk("object");
6680 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6681 CXCursor_ObjCInstanceMethodDecl));
6682 }
6683 }
6684
6685 // - (void)removeKey:(NSSet *)objects
6686 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006687 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006688 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006689 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006690 if (ReturnType.isNull()) {
6691 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6692 Builder.AddTextChunk("void");
6693 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6694 }
6695
6696 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6697 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6698 Builder.AddTextChunk("NSSet *");
6699 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6700 Builder.AddTextChunk("objects");
6701 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6702 CXCursor_ObjCInstanceMethodDecl));
6703 }
6704 }
6705
6706 // - (void)intersectKey:(NSSet *)objects
6707 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006708 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006709 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006710 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006711 if (ReturnType.isNull()) {
6712 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6713 Builder.AddTextChunk("void");
6714 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6715 }
6716
6717 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6718 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6719 Builder.AddTextChunk("NSSet *");
6720 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6721 Builder.AddTextChunk("objects");
6722 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6723 CXCursor_ObjCInstanceMethodDecl));
6724 }
6725 }
6726
6727 // Key-Value Observing
6728 // + (NSSet *)keyPathsForValuesAffectingKey
6729 if (!IsInstanceMethod &&
6730 (ReturnType.isNull() ||
6731 (ReturnType->isObjCObjectPointerType() &&
6732 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6733 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6734 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006735 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006736 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006737 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006738 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006739 if (ReturnType.isNull()) {
6740 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6741 Builder.AddTextChunk("NSSet *");
6742 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6743 }
6744
6745 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6746 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006747 CXCursor_ObjCClassMethodDecl));
6748 }
6749 }
6750
6751 // + (BOOL)automaticallyNotifiesObserversForKey
6752 if (!IsInstanceMethod &&
6753 (ReturnType.isNull() ||
6754 ReturnType->isIntegerType() ||
6755 ReturnType->isBooleanType())) {
6756 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006757 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006758 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6759 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6760 if (ReturnType.isNull()) {
6761 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6762 Builder.AddTextChunk("BOOL");
6763 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6764 }
6765
6766 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6767 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6768 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006769 }
6770 }
6771}
6772
Douglas Gregore8f5a172010-04-07 00:21:17 +00006773void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6774 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006775 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006776 // Determine the return type of the method we're declaring, if
6777 // provided.
6778 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006779 Decl *IDecl = 0;
6780 if (CurContext->isObjCContainer()) {
6781 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6782 IDecl = cast<Decl>(OCD);
6783 }
Douglas Gregorea766182010-10-18 18:21:28 +00006784 // Determine where we should start searching for methods.
6785 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006786 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006787 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006788 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6789 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006790 IsInImplementation = true;
6791 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006792 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006793 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006794 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006795 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006796 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006797 }
6798
6799 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006800 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006801 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006802 }
6803
Douglas Gregorea766182010-10-18 18:21:28 +00006804 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006805 HandleCodeCompleteResults(this, CodeCompleter,
6806 CodeCompletionContext::CCC_Other,
6807 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006808 return;
6809 }
6810
6811 // Find all of the methods that we could declare/implement here.
6812 KnownMethodsMap KnownMethods;
6813 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006814 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006815
Douglas Gregore8f5a172010-04-07 00:21:17 +00006816 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006817 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006818 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006819 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006820 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006821 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006822 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006823 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6824 MEnd = KnownMethods.end();
6825 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006826 ObjCMethodDecl *Method = M->second.first;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006827 CodeCompletionBuilder Builder(Results.getAllocator(),
6828 Results.getCodeCompletionTUInfo());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006829
6830 // If the result type was not already provided, add it to the
6831 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006832 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006833 AddObjCPassingTypeChunk(Method->getResultType(),
6834 Method->getObjCDeclQualifier(),
6835 Context, Policy,
6836 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006837
6838 Selector Sel = Method->getSelector();
6839
6840 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006841 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006842 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006843
6844 // Add parameters to the pattern.
6845 unsigned I = 0;
6846 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6847 PEnd = Method->param_end();
6848 P != PEnd; (void)++P, ++I) {
6849 // Add the part of the selector name.
6850 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006851 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006852 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006853 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6854 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006855 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006856 } else
6857 break;
6858
6859 // Add the parameter type.
Douglas Gregor90f5f472012-04-10 18:35:07 +00006860 AddObjCPassingTypeChunk((*P)->getOriginalType(),
6861 (*P)->getObjCDeclQualifier(),
6862 Context, Policy,
Douglas Gregor8987b232011-09-27 23:30:47 +00006863 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006864
6865 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006866 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006867 }
6868
6869 if (Method->isVariadic()) {
6870 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006871 Builder.AddChunk(CodeCompletionString::CK_Comma);
6872 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006873 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006874
Douglas Gregor447107d2010-05-28 00:57:46 +00006875 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006876 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006877 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6878 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6879 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006880 if (!Method->getResultType()->isVoidType()) {
6881 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006882 Builder.AddTextChunk("return");
6883 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6884 Builder.AddPlaceholderChunk("expression");
6885 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006886 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006887 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006888
Douglas Gregor218937c2011-02-01 19:23:04 +00006889 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6890 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006891 }
6892
Douglas Gregor408be5a2010-08-25 01:08:01 +00006893 unsigned Priority = CCP_CodePattern;
6894 if (!M->second.second)
6895 Priority += CCD_InBaseClass;
6896
Douglas Gregorba103062012-03-27 23:34:16 +00006897 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006898 }
6899
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006900 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6901 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006902 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006903 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006904 Containers.push_back(SearchDecl);
6905
Douglas Gregore74c25c2011-05-04 23:50:46 +00006906 VisitedSelectorSet KnownSelectors;
6907 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6908 MEnd = KnownMethods.end();
6909 M != MEnd; ++M)
6910 KnownSelectors.insert(M->first);
6911
6912
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006913 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6914 if (!IFace)
6915 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6916 IFace = Category->getClassInterface();
6917
6918 if (IFace) {
Douglas Gregord3297242013-01-16 23:00:23 +00006919 for (ObjCInterfaceDecl::visible_categories_iterator
6920 Cat = IFace->visible_categories_begin(),
6921 CatEnd = IFace->visible_categories_end();
6922 Cat != CatEnd; ++Cat) {
6923 Containers.push_back(*Cat);
6924 }
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006925 }
6926
6927 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6928 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6929 PEnd = Containers[I]->prop_end();
6930 P != PEnd; ++P) {
David Blaikie581deb32012-06-06 20:45:41 +00006931 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006932 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006933 }
6934 }
6935 }
6936
Douglas Gregore8f5a172010-04-07 00:21:17 +00006937 Results.ExitScope();
6938
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006939 HandleCodeCompleteResults(this, CodeCompleter,
6940 CodeCompletionContext::CCC_Other,
6941 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006942}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006943
6944void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6945 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006946 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006947 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006948 IdentifierInfo **SelIdents,
6949 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006950 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006951 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006952 if (ExternalSource) {
6953 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6954 I != N; ++I) {
6955 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006956 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006957 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006958
6959 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006960 }
6961 }
6962
6963 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006964 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006965 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006966 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006967 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006968
6969 if (ReturnTy)
6970 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006971
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006972 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006973 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6974 MEnd = MethodPool.end();
6975 M != MEnd; ++M) {
6976 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6977 &M->second.second;
6978 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006979 MethList = MethList->Next) {
6980 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6981 NumSelIdents))
6982 continue;
6983
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006984 if (AtParameterName) {
6985 // Suggest parameter names we've seen before.
6986 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6987 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6988 if (Param->getIdentifier()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006989 CodeCompletionBuilder Builder(Results.getAllocator(),
6990 Results.getCodeCompletionTUInfo());
Douglas Gregordae68752011-02-01 22:57:45 +00006991 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006992 Param->getIdentifier()->getName()));
6993 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006994 }
6995 }
6996
6997 continue;
6998 }
6999
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007000 Result R(MethList->Method, 0);
7001 R.StartParameter = NumSelIdents;
7002 R.AllParametersAreInformative = false;
7003 R.DeclaringEntity = true;
7004 Results.MaybeAddResult(R, CurContext);
7005 }
7006 }
7007
7008 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00007009 HandleCodeCompleteResults(this, CodeCompleter,
7010 CodeCompletionContext::CCC_Other,
7011 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007012}
Douglas Gregor87c08a52010-08-13 22:48:40 +00007013
Douglas Gregorf29c5232010-08-24 22:20:20 +00007014void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007015 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007016 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007017 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007018 Results.EnterNewScope();
7019
7020 // #if <condition>
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007021 CodeCompletionBuilder Builder(Results.getAllocator(),
7022 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007023 Builder.AddTypedTextChunk("if");
7024 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7025 Builder.AddPlaceholderChunk("condition");
7026 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007027
7028 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007029 Builder.AddTypedTextChunk("ifdef");
7030 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7031 Builder.AddPlaceholderChunk("macro");
7032 Results.AddResult(Builder.TakeString());
7033
Douglas Gregorf44e8542010-08-24 19:08:16 +00007034 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007035 Builder.AddTypedTextChunk("ifndef");
7036 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7037 Builder.AddPlaceholderChunk("macro");
7038 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007039
7040 if (InConditional) {
7041 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00007042 Builder.AddTypedTextChunk("elif");
7043 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7044 Builder.AddPlaceholderChunk("condition");
7045 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007046
7047 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00007048 Builder.AddTypedTextChunk("else");
7049 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007050
7051 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00007052 Builder.AddTypedTextChunk("endif");
7053 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007054 }
7055
7056 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007057 Builder.AddTypedTextChunk("include");
7058 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7059 Builder.AddTextChunk("\"");
7060 Builder.AddPlaceholderChunk("header");
7061 Builder.AddTextChunk("\"");
7062 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007063
7064 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007065 Builder.AddTypedTextChunk("include");
7066 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7067 Builder.AddTextChunk("<");
7068 Builder.AddPlaceholderChunk("header");
7069 Builder.AddTextChunk(">");
7070 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007071
7072 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007073 Builder.AddTypedTextChunk("define");
7074 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7075 Builder.AddPlaceholderChunk("macro");
7076 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007077
7078 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00007079 Builder.AddTypedTextChunk("define");
7080 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7081 Builder.AddPlaceholderChunk("macro");
7082 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7083 Builder.AddPlaceholderChunk("args");
7084 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7085 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007086
7087 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007088 Builder.AddTypedTextChunk("undef");
7089 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7090 Builder.AddPlaceholderChunk("macro");
7091 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007092
7093 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00007094 Builder.AddTypedTextChunk("line");
7095 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7096 Builder.AddPlaceholderChunk("number");
7097 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007098
7099 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00007100 Builder.AddTypedTextChunk("line");
7101 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7102 Builder.AddPlaceholderChunk("number");
7103 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7104 Builder.AddTextChunk("\"");
7105 Builder.AddPlaceholderChunk("filename");
7106 Builder.AddTextChunk("\"");
7107 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007108
7109 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007110 Builder.AddTypedTextChunk("error");
7111 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7112 Builder.AddPlaceholderChunk("message");
7113 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007114
7115 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00007116 Builder.AddTypedTextChunk("pragma");
7117 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7118 Builder.AddPlaceholderChunk("arguments");
7119 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007120
David Blaikie4e4d0842012-03-11 07:00:24 +00007121 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00007122 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007123 Builder.AddTypedTextChunk("import");
7124 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7125 Builder.AddTextChunk("\"");
7126 Builder.AddPlaceholderChunk("header");
7127 Builder.AddTextChunk("\"");
7128 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007129
7130 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007131 Builder.AddTypedTextChunk("import");
7132 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7133 Builder.AddTextChunk("<");
7134 Builder.AddPlaceholderChunk("header");
7135 Builder.AddTextChunk(">");
7136 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007137 }
7138
7139 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007140 Builder.AddTypedTextChunk("include_next");
7141 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7142 Builder.AddTextChunk("\"");
7143 Builder.AddPlaceholderChunk("header");
7144 Builder.AddTextChunk("\"");
7145 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007146
7147 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007148 Builder.AddTypedTextChunk("include_next");
7149 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7150 Builder.AddTextChunk("<");
7151 Builder.AddPlaceholderChunk("header");
7152 Builder.AddTextChunk(">");
7153 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007154
7155 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007156 Builder.AddTypedTextChunk("warning");
7157 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7158 Builder.AddPlaceholderChunk("message");
7159 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007160
7161 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7162 // completions for them. And __include_macros is a Clang-internal extension
7163 // that we don't want to encourage anyone to use.
7164
7165 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7166 Results.ExitScope();
7167
Douglas Gregorf44e8542010-08-24 19:08:16 +00007168 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00007169 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00007170 Results.data(), Results.size());
7171}
7172
7173void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007174 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007175 S->getFnParent()? Sema::PCC_RecoveryInFunction
7176 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007177}
7178
Douglas Gregorf29c5232010-08-24 22:20:20 +00007179void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007180 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007181 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007182 IsDefinition? CodeCompletionContext::CCC_MacroName
7183 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007184 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7185 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007186 CodeCompletionBuilder Builder(Results.getAllocator(),
7187 Results.getCodeCompletionTUInfo());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007188 Results.EnterNewScope();
7189 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7190 MEnd = PP.macro_end();
7191 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007192 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007193 M->first->getName()));
Argyrios Kyrtzidisc04bb922012-09-27 00:24:09 +00007194 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7195 CCP_CodePattern,
7196 CXCursor_MacroDefinition));
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007197 }
7198 Results.ExitScope();
7199 } else if (IsDefinition) {
7200 // FIXME: Can we detect when the user just wrote an include guard above?
7201 }
7202
Douglas Gregor52779fb2010-09-23 23:01:17 +00007203 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007204 Results.data(), Results.size());
7205}
7206
Douglas Gregorf29c5232010-08-24 22:20:20 +00007207void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007208 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007209 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007210 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007211
7212 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00007213 AddMacroResults(PP, Results, true);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007214
7215 // defined (<macro>)
7216 Results.EnterNewScope();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007217 CodeCompletionBuilder Builder(Results.getAllocator(),
7218 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007219 Builder.AddTypedTextChunk("defined");
7220 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7221 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7222 Builder.AddPlaceholderChunk("macro");
7223 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7224 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007225 Results.ExitScope();
7226
7227 HandleCodeCompleteResults(this, CodeCompleter,
7228 CodeCompletionContext::CCC_PreprocessorExpression,
7229 Results.data(), Results.size());
7230}
7231
7232void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7233 IdentifierInfo *Macro,
7234 MacroInfo *MacroInfo,
7235 unsigned Argument) {
7236 // FIXME: In the future, we could provide "overload" results, much like we
7237 // do for function calls.
7238
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007239 // Now just ignore this. There will be another code-completion callback
7240 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007241}
7242
Douglas Gregor55817af2010-08-25 17:04:25 +00007243void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007244 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007245 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007246 0, 0);
7247}
7248
Douglas Gregordae68752011-02-01 22:57:45 +00007249void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007250 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007251 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007252 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7253 CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007254 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7255 CodeCompletionDeclConsumer Consumer(Builder,
7256 Context.getTranslationUnitDecl());
7257 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7258 Consumer);
7259 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007260
7261 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00007262 AddMacroResults(PP, Builder, true);
Douglas Gregor87c08a52010-08-13 22:48:40 +00007263
7264 Results.clear();
7265 Results.insert(Results.end(),
7266 Builder.data(), Builder.data() + Builder.size());
7267}