blob: b1aead8f026d7553d45161837b6f66ff42aa5dc7 [file] [log] [blame]
Douglas Gregor81b747b2009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the code-completion semantic actions.
11//
12//===----------------------------------------------------------------------===//
John McCall2d887082010-08-25 22:03:47 +000013#include "clang/Sema/SemaInternal.h"
Douglas Gregore737f502010-08-12 20:07:10 +000014#include "clang/Sema/Lookup.h"
John McCall120d63c2010-08-24 20:38:10 +000015#include "clang/Sema/Overload.h"
Douglas Gregor81b747b2009-09-17 21:32:03 +000016#include "clang/Sema/CodeCompleteConsumer.h"
Douglas Gregor719770d2010-04-06 17:30:22 +000017#include "clang/Sema/ExternalSemaSource.h"
John McCall5f1e0942010-08-24 08:50:51 +000018#include "clang/Sema/Scope.h"
John McCall781472f2010-08-25 08:40:02 +000019#include "clang/Sema/ScopeInfo.h"
John McCall7cd088e2010-08-24 07:21:54 +000020#include "clang/AST/DeclObjC.h"
Douglas Gregorb9d0ef72009-09-21 19:57:38 +000021#include "clang/AST/ExprCXX.h"
Douglas Gregor24a069f2009-11-17 17:59:40 +000022#include "clang/AST/ExprObjC.h"
Douglas Gregorc5b2e582012-01-29 18:15:03 +000023#include "clang/Lex/HeaderSearch.h"
Douglas Gregor3f7c7f42009-10-30 16:50:04 +000024#include "clang/Lex/MacroInfo.h"
25#include "clang/Lex/Preprocessor.h"
Douglas Gregord36adf52010-09-16 16:06:31 +000026#include "llvm/ADT/DenseSet.h"
Benjamin Kramer013b3662012-01-30 16:17:39 +000027#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000028#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer8fe83e12012-02-04 13:45:25 +000029#include "llvm/ADT/SmallString.h"
Douglas Gregor6a684032009-09-28 03:51:44 +000030#include "llvm/ADT/StringExtras.h"
Douglas Gregor22f56992010-04-06 19:22:33 +000031#include "llvm/ADT/StringSwitch.h"
Douglas Gregor458433d2010-08-26 15:07:07 +000032#include "llvm/ADT/Twine.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000033#include <list>
34#include <map>
35#include <vector>
Douglas Gregor81b747b2009-09-17 21:32:03 +000036
37using namespace clang;
John McCall781472f2010-08-25 08:40:02 +000038using namespace sema;
Douglas Gregor81b747b2009-09-17 21:32:03 +000039
Douglas Gregor86d9a522009-09-21 16:56:56 +000040namespace {
41 /// \brief A container of code-completion results.
42 class ResultBuilder {
43 public:
44 /// \brief The type of a name-lookup filter, which can be provided to the
45 /// name-lookup routines to specify which declarations should be included in
46 /// the result set (when it returns true) and which declarations should be
47 /// filtered out (returns false).
48 typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
49
John McCall0a2c5e22010-08-25 06:19:51 +000050 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +000051
52 private:
53 /// \brief The actual results we have found.
54 std::vector<Result> Results;
55
56 /// \brief A record of all of the declarations we have found and placed
57 /// into the result set, used to ensure that no declaration ever gets into
58 /// the result set twice.
59 llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
60
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000061 typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
62
63 /// \brief An entry in the shadow map, which is optimized to store
64 /// a single (declaration, index) mapping (the common case) but
65 /// can also store a list of (declaration, index) mappings.
66 class ShadowMapEntry {
Chris Lattner5f9e2722011-07-23 10:55:15 +000067 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000068
69 /// \brief Contains either the solitary NamedDecl * or a vector
70 /// of (declaration, index) pairs.
71 llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
72
73 /// \brief When the entry contains a single declaration, this is
74 /// the index associated with that entry.
75 unsigned SingleDeclIndex;
76
77 public:
78 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
79
80 void Add(NamedDecl *ND, unsigned Index) {
81 if (DeclOrVector.isNull()) {
82 // 0 - > 1 elements: just set the single element information.
83 DeclOrVector = ND;
84 SingleDeclIndex = Index;
85 return;
86 }
87
88 if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
89 // 1 -> 2 elements: create the vector of results and push in the
90 // existing declaration.
91 DeclIndexPairVector *Vec = new DeclIndexPairVector;
92 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
93 DeclOrVector = Vec;
94 }
95
96 // Add the new element to the end of the vector.
97 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
98 DeclIndexPair(ND, Index));
99 }
100
101 void Destroy() {
102 if (DeclIndexPairVector *Vec
103 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
104 delete Vec;
105 DeclOrVector = ((NamedDecl *)0);
106 }
107 }
108
109 // Iteration.
110 class iterator;
111 iterator begin() const;
112 iterator end() const;
113 };
114
Douglas Gregor86d9a522009-09-21 16:56:56 +0000115 /// \brief A mapping from declaration names to the declarations that have
116 /// this name within a particular scope and their index within the list of
117 /// results.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000118 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000119
120 /// \brief The semantic analysis object for which results are being
121 /// produced.
122 Sema &SemaRef;
Douglas Gregor218937c2011-02-01 19:23:04 +0000123
124 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000125 CodeCompletionAllocator &Allocator;
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));
760 for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
761 Ctors.first != Ctors.second; ++Ctors.first) {
762 R.Declaration = *Ctors.first;
763 R.CursorKind = getCursorKindForDecl(R.Declaration);
764 Results.push_back(R);
765 }
766}
767
Douglas Gregore495b7f2010-01-14 00:20:49 +0000768void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
769 assert(!ShadowMaps.empty() && "Must enter into a results scope");
770
771 if (R.Kind != Result::RK_Declaration) {
772 // For non-declaration results, just add the result.
773 Results.push_back(R);
774 return;
775 }
776
777 // Look through using declarations.
778 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
779 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
780 return;
781 }
782
783 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
784 unsigned IDNS = CanonDecl->getIdentifierNamespace();
785
Douglas Gregor45bcd432010-01-14 03:21:49 +0000786 bool AsNestedNameSpecifier = false;
787 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000788 return;
789
Douglas Gregor6f942b22010-09-21 16:06:22 +0000790 // C++ constructors are never found by name lookup.
791 if (isa<CXXConstructorDecl>(R.Declaration))
792 return;
793
Douglas Gregor86d9a522009-09-21 16:56:56 +0000794 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000795 ShadowMapEntry::iterator I, IEnd;
796 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
797 if (NamePos != SMap.end()) {
798 I = NamePos->second.begin();
799 IEnd = NamePos->second.end();
800 }
801
802 for (; I != IEnd; ++I) {
803 NamedDecl *ND = I->first;
804 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000805 if (ND->getCanonicalDecl() == CanonDecl) {
806 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000807 Results[Index].Declaration = R.Declaration;
808
Douglas Gregor86d9a522009-09-21 16:56:56 +0000809 // We're done.
810 return;
811 }
812 }
813
814 // This is a new declaration in this scope. However, check whether this
815 // declaration name is hidden by a similarly-named declaration in an outer
816 // scope.
817 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
818 --SMEnd;
819 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000820 ShadowMapEntry::iterator I, IEnd;
821 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
822 if (NamePos != SM->end()) {
823 I = NamePos->second.begin();
824 IEnd = NamePos->second.end();
825 }
826 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000827 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000828 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000829 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
830 Decl::IDNS_ObjCProtocol)))
831 continue;
832
833 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000834 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000835 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000836 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000837 continue;
838
839 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000840 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000841 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000842
843 break;
844 }
845 }
846
847 // Make sure that any given declaration only shows up in the result set once.
848 if (!AllDeclsFound.insert(CanonDecl))
849 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000850
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000851 // If the filter is for nested-name-specifiers, then this result starts a
852 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000853 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000854 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000855 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000856 } else
857 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000858
Douglas Gregor0563c262009-09-22 23:15:58 +0000859 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000860 if (R.QualifierIsInformative && !R.Qualifier &&
861 !R.StartsNestedNameSpecifier) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000862 DeclContext *Ctx = R.Declaration->getDeclContext();
863 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
864 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
865 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
866 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
867 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
868 else
869 R.QualifierIsInformative = false;
870 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000871
Douglas Gregor86d9a522009-09-21 16:56:56 +0000872 // Insert this result into the set of results and into the current shadow
873 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000874 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000875 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000876
877 if (!AsNestedNameSpecifier)
878 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000879}
880
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000881void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000882 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000883 if (R.Kind != Result::RK_Declaration) {
884 // For non-declaration results, just add the result.
885 Results.push_back(R);
886 return;
887 }
888
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000889 // Look through using declarations.
890 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
891 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
892 return;
893 }
894
Douglas Gregor45bcd432010-01-14 03:21:49 +0000895 bool AsNestedNameSpecifier = false;
896 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000897 return;
898
Douglas Gregor6f942b22010-09-21 16:06:22 +0000899 // C++ constructors are never found by name lookup.
900 if (isa<CXXConstructorDecl>(R.Declaration))
901 return;
902
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000903 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
904 return;
Nick Lewycky173a37a2012-04-03 21:44:08 +0000905
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000906 // Make sure that any given declaration only shows up in the result set once.
907 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
908 return;
909
910 // If the filter is for nested-name-specifiers, then this result starts a
911 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000912 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000913 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000914 R.Priority = CCP_NestedNameSpecifier;
915 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000916 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
917 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000918 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000919 R.QualifierIsInformative = true;
920
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000921 // If this result is supposed to have an informative qualifier, add one.
922 if (R.QualifierIsInformative && !R.Qualifier &&
923 !R.StartsNestedNameSpecifier) {
924 DeclContext *Ctx = R.Declaration->getDeclContext();
925 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
926 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
927 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
928 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000929 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000930 else
931 R.QualifierIsInformative = false;
932 }
933
Douglas Gregor12e13132010-05-26 22:00:08 +0000934 // Adjust the priority if this result comes from a base class.
935 if (InBaseClass)
936 R.Priority += CCD_InBaseClass;
937
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000938 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000939
Douglas Gregor3cdee122010-08-26 16:36:48 +0000940 if (HasObjectTypeQualifiers)
941 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
942 if (Method->isInstance()) {
943 Qualifiers MethodQuals
944 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
945 if (ObjectTypeQualifiers == MethodQuals)
946 R.Priority += CCD_ObjectQualifierMatch;
947 else if (ObjectTypeQualifiers - MethodQuals) {
948 // The method cannot be invoked, because doing so would drop
949 // qualifiers.
950 return;
951 }
952 }
953
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000954 // Insert this result into the set of results.
955 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000956
957 if (!AsNestedNameSpecifier)
958 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000959}
960
Douglas Gregora4477812010-01-14 16:01:26 +0000961void ResultBuilder::AddResult(Result R) {
962 assert(R.Kind != Result::RK_Declaration &&
963 "Declaration results need more context");
964 Results.push_back(R);
965}
966
Douglas Gregor86d9a522009-09-21 16:56:56 +0000967/// \brief Enter into a new scope.
968void ResultBuilder::EnterNewScope() {
969 ShadowMaps.push_back(ShadowMap());
970}
971
972/// \brief Exit from the current scope.
973void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000974 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
975 EEnd = ShadowMaps.back().end();
976 E != EEnd;
977 ++E)
978 E->second.Destroy();
979
Douglas Gregor86d9a522009-09-21 16:56:56 +0000980 ShadowMaps.pop_back();
981}
982
Douglas Gregor791215b2009-09-21 20:51:25 +0000983/// \brief Determines whether this given declaration will be found by
984/// ordinary name lookup.
985bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000986 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
987
Douglas Gregor791215b2009-09-21 20:51:25 +0000988 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +0000989 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000990 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +0000991 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +0000992 if (isa<ObjCIvarDecl>(ND))
993 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +0000994 }
995
Douglas Gregor791215b2009-09-21 20:51:25 +0000996 return ND->getIdentifierNamespace() & IDNS;
997}
998
Douglas Gregor01dfea02010-01-10 23:08:15 +0000999/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001000/// ordinary name lookup but is not a type name.
1001bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
1002 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1003 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1004 return false;
1005
1006 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001007 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +00001008 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +00001009 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +00001010 if (isa<ObjCIvarDecl>(ND))
1011 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001012 }
1013
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001014 return ND->getIdentifierNamespace() & IDNS;
1015}
1016
Douglas Gregorf9578432010-07-28 21:50:18 +00001017bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
1018 if (!IsOrdinaryNonTypeName(ND))
1019 return 0;
1020
1021 if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
1022 if (VD->getType()->isIntegralOrEnumerationType())
1023 return true;
1024
1025 return false;
1026}
1027
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001028/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001029/// ordinary name lookup.
1030bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001031 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1032
Douglas Gregor01dfea02010-01-10 23:08:15 +00001033 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001034 if (SemaRef.getLangOpts().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001035 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001036
1037 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001038 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1039 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001040}
1041
Douglas Gregor86d9a522009-09-21 16:56:56 +00001042/// \brief Determines whether the given declaration is suitable as the
1043/// start of a C++ nested-name-specifier, e.g., a class or namespace.
1044bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
1045 // Allow us to find class templates, too.
1046 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1047 ND = ClassTemplate->getTemplatedDecl();
1048
1049 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1050}
1051
1052/// \brief Determines whether the given declaration is an enumeration.
1053bool ResultBuilder::IsEnum(NamedDecl *ND) const {
1054 return isa<EnumDecl>(ND);
1055}
1056
1057/// \brief Determines whether the given declaration is a class or struct.
1058bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
1059 // Allow us to find class templates, too.
1060 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1061 ND = ClassTemplate->getTemplatedDecl();
Joao Matos6666ed42012-08-31 18:45:21 +00001062
1063 // For purposes of this check, interfaces match too.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001064 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001065 return RD->getTagKind() == TTK_Class ||
Joao Matos6666ed42012-08-31 18:45:21 +00001066 RD->getTagKind() == TTK_Struct ||
1067 RD->getTagKind() == TTK_Interface;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001068
1069 return false;
1070}
1071
1072/// \brief Determines whether the given declaration is a union.
1073bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1074 // Allow us to find class templates, too.
1075 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1076 ND = ClassTemplate->getTemplatedDecl();
1077
1078 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001079 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001080
1081 return false;
1082}
1083
1084/// \brief Determines whether the given declaration is a namespace.
1085bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1086 return isa<NamespaceDecl>(ND);
1087}
1088
1089/// \brief Determines whether the given declaration is a namespace or
1090/// namespace alias.
1091bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1092 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1093}
1094
Douglas Gregor76282942009-12-11 17:31:05 +00001095/// \brief Determines whether the given declaration is a type.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001096bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregord32b0222010-08-24 01:06:58 +00001097 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1098 ND = Using->getTargetDecl();
1099
1100 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001101}
1102
Douglas Gregor76282942009-12-11 17:31:05 +00001103/// \brief Determines which members of a class should be visible via
1104/// "." or "->". Only value declarations, nested name specifiers, and
1105/// using declarations thereof should show up.
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001106bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor76282942009-12-11 17:31:05 +00001107 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1108 ND = Using->getTargetDecl();
1109
Douglas Gregorce821962009-12-11 18:14:22 +00001110 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1111 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001112}
1113
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001114static bool isObjCReceiverType(ASTContext &C, QualType T) {
1115 T = C.getCanonicalType(T);
1116 switch (T->getTypeClass()) {
1117 case Type::ObjCObject:
1118 case Type::ObjCInterface:
1119 case Type::ObjCObjectPointer:
1120 return true;
1121
1122 case Type::Builtin:
1123 switch (cast<BuiltinType>(T)->getKind()) {
1124 case BuiltinType::ObjCId:
1125 case BuiltinType::ObjCClass:
1126 case BuiltinType::ObjCSel:
1127 return true;
1128
1129 default:
1130 break;
1131 }
1132 return false;
1133
1134 default:
1135 break;
1136 }
1137
David Blaikie4e4d0842012-03-11 07:00:24 +00001138 if (!C.getLangOpts().CPlusPlus)
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001139 return false;
1140
1141 // FIXME: We could perform more analysis here to determine whether a
1142 // particular class type has any conversions to Objective-C types. For now,
1143 // just accept all class types.
1144 return T->isDependentType() || T->isRecordType();
1145}
1146
1147bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1148 QualType T = getDeclUsageType(SemaRef.Context, ND);
1149 if (T.isNull())
1150 return false;
1151
1152 T = SemaRef.Context.getBaseElementType(T);
1153 return isObjCReceiverType(SemaRef.Context, T);
1154}
1155
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001156bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const {
1157 if (IsObjCMessageReceiver(ND))
1158 return true;
1159
1160 VarDecl *Var = dyn_cast<VarDecl>(ND);
1161 if (!Var)
1162 return false;
1163
1164 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1165}
1166
Douglas Gregorfb629412010-08-23 21:17:50 +00001167bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
David Blaikie4e4d0842012-03-11 07:00:24 +00001168 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1169 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregorfb629412010-08-23 21:17:50 +00001170 return false;
1171
1172 QualType T = getDeclUsageType(SemaRef.Context, ND);
1173 if (T.isNull())
1174 return false;
1175
1176 T = SemaRef.Context.getBaseElementType(T);
1177 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1178 T->isObjCIdType() ||
David Blaikie4e4d0842012-03-11 07:00:24 +00001179 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregorfb629412010-08-23 21:17:50 +00001180}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001181
Douglas Gregor52779fb2010-09-23 23:01:17 +00001182bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1183 return false;
1184}
1185
James Dennettde23c7e2012-06-17 05:33:25 +00001186/// \brief Determines whether the given declaration is an Objective-C
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001187/// instance variable.
1188bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1189 return isa<ObjCIvarDecl>(ND);
1190}
1191
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001192namespace {
1193 /// \brief Visible declaration consumer that adds a code-completion result
1194 /// for each visible declaration.
1195 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1196 ResultBuilder &Results;
1197 DeclContext *CurContext;
1198
1199 public:
1200 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1201 : Results(Results), CurContext(CurContext) { }
1202
Erik Verbruggend1205962011-10-06 07:27:49 +00001203 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1204 bool InBaseClass) {
1205 bool Accessible = true;
Douglas Gregor17015ef2011-11-03 16:51:37 +00001206 if (Ctx)
1207 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1208
Erik Verbruggend1205962011-10-06 07:27:49 +00001209 ResultBuilder::Result Result(ND, 0, false, Accessible);
1210 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001211 }
1212 };
1213}
1214
Douglas Gregor86d9a522009-09-21 16:56:56 +00001215/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001216static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001217 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001218 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001219 Results.AddResult(Result("short", CCP_Type));
1220 Results.AddResult(Result("long", CCP_Type));
1221 Results.AddResult(Result("signed", CCP_Type));
1222 Results.AddResult(Result("unsigned", CCP_Type));
1223 Results.AddResult(Result("void", CCP_Type));
1224 Results.AddResult(Result("char", CCP_Type));
1225 Results.AddResult(Result("int", CCP_Type));
1226 Results.AddResult(Result("float", CCP_Type));
1227 Results.AddResult(Result("double", CCP_Type));
1228 Results.AddResult(Result("enum", CCP_Type));
1229 Results.AddResult(Result("struct", CCP_Type));
1230 Results.AddResult(Result("union", CCP_Type));
1231 Results.AddResult(Result("const", CCP_Type));
1232 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001233
Douglas Gregor86d9a522009-09-21 16:56:56 +00001234 if (LangOpts.C99) {
1235 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001236 Results.AddResult(Result("_Complex", CCP_Type));
1237 Results.AddResult(Result("_Imaginary", CCP_Type));
1238 Results.AddResult(Result("_Bool", CCP_Type));
1239 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001240 }
1241
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001242 CodeCompletionBuilder Builder(Results.getAllocator(),
1243 Results.getCodeCompletionTUInfo());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001244 if (LangOpts.CPlusPlus) {
1245 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001246 Results.AddResult(Result("bool", CCP_Type +
1247 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001248 Results.AddResult(Result("class", CCP_Type));
1249 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001250
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001251 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001252 Builder.AddTypedTextChunk("typename");
1253 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1254 Builder.AddPlaceholderChunk("qualifier");
1255 Builder.AddTextChunk("::");
1256 Builder.AddPlaceholderChunk("name");
1257 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001258
Douglas Gregor86d9a522009-09-21 16:56:56 +00001259 if (LangOpts.CPlusPlus0x) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001260 Results.AddResult(Result("auto", CCP_Type));
1261 Results.AddResult(Result("char16_t", CCP_Type));
1262 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001263
Douglas Gregor218937c2011-02-01 19:23:04 +00001264 Builder.AddTypedTextChunk("decltype");
1265 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1266 Builder.AddPlaceholderChunk("expression");
1267 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1268 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001269 }
1270 }
1271
1272 // GNU extensions
1273 if (LangOpts.GNUMode) {
1274 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001275 // Results.AddResult(Result("_Decimal32"));
1276 // Results.AddResult(Result("_Decimal64"));
1277 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001278
Douglas Gregor218937c2011-02-01 19:23:04 +00001279 Builder.AddTypedTextChunk("typeof");
1280 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1281 Builder.AddPlaceholderChunk("expression");
1282 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001283
Douglas Gregor218937c2011-02-01 19:23:04 +00001284 Builder.AddTypedTextChunk("typeof");
1285 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1286 Builder.AddPlaceholderChunk("type");
1287 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1288 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001289 }
1290}
1291
John McCallf312b1e2010-08-26 23:41:50 +00001292static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001293 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001294 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001295 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001296 // Note: we don't suggest either "auto" or "register", because both
1297 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1298 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001299 Results.AddResult(Result("extern"));
1300 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001301}
1302
John McCallf312b1e2010-08-26 23:41:50 +00001303static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001304 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001305 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001306 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001307 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001308 case Sema::PCC_Class:
1309 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001310 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001311 Results.AddResult(Result("explicit"));
1312 Results.AddResult(Result("friend"));
1313 Results.AddResult(Result("mutable"));
1314 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001315 }
1316 // Fall through
1317
John McCallf312b1e2010-08-26 23:41:50 +00001318 case Sema::PCC_ObjCInterface:
1319 case Sema::PCC_ObjCImplementation:
1320 case Sema::PCC_Namespace:
1321 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001322 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001323 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001324 break;
1325
John McCallf312b1e2010-08-26 23:41:50 +00001326 case Sema::PCC_ObjCInstanceVariableList:
1327 case Sema::PCC_Expression:
1328 case Sema::PCC_Statement:
1329 case Sema::PCC_ForInit:
1330 case Sema::PCC_Condition:
1331 case Sema::PCC_RecoveryInFunction:
1332 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001333 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001334 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001335 break;
1336 }
1337}
1338
Douglas Gregorbca403c2010-01-13 23:51:12 +00001339static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1340static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1341static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001342 ResultBuilder &Results,
1343 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001344static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001345 ResultBuilder &Results,
1346 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001347static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001348 ResultBuilder &Results,
1349 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001350static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001351
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001352static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001353 CodeCompletionBuilder Builder(Results.getAllocator(),
1354 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00001355 Builder.AddTypedTextChunk("typedef");
1356 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1357 Builder.AddPlaceholderChunk("type");
1358 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1359 Builder.AddPlaceholderChunk("name");
1360 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001361}
1362
John McCallf312b1e2010-08-26 23:41:50 +00001363static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001364 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001365 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001366 case Sema::PCC_Namespace:
1367 case Sema::PCC_Class:
1368 case Sema::PCC_ObjCInstanceVariableList:
1369 case Sema::PCC_Template:
1370 case Sema::PCC_MemberTemplate:
1371 case Sema::PCC_Statement:
1372 case Sema::PCC_RecoveryInFunction:
1373 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001374 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001375 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001376 return true;
1377
John McCallf312b1e2010-08-26 23:41:50 +00001378 case Sema::PCC_Expression:
1379 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001380 return LangOpts.CPlusPlus;
1381
1382 case Sema::PCC_ObjCInterface:
1383 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001384 return false;
1385
John McCallf312b1e2010-08-26 23:41:50 +00001386 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001387 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001388 }
David Blaikie7530c032012-01-17 06:56:22 +00001389
1390 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001391}
1392
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001393static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1394 const Preprocessor &PP) {
1395 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001396 Policy.AnonymousTagLocations = false;
1397 Policy.SuppressStrongLifetime = true;
Douglas Gregor25270b62011-11-03 00:16:13 +00001398 Policy.SuppressUnwrittenScope = true;
Douglas Gregor8ca72082011-10-18 21:20:17 +00001399 return Policy;
1400}
1401
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001402/// \brief Retrieve a printing policy suitable for code completion.
1403static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1404 return getCompletionPrintingPolicy(S.Context, S.PP);
1405}
1406
Douglas Gregor8ca72082011-10-18 21:20:17 +00001407/// \brief Retrieve the string representation of the given type as a string
1408/// that has the appropriate lifetime for code completion.
1409///
1410/// This routine provides a fast path where we provide constant strings for
1411/// common type names.
1412static const char *GetCompletionTypeString(QualType T,
1413 ASTContext &Context,
1414 const PrintingPolicy &Policy,
1415 CodeCompletionAllocator &Allocator) {
1416 if (!T.getLocalQualifiers()) {
1417 // Built-in type names are constant strings.
1418 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidis27a00972012-05-05 04:20:28 +00001419 return BT->getNameAsCString(Policy);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001420
1421 // Anonymous tag types are constant strings.
1422 if (const TagType *TagT = dyn_cast<TagType>(T))
1423 if (TagDecl *Tag = TagT->getDecl())
1424 if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
1425 switch (Tag->getTagKind()) {
1426 case TTK_Struct: return "struct <anonymous>";
Joao Matos6666ed42012-08-31 18:45:21 +00001427 case TTK_Interface: return "__interface <anonymous>";
1428 case TTK_Class: return "class <anonymous>";
Douglas Gregor8ca72082011-10-18 21:20:17 +00001429 case TTK_Union: return "union <anonymous>";
1430 case TTK_Enum: return "enum <anonymous>";
1431 }
1432 }
1433 }
1434
1435 // Slow path: format the type as a string.
1436 std::string Result;
1437 T.getAsStringInternal(Result, Policy);
1438 return Allocator.CopyString(Result);
1439}
1440
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001441/// \brief Add a completion for "this", if we're in a member function.
1442static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1443 QualType ThisTy = S.getCurrentThisType();
1444 if (ThisTy.isNull())
1445 return;
1446
1447 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001448 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001449 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1450 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1451 S.Context,
1452 Policy,
1453 Allocator));
1454 Builder.AddTypedTextChunk("this");
Joao Matos6666ed42012-08-31 18:45:21 +00001455 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001456}
1457
Douglas Gregor01dfea02010-01-10 23:08:15 +00001458/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001459static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001460 Scope *S,
1461 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001462 ResultBuilder &Results) {
Douglas Gregor8ca72082011-10-18 21:20:17 +00001463 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001464 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor8ca72082011-10-18 21:20:17 +00001465 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregor218937c2011-02-01 19:23:04 +00001466
John McCall0a2c5e22010-08-25 06:19:51 +00001467 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001468 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001469 case Sema::PCC_Namespace:
David Blaikie4e4d0842012-03-11 07:00:24 +00001470 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001471 if (Results.includeCodePatterns()) {
1472 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001473 Builder.AddTypedTextChunk("namespace");
1474 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1475 Builder.AddPlaceholderChunk("identifier");
1476 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1477 Builder.AddPlaceholderChunk("declarations");
1478 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1479 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1480 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001481 }
1482
Douglas Gregor01dfea02010-01-10 23:08:15 +00001483 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001484 Builder.AddTypedTextChunk("namespace");
1485 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1486 Builder.AddPlaceholderChunk("name");
1487 Builder.AddChunk(CodeCompletionString::CK_Equal);
1488 Builder.AddPlaceholderChunk("namespace");
1489 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001490
1491 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001492 Builder.AddTypedTextChunk("using");
1493 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1494 Builder.AddTextChunk("namespace");
1495 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1496 Builder.AddPlaceholderChunk("identifier");
1497 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001498
1499 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001500 Builder.AddTypedTextChunk("asm");
1501 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1502 Builder.AddPlaceholderChunk("string-literal");
1503 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1504 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001505
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001506 if (Results.includeCodePatterns()) {
1507 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001508 Builder.AddTypedTextChunk("template");
1509 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1510 Builder.AddPlaceholderChunk("declaration");
1511 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001512 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001513 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001514
David Blaikie4e4d0842012-03-11 07:00:24 +00001515 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001516 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001517
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001518 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001519 // Fall through
1520
John McCallf312b1e2010-08-26 23:41:50 +00001521 case Sema::PCC_Class:
David Blaikie4e4d0842012-03-11 07:00:24 +00001522 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001523 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001524 Builder.AddTypedTextChunk("using");
1525 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1526 Builder.AddPlaceholderChunk("qualifier");
1527 Builder.AddTextChunk("::");
1528 Builder.AddPlaceholderChunk("name");
1529 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001530
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001531 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001532 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001533 Builder.AddTypedTextChunk("using");
1534 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1535 Builder.AddTextChunk("typename");
1536 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1537 Builder.AddPlaceholderChunk("qualifier");
1538 Builder.AddTextChunk("::");
1539 Builder.AddPlaceholderChunk("name");
1540 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001541 }
1542
John McCallf312b1e2010-08-26 23:41:50 +00001543 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001544 AddTypedefResult(Results);
1545
Douglas Gregor01dfea02010-01-10 23:08:15 +00001546 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001547 Builder.AddTypedTextChunk("public");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001548 if (Results.includeCodePatterns())
1549 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001550 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001551
1552 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001553 Builder.AddTypedTextChunk("protected");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001554 if (Results.includeCodePatterns())
1555 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001556 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001557
1558 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001559 Builder.AddTypedTextChunk("private");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001560 if (Results.includeCodePatterns())
1561 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001562 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001563 }
1564 }
1565 // Fall through
1566
John McCallf312b1e2010-08-26 23:41:50 +00001567 case Sema::PCC_Template:
1568 case Sema::PCC_MemberTemplate:
David Blaikie4e4d0842012-03-11 07:00:24 +00001569 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001570 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001571 Builder.AddTypedTextChunk("template");
1572 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1573 Builder.AddPlaceholderChunk("parameters");
1574 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1575 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001576 }
1577
David Blaikie4e4d0842012-03-11 07:00:24 +00001578 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1579 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001580 break;
1581
John McCallf312b1e2010-08-26 23:41:50 +00001582 case Sema::PCC_ObjCInterface:
David Blaikie4e4d0842012-03-11 07:00:24 +00001583 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1584 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1585 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001586 break;
1587
John McCallf312b1e2010-08-26 23:41:50 +00001588 case Sema::PCC_ObjCImplementation:
David Blaikie4e4d0842012-03-11 07:00:24 +00001589 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1590 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1591 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001592 break;
1593
John McCallf312b1e2010-08-26 23:41:50 +00001594 case Sema::PCC_ObjCInstanceVariableList:
David Blaikie4e4d0842012-03-11 07:00:24 +00001595 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001596 break;
1597
John McCallf312b1e2010-08-26 23:41:50 +00001598 case Sema::PCC_RecoveryInFunction:
1599 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001600 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001601
David Blaikie4e4d0842012-03-11 07:00:24 +00001602 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1603 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001604 Builder.AddTypedTextChunk("try");
1605 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1606 Builder.AddPlaceholderChunk("statements");
1607 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1608 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1609 Builder.AddTextChunk("catch");
1610 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1611 Builder.AddPlaceholderChunk("declaration");
1612 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1613 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1614 Builder.AddPlaceholderChunk("statements");
1615 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1616 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1617 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001618 }
David Blaikie4e4d0842012-03-11 07:00:24 +00001619 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001620 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001621
Douglas Gregord8e8a582010-05-25 21:41:55 +00001622 if (Results.includeCodePatterns()) {
1623 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001624 Builder.AddTypedTextChunk("if");
1625 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001626 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001627 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001628 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001629 Builder.AddPlaceholderChunk("expression");
1630 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1631 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1632 Builder.AddPlaceholderChunk("statements");
1633 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1634 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1635 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001636
Douglas Gregord8e8a582010-05-25 21:41:55 +00001637 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001638 Builder.AddTypedTextChunk("switch");
1639 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001640 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001641 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001642 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001643 Builder.AddPlaceholderChunk("expression");
1644 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1645 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1646 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1647 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1648 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001649 }
1650
Douglas Gregor01dfea02010-01-10 23:08:15 +00001651 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001652 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001653 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001654 Builder.AddTypedTextChunk("case");
1655 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1656 Builder.AddPlaceholderChunk("expression");
1657 Builder.AddChunk(CodeCompletionString::CK_Colon);
1658 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001659
1660 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001661 Builder.AddTypedTextChunk("default");
1662 Builder.AddChunk(CodeCompletionString::CK_Colon);
1663 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001664 }
1665
Douglas Gregord8e8a582010-05-25 21:41:55 +00001666 if (Results.includeCodePatterns()) {
1667 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001668 Builder.AddTypedTextChunk("while");
1669 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001670 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001671 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001672 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001673 Builder.AddPlaceholderChunk("expression");
1674 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1675 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1676 Builder.AddPlaceholderChunk("statements");
1677 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1678 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1679 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001680
1681 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001682 Builder.AddTypedTextChunk("do");
1683 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1684 Builder.AddPlaceholderChunk("statements");
1685 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1686 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1687 Builder.AddTextChunk("while");
1688 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1689 Builder.AddPlaceholderChunk("expression");
1690 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1691 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001692
Douglas Gregord8e8a582010-05-25 21:41:55 +00001693 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001694 Builder.AddTypedTextChunk("for");
1695 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001696 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001697 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001698 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001699 Builder.AddPlaceholderChunk("init-expression");
1700 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1701 Builder.AddPlaceholderChunk("condition");
1702 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1703 Builder.AddPlaceholderChunk("inc-expression");
1704 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1705 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1706 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1707 Builder.AddPlaceholderChunk("statements");
1708 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1709 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1710 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001711 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001712
1713 if (S->getContinueParent()) {
1714 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001715 Builder.AddTypedTextChunk("continue");
1716 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001717 }
1718
1719 if (S->getBreakParent()) {
1720 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001721 Builder.AddTypedTextChunk("break");
1722 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001723 }
1724
1725 // "return expression ;" or "return ;", depending on whether we
1726 // know the function is void or not.
1727 bool isVoid = false;
1728 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1729 isVoid = Function->getResultType()->isVoidType();
1730 else if (ObjCMethodDecl *Method
1731 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1732 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001733 else if (SemaRef.getCurBlock() &&
1734 !SemaRef.getCurBlock()->ReturnType.isNull())
1735 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001736 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001737 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001738 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1739 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001740 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001741 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001742
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001743 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001744 Builder.AddTypedTextChunk("goto");
1745 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1746 Builder.AddPlaceholderChunk("label");
1747 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001748
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001749 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001750 Builder.AddTypedTextChunk("using");
1751 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1752 Builder.AddTextChunk("namespace");
1753 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1754 Builder.AddPlaceholderChunk("identifier");
1755 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001756 }
1757
1758 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001759 case Sema::PCC_ForInit:
1760 case Sema::PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00001761 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001762 // Fall through: conditions and statements can have expressions.
1763
Douglas Gregor02688102010-09-14 23:59:36 +00001764 case Sema::PCC_ParenthesizedExpression:
David Blaikie4e4d0842012-03-11 07:00:24 +00001765 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCallf85e1932011-06-15 23:02:42 +00001766 CCC == Sema::PCC_ParenthesizedExpression) {
1767 // (__bridge <type>)<expression>
1768 Builder.AddTypedTextChunk("__bridge");
1769 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1770 Builder.AddPlaceholderChunk("type");
1771 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1772 Builder.AddPlaceholderChunk("expression");
1773 Results.AddResult(Result(Builder.TakeString()));
1774
1775 // (__bridge_transfer <Objective-C type>)<expression>
1776 Builder.AddTypedTextChunk("__bridge_transfer");
1777 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1778 Builder.AddPlaceholderChunk("Objective-C type");
1779 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1780 Builder.AddPlaceholderChunk("expression");
1781 Results.AddResult(Result(Builder.TakeString()));
1782
1783 // (__bridge_retained <CF type>)<expression>
1784 Builder.AddTypedTextChunk("__bridge_retained");
1785 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1786 Builder.AddPlaceholderChunk("CF type");
1787 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1788 Builder.AddPlaceholderChunk("expression");
1789 Results.AddResult(Result(Builder.TakeString()));
1790 }
1791 // Fall through
1792
John McCallf312b1e2010-08-26 23:41:50 +00001793 case Sema::PCC_Expression: {
David Blaikie4e4d0842012-03-11 07:00:24 +00001794 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001795 // 'this', if we're in a non-static member function.
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001796 addThisCompletion(SemaRef, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001797
Douglas Gregor8ca72082011-10-18 21:20:17 +00001798 // true
1799 Builder.AddResultTypeChunk("bool");
1800 Builder.AddTypedTextChunk("true");
1801 Results.AddResult(Result(Builder.TakeString()));
1802
1803 // false
1804 Builder.AddResultTypeChunk("bool");
1805 Builder.AddTypedTextChunk("false");
1806 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001807
David Blaikie4e4d0842012-03-11 07:00:24 +00001808 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001809 // dynamic_cast < type-id > ( expression )
1810 Builder.AddTypedTextChunk("dynamic_cast");
1811 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1812 Builder.AddPlaceholderChunk("type");
1813 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1814 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1815 Builder.AddPlaceholderChunk("expression");
1816 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1817 Results.AddResult(Result(Builder.TakeString()));
1818 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001819
1820 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001821 Builder.AddTypedTextChunk("static_cast");
1822 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1823 Builder.AddPlaceholderChunk("type");
1824 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1825 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1826 Builder.AddPlaceholderChunk("expression");
1827 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1828 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001829
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001830 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001831 Builder.AddTypedTextChunk("reinterpret_cast");
1832 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1833 Builder.AddPlaceholderChunk("type");
1834 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1835 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1836 Builder.AddPlaceholderChunk("expression");
1837 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1838 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001839
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001840 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001841 Builder.AddTypedTextChunk("const_cast");
1842 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1843 Builder.AddPlaceholderChunk("type");
1844 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1845 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1846 Builder.AddPlaceholderChunk("expression");
1847 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1848 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001849
David Blaikie4e4d0842012-03-11 07:00:24 +00001850 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001851 // typeid ( expression-or-type )
Douglas Gregor8ca72082011-10-18 21:20:17 +00001852 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001853 Builder.AddTypedTextChunk("typeid");
1854 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1855 Builder.AddPlaceholderChunk("expression-or-type");
1856 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1857 Results.AddResult(Result(Builder.TakeString()));
1858 }
1859
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001860 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001861 Builder.AddTypedTextChunk("new");
1862 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1863 Builder.AddPlaceholderChunk("type");
1864 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1865 Builder.AddPlaceholderChunk("expressions");
1866 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1867 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001868
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001869 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001870 Builder.AddTypedTextChunk("new");
1871 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1872 Builder.AddPlaceholderChunk("type");
1873 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1874 Builder.AddPlaceholderChunk("size");
1875 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1876 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1877 Builder.AddPlaceholderChunk("expressions");
1878 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1879 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001880
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001881 // delete expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001882 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001883 Builder.AddTypedTextChunk("delete");
1884 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1885 Builder.AddPlaceholderChunk("expression");
1886 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001887
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001888 // delete [] expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001889 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001890 Builder.AddTypedTextChunk("delete");
1891 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1892 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1893 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1894 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1895 Builder.AddPlaceholderChunk("expression");
1896 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001897
David Blaikie4e4d0842012-03-11 07:00:24 +00001898 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001899 // throw expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001900 Builder.AddResultTypeChunk("void");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001901 Builder.AddTypedTextChunk("throw");
1902 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1903 Builder.AddPlaceholderChunk("expression");
1904 Results.AddResult(Result(Builder.TakeString()));
1905 }
Douglas Gregora50216c2011-10-18 16:29:03 +00001906
Douglas Gregor12e13132010-05-26 22:00:08 +00001907 // FIXME: Rethrow?
Douglas Gregora50216c2011-10-18 16:29:03 +00001908
David Blaikie4e4d0842012-03-11 07:00:24 +00001909 if (SemaRef.getLangOpts().CPlusPlus0x) {
Douglas Gregora50216c2011-10-18 16:29:03 +00001910 // nullptr
Douglas Gregor8ca72082011-10-18 21:20:17 +00001911 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001912 Builder.AddTypedTextChunk("nullptr");
1913 Results.AddResult(Result(Builder.TakeString()));
1914
1915 // alignof
Douglas Gregor8ca72082011-10-18 21:20:17 +00001916 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001917 Builder.AddTypedTextChunk("alignof");
1918 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1919 Builder.AddPlaceholderChunk("type");
1920 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1921 Results.AddResult(Result(Builder.TakeString()));
1922
1923 // noexcept
Douglas Gregor8ca72082011-10-18 21:20:17 +00001924 Builder.AddResultTypeChunk("bool");
Douglas Gregora50216c2011-10-18 16:29:03 +00001925 Builder.AddTypedTextChunk("noexcept");
1926 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1927 Builder.AddPlaceholderChunk("expression");
1928 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1929 Results.AddResult(Result(Builder.TakeString()));
1930
1931 // sizeof... expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001932 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001933 Builder.AddTypedTextChunk("sizeof...");
1934 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1935 Builder.AddPlaceholderChunk("parameter-pack");
1936 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1937 Results.AddResult(Result(Builder.TakeString()));
1938 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001939 }
1940
David Blaikie4e4d0842012-03-11 07:00:24 +00001941 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001942 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001943 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1944 // The interface can be NULL.
1945 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregor8ca72082011-10-18 21:20:17 +00001946 if (ID->getSuperClass()) {
1947 std::string SuperType;
1948 SuperType = ID->getSuperClass()->getNameAsString();
1949 if (Method->isInstanceMethod())
1950 SuperType += " *";
1951
1952 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1953 Builder.AddTypedTextChunk("super");
1954 Results.AddResult(Result(Builder.TakeString()));
1955 }
Ted Kremenek681e2562010-05-31 21:43:10 +00001956 }
1957
Douglas Gregorbca403c2010-01-13 23:51:12 +00001958 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001959 }
1960
Jordan Rosef70a8862012-06-30 21:33:57 +00001961 if (SemaRef.getLangOpts().C11) {
1962 // _Alignof
1963 Builder.AddResultTypeChunk("size_t");
1964 if (SemaRef.getASTContext().Idents.get("alignof").hasMacroDefinition())
1965 Builder.AddTypedTextChunk("alignof");
1966 else
1967 Builder.AddTypedTextChunk("_Alignof");
1968 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1969 Builder.AddPlaceholderChunk("type");
1970 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1971 Results.AddResult(Result(Builder.TakeString()));
1972 }
1973
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001974 // sizeof expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001975 Builder.AddResultTypeChunk("size_t");
Douglas Gregor218937c2011-02-01 19:23:04 +00001976 Builder.AddTypedTextChunk("sizeof");
1977 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1978 Builder.AddPlaceholderChunk("expression-or-type");
1979 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1980 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001981 break;
1982 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001983
John McCallf312b1e2010-08-26 23:41:50 +00001984 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001985 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00001986 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001987 }
1988
David Blaikie4e4d0842012-03-11 07:00:24 +00001989 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
1990 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001991
David Blaikie4e4d0842012-03-11 07:00:24 +00001992 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00001993 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001994}
1995
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001996/// \brief If the given declaration has an associated type, add it as a result
1997/// type chunk.
1998static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00001999 const PrintingPolicy &Policy,
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002000 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00002001 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002002 if (!ND)
2003 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00002004
2005 // Skip constructors and conversion functions, which have their return types
2006 // built into their names.
2007 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
2008 return;
2009
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002010 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00002011 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002012 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
2013 T = Function->getResultType();
2014 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
2015 T = Method->getResultType();
2016 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
2017 T = FunTmpl->getTemplatedDecl()->getResultType();
2018 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
2019 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
2020 else if (isa<UnresolvedUsingValueDecl>(ND)) {
2021 /* Do nothing: ignore unresolved using declarations*/
John McCallf85e1932011-06-15 23:02:42 +00002022 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002023 T = Value->getType();
John McCallf85e1932011-06-15 23:02:42 +00002024 } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002025 T = Property->getType();
2026
2027 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2028 return;
2029
Douglas Gregor8987b232011-09-27 23:30:47 +00002030 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002031 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002032}
2033
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002034static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00002035 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002036 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2037 if (Sentinel->getSentinel() == 0) {
David Blaikie4e4d0842012-03-11 07:00:24 +00002038 if (Context.getLangOpts().ObjC1 &&
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002039 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002040 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002041 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002042 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002043 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002044 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002045 }
2046}
2047
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002048static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2049 std::string Result;
2050 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002051 Result += "in ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002052 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002053 Result += "inout ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002054 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002055 Result += "out ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002056 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002057 Result += "bycopy ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002058 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002059 Result += "byref ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002060 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002061 Result += "oneway ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002062 return Result;
2063}
2064
Douglas Gregor83482d12010-08-24 16:15:59 +00002065static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002066 const PrintingPolicy &Policy,
Douglas Gregoraba48082010-08-29 19:47:46 +00002067 ParmVarDecl *Param,
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002068 bool SuppressName = false,
2069 bool SuppressBlock = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00002070 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2071 if (Param->getType()->isDependentType() ||
2072 !Param->getType()->isBlockPointerType()) {
2073 // The argument for a dependent or non-block parameter is a placeholder
2074 // containing that parameter's type.
2075 std::string Result;
2076
Douglas Gregoraba48082010-08-29 19:47:46 +00002077 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002078 Result = Param->getIdentifier()->getName();
2079
John McCallf85e1932011-06-15 23:02:42 +00002080 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002081
2082 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002083 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2084 + Result + ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00002085 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002086 Result += Param->getIdentifier()->getName();
2087 }
2088 return Result;
2089 }
2090
2091 // The argument for a block pointer parameter is a block literal with
2092 // the appropriate type.
Douglas Gregor830072c2011-02-15 22:37:09 +00002093 FunctionTypeLoc *Block = 0;
2094 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregor83482d12010-08-24 16:15:59 +00002095 TypeLoc TL;
2096 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2097 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2098 while (true) {
2099 // Look through typedefs.
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002100 if (!SuppressBlock) {
2101 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2102 if (TypeSourceInfo *InnerTSInfo
2103 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2104 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2105 continue;
2106 }
2107 }
2108
2109 // Look through qualified types
2110 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2111 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregor83482d12010-08-24 16:15:59 +00002112 continue;
2113 }
2114 }
2115
Douglas Gregor83482d12010-08-24 16:15:59 +00002116 // Try to get the function prototype behind the block pointer type,
2117 // then we're done.
2118 if (BlockPointerTypeLoc *BlockPtr
2119 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00002120 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor830072c2011-02-15 22:37:09 +00002121 Block = dyn_cast<FunctionTypeLoc>(&TL);
2122 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregor83482d12010-08-24 16:15:59 +00002123 }
2124 break;
2125 }
2126 }
2127
2128 if (!Block) {
2129 // We were unable to find a FunctionProtoTypeLoc with parameter names
2130 // for the block; just use the parameter type as a placeholder.
2131 std::string Result;
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002132 if (!ObjCMethodParam && Param->getIdentifier())
2133 Result = Param->getIdentifier()->getName();
2134
John McCallf85e1932011-06-15 23:02:42 +00002135 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002136
2137 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002138 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2139 + Result + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002140 if (Param->getIdentifier())
2141 Result += Param->getIdentifier()->getName();
2142 }
2143
2144 return Result;
2145 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002146
Douglas Gregor83482d12010-08-24 16:15:59 +00002147 // We have the function prototype behind the block pointer type, as it was
2148 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00002149 std::string Result;
2150 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002151 if (!ResultType->isVoidType() || SuppressBlock)
John McCallf85e1932011-06-15 23:02:42 +00002152 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002153
2154 // Format the parameter list.
2155 std::string Params;
Douglas Gregor830072c2011-02-15 22:37:09 +00002156 if (!BlockProto || Block->getNumArgs() == 0) {
2157 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002158 Params = "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00002159 else
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002160 Params = "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00002161 } else {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002162 Params += "(";
Douglas Gregor38276252010-09-08 22:47:51 +00002163 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2164 if (I)
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002165 Params += ", ";
2166 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2167 /*SuppressName=*/false,
2168 /*SuppressBlock=*/true);
Douglas Gregor38276252010-09-08 22:47:51 +00002169
Douglas Gregor830072c2011-02-15 22:37:09 +00002170 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002171 Params += ", ...";
Douglas Gregor38276252010-09-08 22:47:51 +00002172 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002173 Params += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00002174 }
Douglas Gregor38276252010-09-08 22:47:51 +00002175
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002176 if (SuppressBlock) {
2177 // Format as a parameter.
2178 Result = Result + " (^";
2179 if (Param->getIdentifier())
2180 Result += Param->getIdentifier()->getName();
2181 Result += ")";
2182 Result += Params;
2183 } else {
2184 // Format as a block literal argument.
2185 Result = '^' + Result;
2186 Result += Params;
2187
2188 if (Param->getIdentifier())
2189 Result += Param->getIdentifier()->getName();
2190 }
2191
Douglas Gregor83482d12010-08-24 16:15:59 +00002192 return Result;
2193}
2194
Douglas Gregor86d9a522009-09-21 16:56:56 +00002195/// \brief Add function parameter chunks to the given code completion string.
2196static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002197 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002198 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00002199 CodeCompletionBuilder &Result,
2200 unsigned Start = 0,
2201 bool InOptional = false) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002202 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002203
Douglas Gregor218937c2011-02-01 19:23:04 +00002204 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002205 ParmVarDecl *Param = Function->getParamDecl(P);
2206
Douglas Gregor218937c2011-02-01 19:23:04 +00002207 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002208 // When we see an optional default argument, put that argument and
2209 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002210 CodeCompletionBuilder Opt(Result.getAllocator(),
2211 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002212 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002213 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002214 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregor218937c2011-02-01 19:23:04 +00002215 Result.AddOptionalChunk(Opt.TakeString());
2216 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002217 }
2218
Douglas Gregor218937c2011-02-01 19:23:04 +00002219 if (FirstParameter)
2220 FirstParameter = false;
2221 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002222 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor218937c2011-02-01 19:23:04 +00002223
2224 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002225
2226 // Format the placeholder string.
Douglas Gregor8987b232011-09-27 23:30:47 +00002227 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2228 Param);
Douglas Gregor83482d12010-08-24 16:15:59 +00002229
Douglas Gregore17794f2010-08-31 05:13:43 +00002230 if (Function->isVariadic() && P == N - 1)
2231 PlaceholderStr += ", ...";
2232
Douglas Gregor86d9a522009-09-21 16:56:56 +00002233 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002234 Result.AddPlaceholderChunk(
2235 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002236 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002237
2238 if (const FunctionProtoType *Proto
2239 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002240 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002241 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002242 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002243
Douglas Gregor218937c2011-02-01 19:23:04 +00002244 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002245 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002246}
2247
2248/// \brief Add template parameter chunks to the given code completion string.
2249static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002250 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002251 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002252 CodeCompletionBuilder &Result,
2253 unsigned MaxParameters = 0,
2254 unsigned Start = 0,
2255 bool InDefaultArg = false) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002256 bool FirstParameter = true;
2257
2258 TemplateParameterList *Params = Template->getTemplateParameters();
2259 TemplateParameterList::iterator PEnd = Params->end();
2260 if (MaxParameters)
2261 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002262 for (TemplateParameterList::iterator P = Params->begin() + Start;
2263 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002264 bool HasDefaultArg = false;
2265 std::string PlaceholderStr;
2266 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2267 if (TTP->wasDeclaredWithTypename())
2268 PlaceholderStr = "typename";
2269 else
2270 PlaceholderStr = "class";
2271
2272 if (TTP->getIdentifier()) {
2273 PlaceholderStr += ' ';
2274 PlaceholderStr += TTP->getIdentifier()->getName();
2275 }
2276
2277 HasDefaultArg = TTP->hasDefaultArgument();
2278 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002279 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002280 if (NTTP->getIdentifier())
2281 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCallf85e1932011-06-15 23:02:42 +00002282 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002283 HasDefaultArg = NTTP->hasDefaultArgument();
2284 } else {
2285 assert(isa<TemplateTemplateParmDecl>(*P));
2286 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2287
2288 // Since putting the template argument list into the placeholder would
2289 // be very, very long, we just use an abbreviation.
2290 PlaceholderStr = "template<...> class";
2291 if (TTP->getIdentifier()) {
2292 PlaceholderStr += ' ';
2293 PlaceholderStr += TTP->getIdentifier()->getName();
2294 }
2295
2296 HasDefaultArg = TTP->hasDefaultArgument();
2297 }
2298
Douglas Gregor218937c2011-02-01 19:23:04 +00002299 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002300 // When we see an optional default argument, put that argument and
2301 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002302 CodeCompletionBuilder Opt(Result.getAllocator(),
2303 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002304 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002305 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002306 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregor218937c2011-02-01 19:23:04 +00002307 P - Params->begin(), true);
2308 Result.AddOptionalChunk(Opt.TakeString());
2309 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002310 }
2311
Douglas Gregor218937c2011-02-01 19:23:04 +00002312 InDefaultArg = false;
2313
Douglas Gregor86d9a522009-09-21 16:56:56 +00002314 if (FirstParameter)
2315 FirstParameter = false;
2316 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002317 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002318
2319 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002320 Result.AddPlaceholderChunk(
2321 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002322 }
2323}
2324
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002325/// \brief Add a qualifier to the given code-completion string, if the
2326/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002327static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002328AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002329 NestedNameSpecifier *Qualifier,
2330 bool QualifierIsInformative,
Douglas Gregor8987b232011-09-27 23:30:47 +00002331 ASTContext &Context,
2332 const PrintingPolicy &Policy) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002333 if (!Qualifier)
2334 return;
2335
2336 std::string PrintedNNS;
2337 {
2338 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor8987b232011-09-27 23:30:47 +00002339 Qualifier->print(OS, Policy);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002340 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002341 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002342 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002343 else
Douglas Gregordae68752011-02-01 22:57:45 +00002344 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002345}
2346
Douglas Gregor218937c2011-02-01 19:23:04 +00002347static void
2348AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2349 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002350 const FunctionProtoType *Proto
2351 = Function->getType()->getAs<FunctionProtoType>();
2352 if (!Proto || !Proto->getTypeQuals())
2353 return;
2354
Douglas Gregora63f6de2011-02-01 21:15:40 +00002355 // FIXME: Add ref-qualifier!
2356
2357 // Handle single qualifiers without copying
2358 if (Proto->getTypeQuals() == Qualifiers::Const) {
2359 Result.AddInformativeChunk(" const");
2360 return;
2361 }
2362
2363 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2364 Result.AddInformativeChunk(" volatile");
2365 return;
2366 }
2367
2368 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2369 Result.AddInformativeChunk(" restrict");
2370 return;
2371 }
2372
2373 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002374 std::string QualsStr;
David Blaikie4ef832f2012-08-10 00:55:35 +00002375 if (Proto->isConst())
Douglas Gregora61a8792009-12-11 18:44:16 +00002376 QualsStr += " const";
David Blaikie4ef832f2012-08-10 00:55:35 +00002377 if (Proto->isVolatile())
Douglas Gregora61a8792009-12-11 18:44:16 +00002378 QualsStr += " volatile";
David Blaikie4ef832f2012-08-10 00:55:35 +00002379 if (Proto->isRestrict())
Douglas Gregora61a8792009-12-11 18:44:16 +00002380 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002381 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002382}
2383
Douglas Gregor6f942b22010-09-21 16:06:22 +00002384/// \brief Add the name of the given declaration
Douglas Gregor8987b232011-09-27 23:30:47 +00002385static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
2386 NamedDecl *ND, CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002387 DeclarationName Name = ND->getDeclName();
2388 if (!Name)
2389 return;
2390
2391 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002392 case DeclarationName::CXXOperatorName: {
2393 const char *OperatorName = 0;
2394 switch (Name.getCXXOverloadedOperator()) {
2395 case OO_None:
2396 case OO_Conditional:
2397 case NUM_OVERLOADED_OPERATORS:
2398 OperatorName = "operator";
2399 break;
2400
2401#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2402 case OO_##Name: OperatorName = "operator" Spelling; break;
2403#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2404#include "clang/Basic/OperatorKinds.def"
2405
2406 case OO_New: OperatorName = "operator new"; break;
2407 case OO_Delete: OperatorName = "operator delete"; break;
2408 case OO_Array_New: OperatorName = "operator new[]"; break;
2409 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2410 case OO_Call: OperatorName = "operator()"; break;
2411 case OO_Subscript: OperatorName = "operator[]"; break;
2412 }
2413 Result.AddTypedTextChunk(OperatorName);
2414 break;
2415 }
2416
Douglas Gregor6f942b22010-09-21 16:06:22 +00002417 case DeclarationName::Identifier:
2418 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002419 case DeclarationName::CXXDestructorName:
2420 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002421 Result.AddTypedTextChunk(
2422 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002423 break;
2424
2425 case DeclarationName::CXXUsingDirective:
2426 case DeclarationName::ObjCZeroArgSelector:
2427 case DeclarationName::ObjCOneArgSelector:
2428 case DeclarationName::ObjCMultiArgSelector:
2429 break;
2430
2431 case DeclarationName::CXXConstructorName: {
2432 CXXRecordDecl *Record = 0;
2433 QualType Ty = Name.getCXXNameType();
2434 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2435 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2436 else if (const InjectedClassNameType *InjectedTy
2437 = Ty->getAs<InjectedClassNameType>())
2438 Record = InjectedTy->getDecl();
2439 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002440 Result.AddTypedTextChunk(
2441 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002442 break;
2443 }
2444
Douglas Gregordae68752011-02-01 22:57:45 +00002445 Result.AddTypedTextChunk(
2446 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002447 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002448 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor8987b232011-09-27 23:30:47 +00002449 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002450 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002451 }
2452 break;
2453 }
2454 }
2455}
2456
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002457CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002458 CodeCompletionAllocator &Allocator,
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002459 CodeCompletionTUInfo &CCTUInfo,
2460 bool IncludeBriefComments) {
2461 return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo,
2462 IncludeBriefComments);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002463}
2464
Douglas Gregor86d9a522009-09-21 16:56:56 +00002465/// \brief If possible, create a new code completion string for the given
2466/// result.
2467///
2468/// \returns Either a new, heap-allocated code completion string describing
2469/// how to use this result, or NULL to indicate that the string or name of the
2470/// result is all that is needed.
2471CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002472CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2473 Preprocessor &PP,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002474 CodeCompletionAllocator &Allocator,
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002475 CodeCompletionTUInfo &CCTUInfo,
2476 bool IncludeBriefComments) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002477 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002478
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002479 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002480 if (Kind == RK_Pattern) {
2481 Pattern->Priority = Priority;
2482 Pattern->Availability = Availability;
Douglas Gregorba103062012-03-27 23:34:16 +00002483
2484 if (Declaration) {
2485 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregorba103062012-03-27 23:34:16 +00002486 Pattern->ParentName = Result.getParentName();
2487 }
2488
Douglas Gregor218937c2011-02-01 19:23:04 +00002489 return Pattern;
2490 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002491
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002492 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002493 Result.AddTypedTextChunk(Keyword);
2494 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002495 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002496
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002497 if (Kind == RK_Macro) {
Douglas Gregor3644d972012-10-09 16:01:50 +00002498 MacroInfo *MI = PP.getMacroInfoHistory(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002499 assert(MI && "Not a macro?");
2500
Douglas Gregordae68752011-02-01 22:57:45 +00002501 Result.AddTypedTextChunk(
2502 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002503
2504 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002505 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002506
2507 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002508 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregore4244702011-07-30 08:17:44 +00002509 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002510
2511 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2512 if (MI->isC99Varargs()) {
2513 --AEnd;
2514
2515 if (A == AEnd) {
2516 Result.AddPlaceholderChunk("...");
2517 }
Douglas Gregore4244702011-07-30 08:17:44 +00002518 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002519
Douglas Gregore4244702011-07-30 08:17:44 +00002520 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002521 if (A != MI->arg_begin())
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002522 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002523
2524 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002525 SmallString<32> Arg = (*A)->getName();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002526 if (MI->isC99Varargs())
2527 Arg += ", ...";
2528 else
2529 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002530 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002531 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002532 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002533
2534 // Non-variadic macros are simple.
2535 Result.AddPlaceholderChunk(
2536 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002537 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002538 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002539 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002540 }
2541
Douglas Gregord8e8a582010-05-25 21:41:55 +00002542 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002543 NamedDecl *ND = Declaration;
Douglas Gregorba103062012-03-27 23:34:16 +00002544 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002545
2546 if (IncludeBriefComments) {
2547 // Add documentation comment, if it exists.
Dmitri Gribenkof50555e2012-08-11 00:51:43 +00002548 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002549 Result.addBriefComment(RC->getBriefText(Ctx));
2550 }
2551 }
2552
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002553 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002554 Result.AddTypedTextChunk(
2555 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002556 Result.AddTextChunk("::");
2557 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002558 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002559
2560 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2561 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2562 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2563 }
2564 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002565
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002566 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002567
Douglas Gregor86d9a522009-09-21 16:56:56 +00002568 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002569 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002570 Ctx, Policy);
2571 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002572 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002573 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002574 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002575 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002576 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002577 }
2578
2579 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002580 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002581 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002582 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002583 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002584
Douglas Gregor86d9a522009-09-21 16:56:56 +00002585 // Figure out which template parameters are deduced (or have default
2586 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002587 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002588 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002589 unsigned LastDeducibleArgument;
2590 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2591 --LastDeducibleArgument) {
2592 if (!Deduced[LastDeducibleArgument - 1]) {
2593 // C++0x: Figure out if the template argument has a default. If so,
2594 // the user doesn't need to type this argument.
2595 // FIXME: We need to abstract template parameters better!
2596 bool HasDefaultArg = false;
2597 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002598 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002599 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2600 HasDefaultArg = TTP->hasDefaultArgument();
2601 else if (NonTypeTemplateParmDecl *NTTP
2602 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2603 HasDefaultArg = NTTP->hasDefaultArgument();
2604 else {
2605 assert(isa<TemplateTemplateParmDecl>(Param));
2606 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002607 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002608 }
2609
2610 if (!HasDefaultArg)
2611 break;
2612 }
2613 }
2614
2615 if (LastDeducibleArgument) {
2616 // Some of the function template arguments cannot be deduced from a
2617 // function call, so we introduce an explicit template argument list
2618 // containing all of the arguments up to the first deducible argument.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002619 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002620 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002621 LastDeducibleArgument);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002622 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002623 }
2624
2625 // Add the function parameters
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002626 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002627 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002628 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002629 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002630 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002631 }
2632
2633 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002634 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002635 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002636 Result.AddTypedTextChunk(
2637 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002638 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002639 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002640 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor218937c2011-02-01 19:23:04 +00002641 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002642 }
2643
Douglas Gregor9630eb62009-11-17 16:44:22 +00002644 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002645 Selector Sel = Method->getSelector();
2646 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002647 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002648 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002649 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002650 }
2651
Douglas Gregor813d8342011-02-18 22:29:55 +00002652 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002653 SelName += ':';
2654 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002655 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002656 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002657 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002658
2659 // If there is only one parameter, and we're past it, add an empty
2660 // typed-text chunk since there is nothing to type.
2661 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002662 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002663 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002664 unsigned Idx = 0;
2665 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2666 PEnd = Method->param_end();
2667 P != PEnd; (void)++P, ++Idx) {
2668 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002669 std::string Keyword;
2670 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002671 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002672 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002673 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002674 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002675 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002676 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002677 else
Douglas Gregordae68752011-02-01 22:57:45 +00002678 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002679 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002680
2681 // If we're before the starting parameter, skip the placeholder.
2682 if (Idx < StartParameter)
2683 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002684
2685 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002686
2687 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002688 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002689 else {
John McCallf85e1932011-06-15 23:02:42 +00002690 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002691 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2692 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002693 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002694 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002695 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002696 }
2697
Douglas Gregore17794f2010-08-31 05:13:43 +00002698 if (Method->isVariadic() && (P + 1) == PEnd)
2699 Arg += ", ...";
2700
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002701 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002702 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002703 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002704 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002705 else
Douglas Gregordae68752011-02-01 22:57:45 +00002706 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002707 }
2708
Douglas Gregor2a17af02009-12-23 00:21:46 +00002709 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002710 if (Method->param_size() == 0) {
2711 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002712 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002713 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002714 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002715 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002716 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002717 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002718
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002719 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002720 }
2721
Douglas Gregor218937c2011-02-01 19:23:04 +00002722 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002723 }
2724
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002725 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002726 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002727 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002728
Douglas Gregordae68752011-02-01 22:57:45 +00002729 Result.AddTypedTextChunk(
2730 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002731 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002732}
2733
Douglas Gregor86d802e2009-09-23 00:34:09 +00002734CodeCompletionString *
2735CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2736 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002737 Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002738 CodeCompletionAllocator &Allocator,
2739 CodeCompletionTUInfo &CCTUInfo) const {
Douglas Gregor8987b232011-09-27 23:30:47 +00002740 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002741
Douglas Gregor218937c2011-02-01 19:23:04 +00002742 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002743 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002744 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002745 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002746 const FunctionProtoType *Proto
2747 = dyn_cast<FunctionProtoType>(getFunctionType());
2748 if (!FDecl && !Proto) {
2749 // Function without a prototype. Just give the return type and a
2750 // highlighted ellipsis.
2751 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002752 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002753 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002754 Result.getAllocator()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002755 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2756 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2757 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002758 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002759 }
2760
2761 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002762 Result.AddTextChunk(
2763 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002764 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002765 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002766 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002767 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002768
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002769 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002770 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2771 for (unsigned I = 0; I != NumParams; ++I) {
2772 if (I)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002773 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002774
2775 std::string ArgString;
2776 QualType ArgType;
2777
2778 if (FDecl) {
2779 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2780 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2781 } else {
2782 ArgType = Proto->getArgType(I);
2783 }
2784
John McCallf85e1932011-06-15 23:02:42 +00002785 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002786
2787 if (I == CurrentArg)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002788 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2789 Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002790 else
Douglas Gregordae68752011-02-01 22:57:45 +00002791 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002792 }
2793
2794 if (Proto && Proto->isVariadic()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002795 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002796 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002797 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002798 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002799 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002800 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002801 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002802
Douglas Gregor218937c2011-02-01 19:23:04 +00002803 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002804}
2805
Chris Lattner5f9e2722011-07-23 10:55:15 +00002806unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002807 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002808 bool PreferredTypeIsPointer) {
2809 unsigned Priority = CCP_Macro;
2810
Douglas Gregorb05496d2010-09-20 21:11:48 +00002811 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2812 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2813 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002814 Priority = CCP_Constant;
2815 if (PreferredTypeIsPointer)
2816 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002817 }
2818 // Treat "YES", "NO", "true", and "false" as constants.
2819 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2820 MacroName.equals("true") || MacroName.equals("false"))
2821 Priority = CCP_Constant;
2822 // Treat "bool" as a type.
2823 else if (MacroName.equals("bool"))
2824 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2825
Douglas Gregor1827e102010-08-16 16:18:59 +00002826
2827 return Priority;
2828}
2829
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002830CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2831 if (!D)
2832 return CXCursor_UnexposedDecl;
2833
2834 switch (D->getKind()) {
2835 case Decl::Enum: return CXCursor_EnumDecl;
2836 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2837 case Decl::Field: return CXCursor_FieldDecl;
2838 case Decl::Function:
2839 return CXCursor_FunctionDecl;
2840 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2841 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002842 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002843
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002844 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002845 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2846 case Decl::ObjCMethod:
2847 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2848 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2849 case Decl::CXXMethod: return CXCursor_CXXMethod;
2850 case Decl::CXXConstructor: return CXCursor_Constructor;
2851 case Decl::CXXDestructor: return CXCursor_Destructor;
2852 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2853 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002854 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002855 case Decl::ParmVar: return CXCursor_ParmDecl;
2856 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002857 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002858 case Decl::Var: return CXCursor_VarDecl;
2859 case Decl::Namespace: return CXCursor_Namespace;
2860 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2861 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2862 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2863 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2864 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2865 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002866 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002867 case Decl::ClassTemplatePartialSpecialization:
2868 return CXCursor_ClassTemplatePartialSpecialization;
2869 case Decl::UsingDirective: return CXCursor_UsingDirective;
Douglas Gregor8e5900c2012-04-30 23:41:16 +00002870 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002871
2872 case Decl::Using:
2873 case Decl::UnresolvedUsingValue:
2874 case Decl::UnresolvedUsingTypename:
2875 return CXCursor_UsingDeclaration;
2876
Douglas Gregor352697a2011-06-03 23:08:58 +00002877 case Decl::ObjCPropertyImpl:
2878 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2879 case ObjCPropertyImplDecl::Dynamic:
2880 return CXCursor_ObjCDynamicDecl;
2881
2882 case ObjCPropertyImplDecl::Synthesize:
2883 return CXCursor_ObjCSynthesizeDecl;
2884 }
Argyrios Kyrtzidis6a010122012-10-05 00:22:24 +00002885
2886 case Decl::Import:
2887 return CXCursor_ModuleImportDecl;
Douglas Gregor352697a2011-06-03 23:08:58 +00002888
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002889 default:
2890 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2891 switch (TD->getTagKind()) {
Joao Matos6666ed42012-08-31 18:45:21 +00002892 case TTK_Interface: // fall through
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002893 case TTK_Struct: return CXCursor_StructDecl;
2894 case TTK_Class: return CXCursor_ClassDecl;
2895 case TTK_Union: return CXCursor_UnionDecl;
2896 case TTK_Enum: return CXCursor_EnumDecl;
2897 }
2898 }
2899 }
2900
2901 return CXCursor_UnexposedDecl;
2902}
2903
Douglas Gregor590c7d52010-07-08 20:55:51 +00002904static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Douglas Gregor3644d972012-10-09 16:01:50 +00002905 bool IncludeUndefined,
Douglas Gregor590c7d52010-07-08 20:55:51 +00002906 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002907 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002908
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002909 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002910
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002911 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2912 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002913 M != MEnd; ++M) {
Douglas Gregor3644d972012-10-09 16:01:50 +00002914 if (IncludeUndefined || M->first->hasMacroDefinition())
2915 Results.AddResult(Result(M->first,
Douglas Gregor1827e102010-08-16 16:18:59 +00002916 getMacroUsagePriority(M->first->getName(),
David Blaikie4e4d0842012-03-11 07:00:24 +00002917 PP.getLangOpts(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002918 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002919 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002920
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002921 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002922
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002923}
2924
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002925static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2926 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002927 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002928
2929 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002930
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002931 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2932 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2933 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2934 Results.AddResult(Result("__func__", CCP_Constant));
2935 Results.ExitScope();
2936}
2937
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002938static void HandleCodeCompleteResults(Sema *S,
2939 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002940 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002941 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002942 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002943 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002944 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002945}
2946
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002947static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2948 Sema::ParserCompletionContext PCC) {
2949 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002950 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002951 return CodeCompletionContext::CCC_TopLevel;
2952
John McCallf312b1e2010-08-26 23:41:50 +00002953 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002954 return CodeCompletionContext::CCC_ClassStructUnion;
2955
John McCallf312b1e2010-08-26 23:41:50 +00002956 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002957 return CodeCompletionContext::CCC_ObjCInterface;
2958
John McCallf312b1e2010-08-26 23:41:50 +00002959 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002960 return CodeCompletionContext::CCC_ObjCImplementation;
2961
John McCallf312b1e2010-08-26 23:41:50 +00002962 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002963 return CodeCompletionContext::CCC_ObjCIvarList;
2964
John McCallf312b1e2010-08-26 23:41:50 +00002965 case Sema::PCC_Template:
2966 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002967 if (S.CurContext->isFileContext())
2968 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002969 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002970 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002971 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002972
John McCallf312b1e2010-08-26 23:41:50 +00002973 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002974 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002975
John McCallf312b1e2010-08-26 23:41:50 +00002976 case Sema::PCC_ForInit:
David Blaikie4e4d0842012-03-11 07:00:24 +00002977 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2978 S.getLangOpts().ObjC1)
Douglas Gregora5450a02010-10-18 22:01:46 +00002979 return CodeCompletionContext::CCC_ParenthesizedExpression;
2980 else
2981 return CodeCompletionContext::CCC_Expression;
2982
2983 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002984 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002985 return CodeCompletionContext::CCC_Expression;
2986
John McCallf312b1e2010-08-26 23:41:50 +00002987 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002988 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002989
John McCallf312b1e2010-08-26 23:41:50 +00002990 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002991 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002992
2993 case Sema::PCC_ParenthesizedExpression:
2994 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002995
2996 case Sema::PCC_LocalDeclarationSpecifiers:
2997 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002998 }
David Blaikie7530c032012-01-17 06:56:22 +00002999
3000 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003001}
3002
Douglas Gregorf6961522010-08-27 21:18:54 +00003003/// \brief If we're in a C++ virtual member function, add completion results
3004/// that invoke the functions we override, since it's common to invoke the
3005/// overridden function as well as adding new functionality.
3006///
3007/// \param S The semantic analysis object for which we are generating results.
3008///
3009/// \param InContext This context in which the nested-name-specifier preceding
3010/// the code-completion point
3011static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3012 ResultBuilder &Results) {
3013 // Look through blocks.
3014 DeclContext *CurContext = S.CurContext;
3015 while (isa<BlockDecl>(CurContext))
3016 CurContext = CurContext->getParent();
3017
3018
3019 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3020 if (!Method || !Method->isVirtual())
3021 return;
3022
3023 // We need to have names for all of the parameters, if we're going to
3024 // generate a forwarding call.
3025 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3026 PEnd = Method->param_end();
3027 P != PEnd;
3028 ++P) {
3029 if (!(*P)->getDeclName())
3030 return;
3031 }
3032
Douglas Gregor8987b232011-09-27 23:30:47 +00003033 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00003034 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
3035 MEnd = Method->end_overridden_methods();
3036 M != MEnd; ++M) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003037 CodeCompletionBuilder Builder(Results.getAllocator(),
3038 Results.getCodeCompletionTUInfo());
Douglas Gregorf6961522010-08-27 21:18:54 +00003039 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
3040 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3041 continue;
3042
3043 // If we need a nested-name-specifier, add one now.
3044 if (!InContext) {
3045 NestedNameSpecifier *NNS
3046 = getRequiredQualification(S.Context, CurContext,
3047 Overridden->getDeclContext());
3048 if (NNS) {
3049 std::string Str;
3050 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00003051 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00003052 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003053 }
3054 } else if (!InContext->Equals(Overridden->getDeclContext()))
3055 continue;
3056
Douglas Gregordae68752011-02-01 22:57:45 +00003057 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003058 Overridden->getNameAsString()));
3059 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00003060 bool FirstParam = true;
3061 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3062 PEnd = Method->param_end();
3063 P != PEnd; ++P) {
3064 if (FirstParam)
3065 FirstParam = false;
3066 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003067 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003068
Douglas Gregordae68752011-02-01 22:57:45 +00003069 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003070 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003071 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003072 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3073 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003074 CCP_SuperCompletion,
Douglas Gregorba103062012-03-27 23:34:16 +00003075 CXCursor_CXXMethod,
3076 CXAvailability_Available,
3077 Overridden));
Douglas Gregorf6961522010-08-27 21:18:54 +00003078 Results.Ignore(Overridden);
3079 }
3080}
3081
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003082void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3083 ModuleIdPath Path) {
3084 typedef CodeCompletionResult Result;
3085 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003086 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003087 CodeCompletionContext::CCC_Other);
3088 Results.EnterNewScope();
3089
3090 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003091 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003092 typedef CodeCompletionResult Result;
3093 if (Path.empty()) {
3094 // Enumerate all top-level modules.
3095 llvm::SmallVector<Module *, 8> Modules;
3096 PP.getHeaderSearchInfo().collectAllModules(Modules);
3097 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3098 Builder.AddTypedTextChunk(
3099 Builder.getAllocator().CopyString(Modules[I]->Name));
3100 Results.AddResult(Result(Builder.TakeString(),
3101 CCP_Declaration,
3102 CXCursor_NotImplemented,
3103 Modules[I]->isAvailable()
3104 ? CXAvailability_Available
3105 : CXAvailability_NotAvailable));
3106 }
3107 } else {
3108 // Load the named module.
3109 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3110 Module::AllVisible,
3111 /*IsInclusionDirective=*/false);
3112 // Enumerate submodules.
3113 if (Mod) {
3114 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3115 SubEnd = Mod->submodule_end();
3116 Sub != SubEnd; ++Sub) {
3117
3118 Builder.AddTypedTextChunk(
3119 Builder.getAllocator().CopyString((*Sub)->Name));
3120 Results.AddResult(Result(Builder.TakeString(),
3121 CCP_Declaration,
3122 CXCursor_NotImplemented,
3123 (*Sub)->isAvailable()
3124 ? CXAvailability_Available
3125 : CXAvailability_NotAvailable));
3126 }
3127 }
3128 }
3129 Results.ExitScope();
3130 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3131 Results.data(),Results.size());
3132}
3133
Douglas Gregor01dfea02010-01-10 23:08:15 +00003134void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003135 ParserCompletionContext CompletionContext) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003136 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003137 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003138 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003139 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003140
Douglas Gregor01dfea02010-01-10 23:08:15 +00003141 // Determine how to filter results, e.g., so that the names of
3142 // values (functions, enumerators, function templates, etc.) are
3143 // only allowed where we can have an expression.
3144 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003145 case PCC_Namespace:
3146 case PCC_Class:
3147 case PCC_ObjCInterface:
3148 case PCC_ObjCImplementation:
3149 case PCC_ObjCInstanceVariableList:
3150 case PCC_Template:
3151 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003152 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003153 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003154 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3155 break;
3156
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003157 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003158 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003159 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003160 case PCC_ForInit:
3161 case PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00003162 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003163 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3164 else
3165 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003166
David Blaikie4e4d0842012-03-11 07:00:24 +00003167 if (getLangOpts().CPlusPlus)
Douglas Gregorf6961522010-08-27 21:18:54 +00003168 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003169 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003170
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003171 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003172 // Unfiltered
3173 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003174 }
3175
Douglas Gregor3cdee122010-08-26 16:36:48 +00003176 // If we are in a C++ non-static member function, check the qualifiers on
3177 // the member function to filter/prioritize the results list.
3178 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3179 if (CurMethod->isInstance())
3180 Results.setObjectTypeQualifiers(
3181 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3182
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003183 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003184 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3185 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003186
Douglas Gregorbca403c2010-01-13 23:51:12 +00003187 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003188 Results.ExitScope();
3189
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003190 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003191 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003192 case PCC_Expression:
3193 case PCC_Statement:
3194 case PCC_RecoveryInFunction:
3195 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003196 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor72db1082010-08-24 01:11:00 +00003197 break;
3198
3199 case PCC_Namespace:
3200 case PCC_Class:
3201 case PCC_ObjCInterface:
3202 case PCC_ObjCImplementation:
3203 case PCC_ObjCInstanceVariableList:
3204 case PCC_Template:
3205 case PCC_MemberTemplate:
3206 case PCC_ForInit:
3207 case PCC_Condition:
3208 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003209 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003210 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003211 }
3212
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003213 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003214 AddMacroResults(PP, Results, false);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003215
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003216 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003217 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003218}
3219
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003220static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3221 ParsedType Receiver,
3222 IdentifierInfo **SelIdents,
3223 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003224 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003225 bool IsSuper,
3226 ResultBuilder &Results);
3227
3228void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3229 bool AllowNonIdentifiers,
3230 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003231 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003232 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003233 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003234 AllowNestedNameSpecifiers
3235 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3236 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003237 Results.EnterNewScope();
3238
3239 // Type qualifiers can come after names.
3240 Results.AddResult(Result("const"));
3241 Results.AddResult(Result("volatile"));
David Blaikie4e4d0842012-03-11 07:00:24 +00003242 if (getLangOpts().C99)
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003243 Results.AddResult(Result("restrict"));
3244
David Blaikie4e4d0842012-03-11 07:00:24 +00003245 if (getLangOpts().CPlusPlus) {
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003246 if (AllowNonIdentifiers) {
3247 Results.AddResult(Result("operator"));
3248 }
3249
3250 // Add nested-name-specifiers.
3251 if (AllowNestedNameSpecifiers) {
3252 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003253 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003254 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3255 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3256 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003257 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003258 }
3259 }
3260 Results.ExitScope();
3261
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003262 // If we're in a context where we might have an expression (rather than a
3263 // declaration), and what we've seen so far is an Objective-C type that could
3264 // be a receiver of a class message, this may be a class message send with
3265 // the initial opening bracket '[' missing. Add appropriate completions.
3266 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3267 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3268 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3269 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3270 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3271 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3272 DS.getTypeQualifiers() == 0 &&
3273 S &&
3274 (S->getFlags() & Scope::DeclScope) != 0 &&
3275 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3276 Scope::FunctionPrototypeScope |
3277 Scope::AtCatchScope)) == 0) {
3278 ParsedType T = DS.getRepAsType();
3279 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003280 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003281 }
3282
Douglas Gregor4497dd42010-08-24 04:59:56 +00003283 // Note that we intentionally suppress macro results here, since we do not
3284 // encourage using macros to produce the names of entities.
3285
Douglas Gregor52779fb2010-09-23 23:01:17 +00003286 HandleCodeCompleteResults(this, CodeCompleter,
3287 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003288 Results.data(), Results.size());
3289}
3290
Douglas Gregorfb629412010-08-23 21:17:50 +00003291struct Sema::CodeCompleteExpressionData {
3292 CodeCompleteExpressionData(QualType PreferredType = QualType())
3293 : PreferredType(PreferredType), IntegralConstantExpression(false),
3294 ObjCCollection(false) { }
3295
3296 QualType PreferredType;
3297 bool IntegralConstantExpression;
3298 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003299 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003300};
3301
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003302/// \brief Perform code-completion in an expression context when we know what
3303/// type we're looking for.
Douglas Gregorfb629412010-08-23 21:17:50 +00003304void Sema::CodeCompleteExpression(Scope *S,
3305 const CodeCompleteExpressionData &Data) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003306 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003307 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003308 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003309 if (Data.ObjCCollection)
3310 Results.setFilter(&ResultBuilder::IsObjCCollection);
3311 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003312 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikie4e4d0842012-03-11 07:00:24 +00003313 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003314 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3315 else
3316 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003317
3318 if (!Data.PreferredType.isNull())
3319 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3320
3321 // Ignore any declarations that we were told that we don't care about.
3322 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3323 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003324
3325 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003326 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3327 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003328
3329 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003330 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003331 Results.ExitScope();
3332
Douglas Gregor590c7d52010-07-08 20:55:51 +00003333 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003334 if (!Data.PreferredType.isNull())
3335 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3336 || Data.PreferredType->isMemberPointerType()
3337 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003338
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003339 if (S->getFnParent() &&
3340 !Data.ObjCCollection &&
3341 !Data.IntegralConstantExpression)
David Blaikie4e4d0842012-03-11 07:00:24 +00003342 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003343
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003344 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003345 AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003346 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003347 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3348 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003349 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003350}
3351
Douglas Gregorac5fd842010-09-18 01:28:11 +00003352void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3353 if (E.isInvalid())
3354 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikie4e4d0842012-03-11 07:00:24 +00003355 else if (getLangOpts().ObjC1)
Douglas Gregorac5fd842010-09-18 01:28:11 +00003356 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003357}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003358
Douglas Gregor73449212010-12-09 23:01:55 +00003359/// \brief The set of properties that have already been added, referenced by
3360/// property name.
3361typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3362
Douglas Gregorb92a4082012-06-12 13:44:08 +00003363/// \brief Retrieve the container definition, if any?
3364static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3365 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3366 if (Interface->hasDefinition())
3367 return Interface->getDefinition();
3368
3369 return Interface;
3370 }
3371
3372 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3373 if (Protocol->hasDefinition())
3374 return Protocol->getDefinition();
3375
3376 return Protocol;
3377 }
3378 return Container;
3379}
3380
3381static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003382 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003383 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003384 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003385 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003386 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003387 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003388
Douglas Gregorb92a4082012-06-12 13:44:08 +00003389 // Retrieve the definition.
3390 Container = getContainerDef(Container);
3391
Douglas Gregor95ac6552009-11-18 01:29:26 +00003392 // Add properties in this container.
3393 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3394 PEnd = Container->prop_end();
3395 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003396 ++P) {
3397 if (AddedProperties.insert(P->getIdentifier()))
David Blaikie581deb32012-06-06 20:45:41 +00003398 Results.MaybeAddResult(Result(*P, 0), CurContext);
Douglas Gregor73449212010-12-09 23:01:55 +00003399 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003400
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003401 // Add nullary methods
3402 if (AllowNullaryMethods) {
3403 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003404 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003405 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3406 MEnd = Container->meth_end();
3407 M != MEnd; ++M) {
3408 if (M->getSelector().isUnarySelector())
3409 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3410 if (AddedProperties.insert(Name)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003411 CodeCompletionBuilder Builder(Results.getAllocator(),
3412 Results.getCodeCompletionTUInfo());
David Blaikie581deb32012-06-06 20:45:41 +00003413 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003414 Builder.AddTypedTextChunk(
3415 Results.getAllocator().CopyString(Name->getName()));
3416
David Blaikie581deb32012-06-06 20:45:41 +00003417 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
Douglas Gregorba103062012-03-27 23:34:16 +00003418 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003419 CurContext);
3420 }
3421 }
3422 }
3423
3424
Douglas Gregor95ac6552009-11-18 01:29:26 +00003425 // Add properties in referenced protocols.
3426 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3427 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3428 PEnd = Protocol->protocol_end();
3429 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003430 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3431 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003432 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003433 if (AllowCategories) {
3434 // Look through categories.
3435 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3436 Category; Category = Category->getNextClassCategory())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003437 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3438 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003439 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003440
3441 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003442 for (ObjCInterfaceDecl::all_protocol_iterator
3443 I = IFace->all_referenced_protocol_begin(),
3444 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003445 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3446 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003447
3448 // Look in the superclass.
3449 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003450 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3451 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003452 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003453 } else if (const ObjCCategoryDecl *Category
3454 = dyn_cast<ObjCCategoryDecl>(Container)) {
3455 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003456 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3457 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003458 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003459 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3460 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003461 }
3462}
3463
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003464void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003465 SourceLocation OpLoc,
3466 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003467 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003468 return;
3469
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003470 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3471 if (ConvertedBase.isInvalid())
3472 return;
3473 Base = ConvertedBase.get();
3474
John McCall0a2c5e22010-08-25 06:19:51 +00003475 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003476
Douglas Gregor81b747b2009-09-17 21:32:03 +00003477 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003478
3479 if (IsArrow) {
3480 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3481 BaseType = Ptr->getPointeeType();
3482 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003483 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003484 else
3485 return;
3486 }
3487
Douglas Gregor3da626b2011-07-07 16:03:39 +00003488 enum CodeCompletionContext::Kind contextKind;
3489
3490 if (IsArrow) {
3491 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3492 }
3493 else {
3494 if (BaseType->isObjCObjectPointerType() ||
3495 BaseType->isObjCObjectOrInterfaceType()) {
3496 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3497 }
3498 else {
3499 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3500 }
3501 }
3502
Douglas Gregor218937c2011-02-01 19:23:04 +00003503 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003504 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003505 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003506 BaseType),
3507 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003508 Results.EnterNewScope();
3509 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003510 // Indicate that we are performing a member access, and the cv-qualifiers
3511 // for the base object type.
3512 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3513
Douglas Gregor95ac6552009-11-18 01:29:26 +00003514 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003515 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003516 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003517 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3518 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003519
David Blaikie4e4d0842012-03-11 07:00:24 +00003520 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003521 if (!Results.empty()) {
3522 // The "template" keyword can follow "->" or "." in the grammar.
3523 // However, we only want to suggest the template keyword if something
3524 // is dependent.
3525 bool IsDependent = BaseType->isDependentType();
3526 if (!IsDependent) {
3527 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3528 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3529 IsDependent = Ctx->isDependentContext();
3530 break;
3531 }
3532 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003533
Douglas Gregor95ac6552009-11-18 01:29:26 +00003534 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003535 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003536 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003537 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003538 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3539 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003540 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003541
3542 // Add property results based on our interface.
3543 const ObjCObjectPointerType *ObjCPtr
3544 = BaseType->getAsObjCInterfacePointerType();
3545 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003546 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3547 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003548 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003549
3550 // Add properties from the protocols in a qualified interface.
3551 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3552 E = ObjCPtr->qual_end();
3553 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003554 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3555 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003556 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003557 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003558 // Objective-C instance variable access.
3559 ObjCInterfaceDecl *Class = 0;
3560 if (const ObjCObjectPointerType *ObjCPtr
3561 = BaseType->getAs<ObjCObjectPointerType>())
3562 Class = ObjCPtr->getInterfaceDecl();
3563 else
John McCallc12c5bb2010-05-15 11:32:37 +00003564 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003565
3566 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003567 if (Class) {
3568 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3569 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003570 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3571 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003572 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003573 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003574
3575 // FIXME: How do we cope with isa?
3576
3577 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003578
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003579 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003580 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003581 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003582 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003583}
3584
Douglas Gregor374929f2009-09-18 15:37:17 +00003585void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3586 if (!CodeCompleter)
3587 return;
3588
Douglas Gregor86d9a522009-09-21 16:56:56 +00003589 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003590 enum CodeCompletionContext::Kind ContextKind
3591 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003592 switch ((DeclSpec::TST)TagSpec) {
3593 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003594 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003595 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003596 break;
3597
3598 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003599 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003600 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003601 break;
3602
3603 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003604 case DeclSpec::TST_class:
Joao Matos6666ed42012-08-31 18:45:21 +00003605 case DeclSpec::TST_interface:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003606 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003607 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003608 break;
3609
3610 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003611 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003612 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003613
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003614 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3615 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003616 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003617
3618 // First pass: look for tags.
3619 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003620 LookupVisibleDecls(S, LookupTagName, Consumer,
3621 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003622
Douglas Gregor8071e422010-08-15 06:18:01 +00003623 if (CodeCompleter->includeGlobals()) {
3624 // Second pass: look for nested name specifiers.
3625 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3626 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3627 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003628
Douglas Gregor52779fb2010-09-23 23:01:17 +00003629 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003630 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003631}
3632
Douglas Gregor1a480c42010-08-27 17:35:51 +00003633void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003634 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003635 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003636 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003637 Results.EnterNewScope();
3638 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3639 Results.AddResult("const");
3640 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3641 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003642 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003643 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3644 Results.AddResult("restrict");
3645 Results.ExitScope();
3646 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003647 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003648 Results.data(), Results.size());
3649}
3650
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003651void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003652 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003653 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003654
John McCall781472f2010-08-25 08:40:02 +00003655 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003656 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3657 if (!type->isEnumeralType()) {
3658 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003659 Data.IntegralConstantExpression = true;
3660 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003661 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003662 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003663
3664 // Code-complete the cases of a switch statement over an enumeration type
3665 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003666 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregorb92a4082012-06-12 13:44:08 +00003667 if (EnumDecl *Def = Enum->getDefinition())
3668 Enum = Def;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003669
3670 // Determine which enumerators we have already seen in the switch statement.
3671 // FIXME: Ideally, we would also be able to look *past* the code-completion
3672 // token, in case we are code-completing in the middle of the switch and not
3673 // at the end. However, we aren't able to do so at the moment.
3674 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003675 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003676 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3677 SC = SC->getNextSwitchCase()) {
3678 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3679 if (!Case)
3680 continue;
3681
3682 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3683 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3684 if (EnumConstantDecl *Enumerator
3685 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3686 // We look into the AST of the case statement to determine which
3687 // enumerator was named. Alternatively, we could compute the value of
3688 // the integral constant expression, then compare it against the
3689 // values of each enumerator. However, value-based approach would not
3690 // work as well with C++ templates where enumerators declared within a
3691 // template are type- and value-dependent.
3692 EnumeratorsSeen.insert(Enumerator);
3693
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003694 // If this is a qualified-id, keep track of the nested-name-specifier
3695 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003696 //
3697 // switch (TagD.getKind()) {
3698 // case TagDecl::TK_enum:
3699 // break;
3700 // case XXX
3701 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003702 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003703 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3704 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003705 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003706 }
3707 }
3708
David Blaikie4e4d0842012-03-11 07:00:24 +00003709 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003710 // If there are no prior enumerators in C++, check whether we have to
3711 // qualify the names of the enumerators that we suggest, because they
3712 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003713 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003714 }
3715
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003716 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003717 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003718 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003719 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003720 Results.EnterNewScope();
3721 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3722 EEnd = Enum->enumerator_end();
3723 E != EEnd; ++E) {
David Blaikie581deb32012-06-06 20:45:41 +00003724 if (EnumeratorsSeen.count(*E))
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003725 continue;
3726
David Blaikie581deb32012-06-06 20:45:41 +00003727 CodeCompletionResult R(*E, Qualifier);
Douglas Gregor5c722c702011-02-18 23:30:37 +00003728 R.Priority = CCP_EnumInCase;
3729 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003730 }
3731 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003732
Douglas Gregor3da626b2011-07-07 16:03:39 +00003733 //We need to make sure we're setting the right context,
3734 //so only say we include macros if the code completer says we do
3735 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3736 if (CodeCompleter->includeMacros()) {
Douglas Gregor3644d972012-10-09 16:01:50 +00003737 AddMacroResults(PP, Results, false);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003738 kind = CodeCompletionContext::CCC_OtherWithMacros;
3739 }
3740
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003741 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003742 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003743 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003744}
3745
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003746namespace {
3747 struct IsBetterOverloadCandidate {
3748 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003749 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003750
3751 public:
John McCall5769d612010-02-08 23:07:23 +00003752 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3753 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003754
3755 bool
3756 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003757 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003758 }
3759 };
3760}
3761
Ahmed Charles13a140c2012-02-25 11:00:22 +00003762static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3763 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003764 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003765
3766 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003767 if (!Args[I])
3768 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003769
Douglas Gregord28dcd72010-05-30 06:10:08 +00003770 return false;
3771}
3772
Richard Trieuf81e5a92011-09-09 02:00:50 +00003773void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charles13a140c2012-02-25 11:00:22 +00003774 llvm::ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003775 if (!CodeCompleter)
3776 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003777
3778 // When we're code-completing for a call, we fall back to ordinary
3779 // name code-completion whenever we can't produce specific
3780 // results. We may want to revisit this strategy in the future,
3781 // e.g., by merging the two kinds of results.
3782
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003783 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003784
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003785 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003786 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3787 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003788 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003789 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003790 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003791
John McCall3b4294e2009-12-16 12:17:52 +00003792 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003793 SourceLocation Loc = Fn->getExprLoc();
3794 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003795
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003796 // FIXME: What if we're calling something that isn't a function declaration?
3797 // FIXME: What if we're calling a pseudo-destructor?
3798 // FIXME: What if we're calling a member function?
3799
Douglas Gregorc0265402010-01-21 15:46:19 +00003800 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003801 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003802
John McCall3b4294e2009-12-16 12:17:52 +00003803 Expr *NakedFn = Fn->IgnoreParenCasts();
3804 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003805 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003806 /*PartialOverloading=*/ true);
3807 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3808 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003809 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003810 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003811 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003812 Results.push_back(ResultCandidate(FDecl));
3813 else
John McCall86820f52010-01-26 01:37:31 +00003814 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003815 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3816 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003817 }
John McCall3b4294e2009-12-16 12:17:52 +00003818 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003819
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003820 QualType ParamType;
3821
Douglas Gregorc0265402010-01-21 15:46:19 +00003822 if (!CandidateSet.empty()) {
3823 // Sort the overload candidate set by placing the best overloads first.
3824 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003825 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003826
Douglas Gregorc0265402010-01-21 15:46:19 +00003827 // Add the remaining viable overload candidates as code-completion reslults.
3828 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3829 CandEnd = CandidateSet.end();
3830 Cand != CandEnd; ++Cand) {
3831 if (Cand->Viable)
3832 Results.push_back(ResultCandidate(Cand->Function));
3833 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003834
3835 // From the viable candidates, try to determine the type of this parameter.
3836 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3837 if (const FunctionType *FType = Results[I].getFunctionType())
3838 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003839 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003840 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003841 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003842 else if (!Context.hasSameUnqualifiedType(
3843 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003844 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003845 ParamType = QualType();
3846 break;
3847 }
3848 }
3849 }
3850 } else {
3851 // Try to determine the parameter type from the type of the expression
3852 // being called.
3853 QualType FunctionType = Fn->getType();
3854 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3855 FunctionType = Ptr->getPointeeType();
3856 else if (const BlockPointerType *BlockPtr
3857 = FunctionType->getAs<BlockPointerType>())
3858 FunctionType = BlockPtr->getPointeeType();
3859 else if (const MemberPointerType *MemPtr
3860 = FunctionType->getAs<MemberPointerType>())
3861 FunctionType = MemPtr->getPointeeType();
3862
3863 if (const FunctionProtoType *Proto
3864 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003865 if (Args.size() < Proto->getNumArgs())
3866 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003867 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003868 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003869
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003870 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003871 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003872 else
3873 CodeCompleteExpression(S, ParamType);
3874
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003875 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003876 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003877 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003878}
3879
John McCalld226f652010-08-21 09:40:31 +00003880void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3881 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003882 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003883 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003884 return;
3885 }
3886
3887 CodeCompleteExpression(S, VD->getType());
3888}
3889
3890void Sema::CodeCompleteReturn(Scope *S) {
3891 QualType ResultType;
3892 if (isa<BlockDecl>(CurContext)) {
3893 if (BlockScopeInfo *BSI = getCurBlock())
3894 ResultType = BSI->ReturnType;
3895 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3896 ResultType = Function->getResultType();
3897 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3898 ResultType = Method->getResultType();
3899
3900 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003901 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003902 else
3903 CodeCompleteExpression(S, ResultType);
3904}
3905
Douglas Gregord2d8be62011-07-30 08:36:53 +00003906void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregord2d8be62011-07-30 08:36:53 +00003907 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003908 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord2d8be62011-07-30 08:36:53 +00003909 mapCodeCompletionContext(*this, PCC_Statement));
3910 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3911 Results.EnterNewScope();
3912
3913 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3914 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3915 CodeCompleter->includeGlobals());
3916
3917 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3918
3919 // "else" block
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003920 CodeCompletionBuilder Builder(Results.getAllocator(),
3921 Results.getCodeCompletionTUInfo());
Douglas Gregord2d8be62011-07-30 08:36:53 +00003922 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00003923 if (Results.includeCodePatterns()) {
3924 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3925 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3926 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3927 Builder.AddPlaceholderChunk("statements");
3928 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3929 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3930 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003931 Results.AddResult(Builder.TakeString());
3932
3933 // "else if" block
3934 Builder.AddTypedTextChunk("else");
3935 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3936 Builder.AddTextChunk("if");
3937 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3938 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00003939 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00003940 Builder.AddPlaceholderChunk("condition");
3941 else
3942 Builder.AddPlaceholderChunk("expression");
3943 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00003944 if (Results.includeCodePatterns()) {
3945 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3946 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3947 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3948 Builder.AddPlaceholderChunk("statements");
3949 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3950 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3951 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003952 Results.AddResult(Builder.TakeString());
3953
3954 Results.ExitScope();
3955
3956 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003957 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003958
3959 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003960 AddMacroResults(PP, Results, false);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003961
3962 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3963 Results.data(),Results.size());
3964}
3965
Richard Trieuf81e5a92011-09-09 02:00:50 +00003966void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003967 if (LHS)
3968 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3969 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003970 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003971}
3972
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003973void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003974 bool EnteringContext) {
3975 if (!SS.getScopeRep() || !CodeCompleter)
3976 return;
3977
Douglas Gregor86d9a522009-09-21 16:56:56 +00003978 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3979 if (!Ctx)
3980 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003981
3982 // Try to instantiate any non-dependent declaration contexts before
3983 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003984 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003985 return;
3986
Douglas Gregor218937c2011-02-01 19:23:04 +00003987 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003988 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003989 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003990 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003991
Douglas Gregor86d9a522009-09-21 16:56:56 +00003992 // The "template" keyword can follow "::" in the grammar, but only
3993 // put it into the grammar if the nested-name-specifier is dependent.
3994 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3995 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003996 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003997
3998 // Add calls to overridden virtual functions, if there are any.
3999 //
4000 // FIXME: This isn't wonderful, because we don't know whether we're actually
4001 // in a context that permits expressions. This is a general issue with
4002 // qualified-id completions.
4003 if (!EnteringContext)
4004 MaybeAddOverrideCalls(*this, Ctx, Results);
4005 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004006
Douglas Gregorf6961522010-08-27 21:18:54 +00004007 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4008 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
4009
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004010 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00004011 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004012 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00004013}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004014
4015void Sema::CodeCompleteUsing(Scope *S) {
4016 if (!CodeCompleter)
4017 return;
4018
Douglas Gregor218937c2011-02-01 19:23:04 +00004019 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004020 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004021 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4022 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004023 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004024
4025 // If we aren't in class scope, we could see the "namespace" keyword.
4026 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00004027 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004028
4029 // After "using", we can see anything that would start a
4030 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004031 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004032 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4033 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004034 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004035
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004036 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004037 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004038 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004039}
4040
4041void Sema::CodeCompleteUsingDirective(Scope *S) {
4042 if (!CodeCompleter)
4043 return;
4044
Douglas Gregor86d9a522009-09-21 16:56:56 +00004045 // After "using namespace", we expect to see a namespace name or namespace
4046 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004047 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004048 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004049 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004050 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004051 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004052 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004053 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4054 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004055 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004056 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004057 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004058 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004059}
4060
4061void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4062 if (!CodeCompleter)
4063 return;
4064
Douglas Gregor86d9a522009-09-21 16:56:56 +00004065 DeclContext *Ctx = (DeclContext *)S->getEntity();
4066 if (!S->getParent())
4067 Ctx = Context.getTranslationUnitDecl();
4068
Douglas Gregor52779fb2010-09-23 23:01:17 +00004069 bool SuppressedGlobalResults
4070 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4071
Douglas Gregor218937c2011-02-01 19:23:04 +00004072 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004073 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004074 SuppressedGlobalResults
4075 ? CodeCompletionContext::CCC_Namespace
4076 : CodeCompletionContext::CCC_Other,
4077 &ResultBuilder::IsNamespace);
4078
4079 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004080 // We only want to see those namespaces that have already been defined
4081 // within this scope, because its likely that the user is creating an
4082 // extended namespace declaration. Keep track of the most recent
4083 // definition of each namespace.
4084 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4085 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4086 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4087 NS != NSEnd; ++NS)
David Blaikie581deb32012-06-06 20:45:41 +00004088 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004089
4090 // Add the most recent definition (or extended definition) of each
4091 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004092 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004093 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregorba103062012-03-27 23:34:16 +00004094 NS = OrigToLatest.begin(),
4095 NSEnd = OrigToLatest.end();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004096 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004097 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004098 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004099 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004100 }
4101
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004102 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004103 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004104 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004105}
4106
4107void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4108 if (!CodeCompleter)
4109 return;
4110
Douglas Gregor86d9a522009-09-21 16:56:56 +00004111 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004112 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004113 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004114 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004115 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004116 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004117 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4118 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004119 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004120 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004121 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004122}
4123
Douglas Gregored8d3222009-09-18 20:05:18 +00004124void Sema::CodeCompleteOperatorName(Scope *S) {
4125 if (!CodeCompleter)
4126 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004127
John McCall0a2c5e22010-08-25 06:19:51 +00004128 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004129 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004130 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004131 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004132 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004133 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004134
Douglas Gregor86d9a522009-09-21 16:56:56 +00004135 // Add the names of overloadable operators.
4136#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4137 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004138 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004139#include "clang/Basic/OperatorKinds.def"
4140
4141 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004142 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004143 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004144 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4145 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004146
4147 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004148 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004149 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004150
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004151 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004152 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004153 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004154}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004155
Douglas Gregor0133f522010-08-28 00:00:50 +00004156void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004157 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004158 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004159 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004160 CXXConstructorDecl *Constructor
4161 = static_cast<CXXConstructorDecl *>(ConstructorD);
4162 if (!Constructor)
4163 return;
4164
Douglas Gregor218937c2011-02-01 19:23:04 +00004165 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004166 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004167 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004168 Results.EnterNewScope();
4169
4170 // Fill in any already-initialized fields or base classes.
4171 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4172 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4173 for (unsigned I = 0; I != NumInitializers; ++I) {
4174 if (Initializers[I]->isBaseInitializer())
4175 InitializedBases.insert(
4176 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4177 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004178 InitializedFields.insert(cast<FieldDecl>(
4179 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004180 }
4181
4182 // Add completions for base classes.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004183 CodeCompletionBuilder Builder(Results.getAllocator(),
4184 Results.getCodeCompletionTUInfo());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004185 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004186 CXXRecordDecl *ClassDecl = Constructor->getParent();
4187 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4188 BaseEnd = ClassDecl->bases_end();
4189 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004190 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4191 SawLastInitializer
4192 = NumInitializers > 0 &&
4193 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4194 Context.hasSameUnqualifiedType(Base->getType(),
4195 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004196 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004197 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004198
Douglas Gregor218937c2011-02-01 19:23:04 +00004199 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004200 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004201 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004202 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4203 Builder.AddPlaceholderChunk("args");
4204 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4205 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004206 SawLastInitializer? CCP_NextInitializer
4207 : CCP_MemberDeclaration));
4208 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004209 }
4210
4211 // Add completions for virtual base classes.
4212 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4213 BaseEnd = ClassDecl->vbases_end();
4214 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004215 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4216 SawLastInitializer
4217 = NumInitializers > 0 &&
4218 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4219 Context.hasSameUnqualifiedType(Base->getType(),
4220 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004221 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004222 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004223
Douglas Gregor218937c2011-02-01 19:23:04 +00004224 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004225 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004226 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004227 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4228 Builder.AddPlaceholderChunk("args");
4229 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4230 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004231 SawLastInitializer? CCP_NextInitializer
4232 : CCP_MemberDeclaration));
4233 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004234 }
4235
4236 // Add completions for members.
4237 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4238 FieldEnd = ClassDecl->field_end();
4239 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004240 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4241 SawLastInitializer
4242 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004243 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
David Blaikie581deb32012-06-06 20:45:41 +00004244 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004245 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004246 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004247
4248 if (!Field->getDeclName())
4249 continue;
4250
Douglas Gregordae68752011-02-01 22:57:45 +00004251 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004252 Field->getIdentifier()->getName()));
4253 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4254 Builder.AddPlaceholderChunk("args");
4255 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4256 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004257 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004258 : CCP_MemberDeclaration,
Douglas Gregorba103062012-03-27 23:34:16 +00004259 CXCursor_MemberRef,
4260 CXAvailability_Available,
David Blaikie581deb32012-06-06 20:45:41 +00004261 *Field));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004262 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004263 }
4264 Results.ExitScope();
4265
Douglas Gregor52779fb2010-09-23 23:01:17 +00004266 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004267 Results.data(), Results.size());
4268}
4269
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004270/// \brief Determine whether this scope denotes a namespace.
4271static bool isNamespaceScope(Scope *S) {
4272 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4273 if (!DC)
4274 return false;
4275
4276 return DC->isFileContext();
4277}
4278
4279void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4280 bool AfterAmpersand) {
4281 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004282 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004283 CodeCompletionContext::CCC_Other);
4284 Results.EnterNewScope();
4285
4286 // Note what has already been captured.
4287 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4288 bool IncludedThis = false;
4289 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4290 CEnd = Intro.Captures.end();
4291 C != CEnd; ++C) {
4292 if (C->Kind == LCK_This) {
4293 IncludedThis = true;
4294 continue;
4295 }
4296
4297 Known.insert(C->Id);
4298 }
4299
4300 // Look for other capturable variables.
4301 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4302 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4303 D != DEnd; ++D) {
4304 VarDecl *Var = dyn_cast<VarDecl>(*D);
4305 if (!Var ||
4306 !Var->hasLocalStorage() ||
4307 Var->hasAttr<BlocksAttr>())
4308 continue;
4309
4310 if (Known.insert(Var->getIdentifier()))
4311 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4312 }
4313 }
4314
4315 // Add 'this', if it would be valid.
4316 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4317 addThisCompletion(*this, Results);
4318
4319 Results.ExitScope();
4320
4321 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4322 Results.data(), Results.size());
4323}
4324
James Dennetta40f7922012-06-14 03:11:41 +00004325/// Macro that optionally prepends an "@" to the string literal passed in via
4326/// Keyword, depending on whether NeedAt is true or false.
4327#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4328
Douglas Gregorbca403c2010-01-13 23:51:12 +00004329static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004330 ResultBuilder &Results,
4331 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004332 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004333 // Since we have an implementation, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004334 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004335
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004336 CodeCompletionBuilder Builder(Results.getAllocator(),
4337 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004338 if (LangOpts.ObjC2) {
4339 // @dynamic
James Dennetta40f7922012-06-14 03:11:41 +00004340 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004341 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4342 Builder.AddPlaceholderChunk("property");
4343 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004344
4345 // @synthesize
James Dennetta40f7922012-06-14 03:11:41 +00004346 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004347 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4348 Builder.AddPlaceholderChunk("property");
4349 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004350 }
4351}
4352
Douglas Gregorbca403c2010-01-13 23:51:12 +00004353static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004354 ResultBuilder &Results,
4355 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004356 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004357
4358 // Since we have an interface or protocol, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004359 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004360
4361 if (LangOpts.ObjC2) {
4362 // @property
James Dennetta40f7922012-06-14 03:11:41 +00004363 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004364
4365 // @required
James Dennetta40f7922012-06-14 03:11:41 +00004366 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004367
4368 // @optional
James Dennetta40f7922012-06-14 03:11:41 +00004369 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004370 }
4371}
4372
Douglas Gregorbca403c2010-01-13 23:51:12 +00004373static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004374 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004375 CodeCompletionBuilder Builder(Results.getAllocator(),
4376 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004377
4378 // @class name ;
James Dennetta40f7922012-06-14 03:11:41 +00004379 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004380 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4381 Builder.AddPlaceholderChunk("name");
4382 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004383
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004384 if (Results.includeCodePatterns()) {
4385 // @interface name
4386 // FIXME: Could introduce the whole pattern, including superclasses and
4387 // such.
James Dennetta40f7922012-06-14 03:11:41 +00004388 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004389 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4390 Builder.AddPlaceholderChunk("class");
4391 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004392
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004393 // @protocol name
James Dennetta40f7922012-06-14 03:11:41 +00004394 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004395 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4396 Builder.AddPlaceholderChunk("protocol");
4397 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004398
4399 // @implementation name
James Dennetta40f7922012-06-14 03:11:41 +00004400 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004401 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4402 Builder.AddPlaceholderChunk("class");
4403 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004404 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004405
4406 // @compatibility_alias name
James Dennetta40f7922012-06-14 03:11:41 +00004407 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004408 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4409 Builder.AddPlaceholderChunk("alias");
4410 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4411 Builder.AddPlaceholderChunk("class");
4412 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004413}
4414
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004415void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004416 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004417 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004418 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004419 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004420 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004421 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004422 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004423 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004424 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004425 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004426 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004427 HandleCodeCompleteResults(this, CodeCompleter,
4428 CodeCompletionContext::CCC_Other,
4429 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004430}
4431
Douglas Gregorbca403c2010-01-13 23:51:12 +00004432static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004433 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004434 CodeCompletionBuilder Builder(Results.getAllocator(),
4435 Results.getCodeCompletionTUInfo());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004436
4437 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004438 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004439 if (Results.getSema().getLangOpts().CPlusPlus ||
4440 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004441 EncodeType = "const char[]";
Douglas Gregor8ca72082011-10-18 21:20:17 +00004442 Builder.AddResultTypeChunk(EncodeType);
James Dennetta40f7922012-06-14 03:11:41 +00004443 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004444 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4445 Builder.AddPlaceholderChunk("type-name");
4446 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4447 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004448
4449 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004450 Builder.AddResultTypeChunk("Protocol *");
James Dennetta40f7922012-06-14 03:11:41 +00004451 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004452 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4453 Builder.AddPlaceholderChunk("protocol-name");
4454 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4455 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004456
4457 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004458 Builder.AddResultTypeChunk("SEL");
James Dennetta40f7922012-06-14 03:11:41 +00004459 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004460 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4461 Builder.AddPlaceholderChunk("selector");
4462 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4463 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004464
4465 // @"string"
4466 Builder.AddResultTypeChunk("NSString *");
4467 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
4468 Builder.AddPlaceholderChunk("string");
4469 Builder.AddTextChunk("\"");
4470 Results.AddResult(Result(Builder.TakeString()));
4471
Douglas Gregor79615892012-07-17 23:24:47 +00004472 // @[objects, ...]
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004473 Builder.AddResultTypeChunk("NSArray *");
James Dennetta40f7922012-06-14 03:11:41 +00004474 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004475 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004476 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4477 Results.AddResult(Result(Builder.TakeString()));
4478
Douglas Gregor79615892012-07-17 23:24:47 +00004479 // @{key : object, ...}
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004480 Builder.AddResultTypeChunk("NSDictionary *");
James Dennetta40f7922012-06-14 03:11:41 +00004481 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004482 Builder.AddPlaceholderChunk("key");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004483 Builder.AddChunk(CodeCompletionString::CK_Colon);
4484 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4485 Builder.AddPlaceholderChunk("object, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004486 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4487 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004488
Douglas Gregor79615892012-07-17 23:24:47 +00004489 // @(expression)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004490 Builder.AddResultTypeChunk("id");
4491 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004492 Builder.AddPlaceholderChunk("expression");
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004493 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4494 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004495}
4496
Douglas Gregorbca403c2010-01-13 23:51:12 +00004497static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004498 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004499 CodeCompletionBuilder Builder(Results.getAllocator(),
4500 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004501
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004502 if (Results.includeCodePatterns()) {
4503 // @try { statements } @catch ( declaration ) { statements } @finally
4504 // { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004505 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004506 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4507 Builder.AddPlaceholderChunk("statements");
4508 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4509 Builder.AddTextChunk("@catch");
4510 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4511 Builder.AddPlaceholderChunk("parameter");
4512 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4513 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4514 Builder.AddPlaceholderChunk("statements");
4515 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4516 Builder.AddTextChunk("@finally");
4517 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4518 Builder.AddPlaceholderChunk("statements");
4519 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4520 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004521 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004522
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004523 // @throw
James Dennetta40f7922012-06-14 03:11:41 +00004524 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004525 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4526 Builder.AddPlaceholderChunk("expression");
4527 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004528
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004529 if (Results.includeCodePatterns()) {
4530 // @synchronized ( expression ) { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004531 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004532 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4533 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4534 Builder.AddPlaceholderChunk("expression");
4535 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4536 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4537 Builder.AddPlaceholderChunk("statements");
4538 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4539 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004540 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004541}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004542
Douglas Gregorbca403c2010-01-13 23:51:12 +00004543static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004544 ResultBuilder &Results,
4545 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004546 typedef CodeCompletionResult Result;
James Dennetta40f7922012-06-14 03:11:41 +00004547 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
4548 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
4549 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004550 if (LangOpts.ObjC2)
James Dennetta40f7922012-06-14 03:11:41 +00004551 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004552}
4553
4554void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004555 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004556 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004557 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004558 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004559 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004560 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004561 HandleCodeCompleteResults(this, CodeCompleter,
4562 CodeCompletionContext::CCC_Other,
4563 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004564}
4565
4566void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004567 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004568 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004569 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004570 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004571 AddObjCStatementResults(Results, false);
4572 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004573 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004574 HandleCodeCompleteResults(this, CodeCompleter,
4575 CodeCompletionContext::CCC_Other,
4576 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004577}
4578
4579void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004580 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004581 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004582 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004583 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004584 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004585 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004586 HandleCodeCompleteResults(this, CodeCompleter,
4587 CodeCompletionContext::CCC_Other,
4588 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004589}
4590
Douglas Gregor988358f2009-11-19 00:14:45 +00004591/// \brief Determine whether the addition of the given flag to an Objective-C
4592/// property's attributes will cause a conflict.
4593static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4594 // Check if we've already added this flag.
4595 if (Attributes & NewFlag)
4596 return true;
4597
4598 Attributes |= NewFlag;
4599
4600 // Check for collisions with "readonly".
4601 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
Jordan Rosed7403a72012-08-20 20:01:13 +00004602 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregor988358f2009-11-19 00:14:45 +00004603 return true;
4604
Jordan Rosed7403a72012-08-20 20:01:13 +00004605 // Check for more than one of { assign, copy, retain, strong, weak }.
Douglas Gregor988358f2009-11-19 00:14:45 +00004606 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004607 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004608 ObjCDeclSpec::DQ_PR_copy |
Jordan Rosed7403a72012-08-20 20:01:13 +00004609 ObjCDeclSpec::DQ_PR_retain |
4610 ObjCDeclSpec::DQ_PR_strong |
4611 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregor988358f2009-11-19 00:14:45 +00004612 if (AssignCopyRetMask &&
4613 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004614 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004615 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004616 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rosed7403a72012-08-20 20:01:13 +00004617 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
4618 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregor988358f2009-11-19 00:14:45 +00004619 return true;
4620
4621 return false;
4622}
4623
Douglas Gregora93b1082009-11-18 23:08:07 +00004624void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004625 if (!CodeCompleter)
4626 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004627
Steve Naroffece8e712009-10-08 21:55:05 +00004628 unsigned Attributes = ODS.getPropertyAttributes();
4629
Douglas Gregor218937c2011-02-01 19:23:04 +00004630 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004631 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004632 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004633 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004634 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004635 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004636 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004637 Results.AddResult(CodeCompletionResult("assign"));
John McCallf85e1932011-06-15 23:02:42 +00004638 if (!ObjCPropertyFlagConflicts(Attributes,
4639 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4640 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004641 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004642 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004643 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004644 Results.AddResult(CodeCompletionResult("retain"));
John McCallf85e1932011-06-15 23:02:42 +00004645 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4646 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004647 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004648 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004649 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004650 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004651 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4652 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rosed7403a72012-08-20 20:01:13 +00004653
4654 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall0a7dd782012-08-21 02:47:43 +00004655 if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Jordan Rosed7403a72012-08-20 20:01:13 +00004656 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
4657 Results.AddResult(CodeCompletionResult("weak"));
4658
Douglas Gregor988358f2009-11-19 00:14:45 +00004659 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004660 CodeCompletionBuilder Setter(Results.getAllocator(),
4661 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004662 Setter.AddTypedTextChunk("setter");
4663 Setter.AddTextChunk(" = ");
4664 Setter.AddPlaceholderChunk("method");
4665 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004666 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004667 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004668 CodeCompletionBuilder Getter(Results.getAllocator(),
4669 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004670 Getter.AddTypedTextChunk("getter");
4671 Getter.AddTextChunk(" = ");
4672 Getter.AddPlaceholderChunk("method");
4673 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004674 }
Steve Naroffece8e712009-10-08 21:55:05 +00004675 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004676 HandleCodeCompleteResults(this, CodeCompleter,
4677 CodeCompletionContext::CCC_Other,
4678 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004679}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004680
James Dennettde23c7e2012-06-17 05:33:25 +00004681/// \brief Describes the kind of Objective-C method that we want to find
Douglas Gregor4ad96852009-11-19 07:41:15 +00004682/// via code completion.
4683enum ObjCMethodKind {
Dmitri Gribenko49fdccb2012-06-08 23:13:42 +00004684 MK_Any, ///< Any kind of method, provided it means other specified criteria.
4685 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
4686 MK_OneArgSelector ///< One-argument selector.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004687};
4688
Douglas Gregor458433d2010-08-26 15:07:07 +00004689static bool isAcceptableObjCSelector(Selector Sel,
4690 ObjCMethodKind WantKind,
4691 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004692 unsigned NumSelIdents,
4693 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004694 if (NumSelIdents > Sel.getNumArgs())
4695 return false;
4696
4697 switch (WantKind) {
4698 case MK_Any: break;
4699 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4700 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4701 }
4702
Douglas Gregorcf544262010-11-17 21:36:08 +00004703 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4704 return false;
4705
Douglas Gregor458433d2010-08-26 15:07:07 +00004706 for (unsigned I = 0; I != NumSelIdents; ++I)
4707 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4708 return false;
4709
4710 return true;
4711}
4712
Douglas Gregor4ad96852009-11-19 07:41:15 +00004713static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4714 ObjCMethodKind WantKind,
4715 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004716 unsigned NumSelIdents,
4717 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004718 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004719 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004720}
Douglas Gregord36adf52010-09-16 16:06:31 +00004721
4722namespace {
4723 /// \brief A set of selectors, which is used to avoid introducing multiple
4724 /// completions with the same selector into the result set.
4725 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4726}
4727
Douglas Gregor36ecb042009-11-17 23:22:23 +00004728/// \brief Add all of the Objective-C methods in the given Objective-C
4729/// container to the set of results.
4730///
4731/// The container will be a class, protocol, category, or implementation of
4732/// any of the above. This mether will recurse to include methods from
4733/// the superclasses of classes along with their categories, protocols, and
4734/// implementations.
4735///
4736/// \param Container the container in which we'll look to find methods.
4737///
James Dennetta40f7922012-06-14 03:11:41 +00004738/// \param WantInstanceMethods Whether to add instance methods (only); if
4739/// false, this routine will add factory methods (only).
Douglas Gregor36ecb042009-11-17 23:22:23 +00004740///
4741/// \param CurContext the context in which we're performing the lookup that
4742/// finds methods.
4743///
Douglas Gregorcf544262010-11-17 21:36:08 +00004744/// \param AllowSameLength Whether we allow a method to be added to the list
4745/// when it has the same number of parameters as we have selector identifiers.
4746///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004747/// \param Results the structure into which we'll add results.
4748static void AddObjCMethods(ObjCContainerDecl *Container,
4749 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004750 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004751 IdentifierInfo **SelIdents,
4752 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004753 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004754 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004755 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004756 ResultBuilder &Results,
4757 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004758 typedef CodeCompletionResult Result;
Douglas Gregorb92a4082012-06-12 13:44:08 +00004759 Container = getContainerDef(Container);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004760 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4761 MEnd = Container->meth_end();
4762 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00004763 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004764 // Check whether the selector identifiers we've been given are a
4765 // subset of the identifiers for this particular method.
David Blaikie581deb32012-06-06 20:45:41 +00004766 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004767 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004768 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004769
David Blaikie262bc182012-04-30 02:36:29 +00004770 if (!Selectors.insert(M->getSelector()))
Douglas Gregord36adf52010-09-16 16:06:31 +00004771 continue;
4772
David Blaikie581deb32012-06-06 20:45:41 +00004773 Result R = Result(*M, 0);
Douglas Gregord3c68542009-11-19 01:08:35 +00004774 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004775 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004776 if (!InOriginalClass)
4777 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004778 Results.MaybeAddResult(R, CurContext);
4779 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004780 }
4781
Douglas Gregore396c7b2010-09-16 15:34:59 +00004782 // Visit the protocols of protocols.
4783 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004784 if (Protocol->hasDefinition()) {
4785 const ObjCList<ObjCProtocolDecl> &Protocols
4786 = Protocol->getReferencedProtocols();
4787 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4788 E = Protocols.end();
4789 I != E; ++I)
4790 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4791 NumSelIdents, CurContext, Selectors, AllowSameLength,
4792 Results, false);
4793 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004794 }
4795
Douglas Gregor36ecb042009-11-17 23:22:23 +00004796 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004797 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004798 return;
4799
4800 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004801 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4802 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004803 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004804 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004805 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004806
4807 // Add methods in categories.
4808 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4809 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004810 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004811 NumSelIdents, CurContext, Selectors, AllowSameLength,
4812 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004813
4814 // Add a categories protocol methods.
4815 const ObjCList<ObjCProtocolDecl> &Protocols
4816 = CatDecl->getReferencedProtocols();
4817 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4818 E = Protocols.end();
4819 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004820 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004821 NumSelIdents, CurContext, Selectors, AllowSameLength,
4822 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004823
4824 // Add methods in category implementations.
4825 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004826 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004827 NumSelIdents, CurContext, Selectors, AllowSameLength,
4828 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004829 }
4830
4831 // Add methods in superclass.
4832 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004833 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004834 SelIdents, NumSelIdents, CurContext, Selectors,
4835 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004836
4837 // Add methods in our implementation, if any.
4838 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004839 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004840 NumSelIdents, CurContext, Selectors, AllowSameLength,
4841 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004842}
4843
4844
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004845void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004846 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004847 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004848 if (!Class) {
4849 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004850 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004851 Class = Category->getClassInterface();
4852
4853 if (!Class)
4854 return;
4855 }
4856
4857 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004858 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004859 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004860 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004861 Results.EnterNewScope();
4862
Douglas Gregord36adf52010-09-16 16:06:31 +00004863 VisitedSelectorSet Selectors;
4864 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004865 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004866 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004867 HandleCodeCompleteResults(this, CodeCompleter,
4868 CodeCompletionContext::CCC_Other,
4869 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004870}
4871
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004872void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004873 // Try to find the interface where setters might live.
4874 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004875 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004876 if (!Class) {
4877 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004878 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004879 Class = Category->getClassInterface();
4880
4881 if (!Class)
4882 return;
4883 }
4884
4885 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004886 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004887 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004888 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004889 Results.EnterNewScope();
4890
Douglas Gregord36adf52010-09-16 16:06:31 +00004891 VisitedSelectorSet Selectors;
4892 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004893 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004894
4895 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004896 HandleCodeCompleteResults(this, CodeCompleter,
4897 CodeCompletionContext::CCC_Other,
4898 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004899}
4900
Douglas Gregorafc45782011-02-15 22:19:42 +00004901void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4902 bool IsParameter) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004903 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004904 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004905 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004906 Results.EnterNewScope();
4907
4908 // Add context-sensitive, Objective-C parameter-passing keywords.
4909 bool AddedInOut = false;
4910 if ((DS.getObjCDeclQualifier() &
4911 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4912 Results.AddResult("in");
4913 Results.AddResult("inout");
4914 AddedInOut = true;
4915 }
4916 if ((DS.getObjCDeclQualifier() &
4917 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4918 Results.AddResult("out");
4919 if (!AddedInOut)
4920 Results.AddResult("inout");
4921 }
4922 if ((DS.getObjCDeclQualifier() &
4923 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4924 ObjCDeclSpec::DQ_Oneway)) == 0) {
4925 Results.AddResult("bycopy");
4926 Results.AddResult("byref");
4927 Results.AddResult("oneway");
4928 }
4929
Douglas Gregorafc45782011-02-15 22:19:42 +00004930 // If we're completing the return type of an Objective-C method and the
4931 // identifier IBAction refers to a macro, provide a completion item for
4932 // an action, e.g.,
4933 // IBAction)<#selector#>:(id)sender
4934 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4935 Context.Idents.get("IBAction").hasMacroDefinition()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004936 CodeCompletionBuilder Builder(Results.getAllocator(),
4937 Results.getCodeCompletionTUInfo(),
4938 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorafc45782011-02-15 22:19:42 +00004939 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004940 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004941 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004942 Builder.AddChunk(CodeCompletionString::CK_Colon);
4943 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004944 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004945 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004946 Builder.AddTextChunk("sender");
4947 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4948 }
4949
Douglas Gregord32b0222010-08-24 01:06:58 +00004950 // Add various builtin type names and specifiers.
4951 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4952 Results.ExitScope();
4953
4954 // Add the various type names
4955 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4956 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4957 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4958 CodeCompleter->includeGlobals());
4959
4960 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00004961 AddMacroResults(PP, Results, false);
Douglas Gregord32b0222010-08-24 01:06:58 +00004962
4963 HandleCodeCompleteResults(this, CodeCompleter,
4964 CodeCompletionContext::CCC_Type,
4965 Results.data(), Results.size());
4966}
4967
Douglas Gregor22f56992010-04-06 19:22:33 +00004968/// \brief When we have an expression with type "id", we may assume
4969/// that it has some more-specific class type based on knowledge of
4970/// common uses of Objective-C. This routine returns that class type,
4971/// or NULL if no better result could be determined.
4972static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004973 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004974 if (!Msg)
4975 return 0;
4976
4977 Selector Sel = Msg->getSelector();
4978 if (Sel.isNull())
4979 return 0;
4980
4981 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4982 if (!Id)
4983 return 0;
4984
4985 ObjCMethodDecl *Method = Msg->getMethodDecl();
4986 if (!Method)
4987 return 0;
4988
4989 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004990 ObjCInterfaceDecl *IFace = 0;
4991 switch (Msg->getReceiverKind()) {
4992 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004993 if (const ObjCObjectType *ObjType
4994 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4995 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004996 break;
4997
4998 case ObjCMessageExpr::Instance: {
4999 QualType T = Msg->getInstanceReceiver()->getType();
5000 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5001 IFace = Ptr->getInterfaceDecl();
5002 break;
5003 }
5004
5005 case ObjCMessageExpr::SuperInstance:
5006 case ObjCMessageExpr::SuperClass:
5007 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00005008 }
5009
5010 if (!IFace)
5011 return 0;
5012
5013 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5014 if (Method->isInstanceMethod())
5015 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5016 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00005017 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00005018 .Case("autorelease", IFace)
5019 .Case("copy", IFace)
5020 .Case("copyWithZone", IFace)
5021 .Case("mutableCopy", IFace)
5022 .Case("mutableCopyWithZone", IFace)
5023 .Case("awakeFromCoder", IFace)
5024 .Case("replacementObjectFromCoder", IFace)
5025 .Case("class", IFace)
5026 .Case("classForCoder", IFace)
5027 .Case("superclass", Super)
5028 .Default(0);
5029
5030 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5031 .Case("new", IFace)
5032 .Case("alloc", IFace)
5033 .Case("allocWithZone", IFace)
5034 .Case("class", IFace)
5035 .Case("superclass", Super)
5036 .Default(0);
5037}
5038
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005039// Add a special completion for a message send to "super", which fills in the
5040// most likely case of forwarding all of our arguments to the superclass
5041// function.
5042///
5043/// \param S The semantic analysis object.
5044///
Dmitri Gribenko70517ca2012-08-23 17:58:28 +00005045/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005046/// the "super" keyword. Otherwise, we just need to provide the arguments.
5047///
5048/// \param SelIdents The identifiers in the selector that have already been
5049/// provided as arguments for a send to "super".
5050///
5051/// \param NumSelIdents The number of identifiers in \p SelIdents.
5052///
5053/// \param Results The set of results to augment.
5054///
5055/// \returns the Objective-C method declaration that would be invoked by
5056/// this "super" completion. If NULL, no completion was added.
5057static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
5058 IdentifierInfo **SelIdents,
5059 unsigned NumSelIdents,
5060 ResultBuilder &Results) {
5061 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5062 if (!CurMethod)
5063 return 0;
5064
5065 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5066 if (!Class)
5067 return 0;
5068
5069 // Try to find a superclass method with the same selector.
5070 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00005071 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5072 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005073 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5074 CurMethod->isInstanceMethod());
5075
Douglas Gregor78bcd912011-02-16 00:51:18 +00005076 // Check in categories or class extensions.
5077 if (!SuperMethod) {
5078 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5079 Category = Category->getNextClassCategory())
5080 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
5081 CurMethod->isInstanceMethod())))
5082 break;
5083 }
5084 }
5085
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005086 if (!SuperMethod)
5087 return 0;
5088
5089 // Check whether the superclass method has the same signature.
5090 if (CurMethod->param_size() != SuperMethod->param_size() ||
5091 CurMethod->isVariadic() != SuperMethod->isVariadic())
5092 return 0;
5093
5094 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5095 CurPEnd = CurMethod->param_end(),
5096 SuperP = SuperMethod->param_begin();
5097 CurP != CurPEnd; ++CurP, ++SuperP) {
5098 // Make sure the parameter types are compatible.
5099 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5100 (*SuperP)->getType()))
5101 return 0;
5102
5103 // Make sure we have a parameter name to forward!
5104 if (!(*CurP)->getIdentifier())
5105 return 0;
5106 }
5107
5108 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005109 CodeCompletionBuilder Builder(Results.getAllocator(),
5110 Results.getCodeCompletionTUInfo());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005111
5112 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005113 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5114 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005115
5116 // If we need the "super" keyword, add it (plus some spacing).
5117 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005118 Builder.AddTypedTextChunk("super");
5119 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005120 }
5121
5122 Selector Sel = CurMethod->getSelector();
5123 if (Sel.isUnarySelector()) {
5124 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005125 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005126 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005127 else
Douglas Gregordae68752011-02-01 22:57:45 +00005128 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005129 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005130 } else {
5131 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5132 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5133 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005134 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005135
5136 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005137 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005138 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005139 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005140 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005141 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005142 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005143 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005144 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005145 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005146 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005147 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005148 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005149 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005150 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005151 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005152 }
5153 }
5154 }
5155
Douglas Gregorba103062012-03-27 23:34:16 +00005156 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5157 CCP_SuperCompletion));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005158 return SuperMethod;
5159}
5160
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005161void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005162 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005163 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005164 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005165 CodeCompletionContext::CCC_ObjCMessageReceiver,
David Blaikie4e4d0842012-03-11 07:00:24 +00005166 getLangOpts().CPlusPlus0x
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005167 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5168 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005169
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005170 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5171 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005172 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5173 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005174
5175 // If we are in an Objective-C method inside a class that has a superclass,
5176 // add "super" as an option.
5177 if (ObjCMethodDecl *Method = getCurMethodDecl())
5178 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005179 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005180 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005181
5182 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5183 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005184
David Blaikie4e4d0842012-03-11 07:00:24 +00005185 if (getLangOpts().CPlusPlus0x)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005186 addThisCompletion(*this, Results);
5187
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005188 Results.ExitScope();
5189
5190 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00005191 AddMacroResults(PP, Results, false);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005192 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005193 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005194
5195}
5196
Douglas Gregor2725ca82010-04-21 19:57:20 +00005197void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5198 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005199 unsigned NumSelIdents,
5200 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005201 ObjCInterfaceDecl *CDecl = 0;
5202 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5203 // Figure out which interface we're in.
5204 CDecl = CurMethod->getClassInterface();
5205 if (!CDecl)
5206 return;
5207
5208 // Find the superclass of this class.
5209 CDecl = CDecl->getSuperClass();
5210 if (!CDecl)
5211 return;
5212
5213 if (CurMethod->isInstanceMethod()) {
5214 // We are inside an instance method, which means that the message
5215 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005216 // current object.
5217 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005218 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005219 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005220 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005221 }
5222
5223 // Fall through to send to the superclass in CDecl.
5224 } else {
5225 // "super" may be the name of a type or variable. Figure out which
5226 // it is.
5227 IdentifierInfo *Super = &Context.Idents.get("super");
5228 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5229 LookupOrdinaryName);
5230 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5231 // "super" names an interface. Use it.
5232 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005233 if (const ObjCObjectType *Iface
5234 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5235 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005236 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5237 // "super" names an unresolved type; we can't be more specific.
5238 } else {
5239 // Assume that "super" names some kind of value and parse that way.
5240 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005241 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005242 UnqualifiedId id;
5243 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005244 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5245 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005246 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005247 SelIdents, NumSelIdents,
5248 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005249 }
5250
5251 // Fall through
5252 }
5253
John McCallb3d87482010-08-24 05:47:05 +00005254 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005255 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005256 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005257 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005258 NumSelIdents, AtArgumentExpression,
5259 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005260}
5261
Douglas Gregorb9d77572010-09-21 00:03:25 +00005262/// \brief Given a set of code-completion results for the argument of a message
5263/// send, determine the preferred type (if any) for that argument expression.
5264static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5265 unsigned NumSelIdents) {
5266 typedef CodeCompletionResult Result;
5267 ASTContext &Context = Results.getSema().Context;
5268
5269 QualType PreferredType;
5270 unsigned BestPriority = CCP_Unlikely * 2;
5271 Result *ResultsData = Results.data();
5272 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5273 Result &R = ResultsData[I];
5274 if (R.Kind == Result::RK_Declaration &&
5275 isa<ObjCMethodDecl>(R.Declaration)) {
5276 if (R.Priority <= BestPriority) {
5277 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5278 if (NumSelIdents <= Method->param_size()) {
5279 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5280 ->getType();
5281 if (R.Priority < BestPriority || PreferredType.isNull()) {
5282 BestPriority = R.Priority;
5283 PreferredType = MyPreferredType;
5284 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5285 MyPreferredType)) {
5286 PreferredType = QualType();
5287 }
5288 }
5289 }
5290 }
5291 }
5292
5293 return PreferredType;
5294}
5295
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005296static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5297 ParsedType Receiver,
5298 IdentifierInfo **SelIdents,
5299 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005300 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005301 bool IsSuper,
5302 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005303 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005304 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005305
Douglas Gregor24a069f2009-11-17 17:59:40 +00005306 // If the given name refers to an interface type, retrieve the
5307 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005308 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005309 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005310 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005311 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5312 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005313 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005314
Douglas Gregor36ecb042009-11-17 23:22:23 +00005315 // Add all of the factory methods in this Objective-C class, its protocols,
5316 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005317 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005318
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005319 // If this is a send-to-super, try to add the special "super" send
5320 // completion.
5321 if (IsSuper) {
5322 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005323 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5324 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005325 Results.Ignore(SuperMethod);
5326 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005327
Douglas Gregor265f7492010-08-27 15:29:55 +00005328 // If we're inside an Objective-C method definition, prefer its selector to
5329 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005330 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005331 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005332
Douglas Gregord36adf52010-09-16 16:06:31 +00005333 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005334 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005335 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005336 SemaRef.CurContext, Selectors, AtArgumentExpression,
5337 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005338 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005339 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005340
Douglas Gregor719770d2010-04-06 17:30:22 +00005341 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005342 // pool from the AST file.
Axel Naumann0ec56b72012-10-18 19:05:02 +00005343 if (SemaRef.getExternalSource()) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005344 for (uint32_t I = 0,
Axel Naumann0ec56b72012-10-18 19:05:02 +00005345 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005346 I != N; ++I) {
Axel Naumann0ec56b72012-10-18 19:05:02 +00005347 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005348 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005349 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005350
5351 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005352 }
5353 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005354
5355 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5356 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005357 M != MEnd; ++M) {
5358 for (ObjCMethodList *MethList = &M->second.second;
5359 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005360 MethList = MethList->Next) {
5361 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5362 NumSelIdents))
5363 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005364
Douglas Gregor13438f92010-04-06 16:40:00 +00005365 Result R(MethList->Method, 0);
5366 R.StartParameter = NumSelIdents;
5367 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005368 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005369 }
5370 }
5371 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005372
5373 Results.ExitScope();
5374}
Douglas Gregor13438f92010-04-06 16:40:00 +00005375
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005376void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5377 IdentifierInfo **SelIdents,
5378 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005379 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005380 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005381
5382 QualType T = this->GetTypeFromParser(Receiver);
5383
Douglas Gregor218937c2011-02-01 19:23:04 +00005384 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005385 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005386 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005387 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005388
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005389 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5390 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005391
5392 // If we're actually at the argument expression (rather than prior to the
5393 // selector), we're actually performing code completion for an expression.
5394 // Determine whether we have a single, best method. If so, we can
5395 // code-complete the expression using the corresponding parameter type as
5396 // our preferred type, improving completion results.
5397 if (AtArgumentExpression) {
5398 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005399 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005400 if (PreferredType.isNull())
5401 CodeCompleteOrdinaryName(S, PCC_Expression);
5402 else
5403 CodeCompleteExpression(S, PreferredType);
5404 return;
5405 }
5406
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005407 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005408 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005409 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005410}
5411
Richard Trieuf81e5a92011-09-09 02:00:50 +00005412void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005413 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005414 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005415 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005416 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005417 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005418
5419 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005420
Douglas Gregor36ecb042009-11-17 23:22:23 +00005421 // If necessary, apply function/array conversion to the receiver.
5422 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005423 if (RecExpr) {
5424 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5425 if (Conv.isInvalid()) // conversion failed. bail.
5426 return;
5427 RecExpr = Conv.take();
5428 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005429 QualType ReceiverType = RecExpr? RecExpr->getType()
5430 : Super? Context.getObjCObjectPointerType(
5431 Context.getObjCInterfaceType(Super))
5432 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005433
Douglas Gregorda892642010-11-08 21:12:30 +00005434 // If we're messaging an expression with type "id" or "Class", check
5435 // whether we know something special about the receiver that allows
5436 // us to assume a more-specific receiver type.
5437 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5438 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5439 if (ReceiverType->isObjCClassType())
5440 return CodeCompleteObjCClassMessage(S,
5441 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5442 SelIdents, NumSelIdents,
5443 AtArgumentExpression, Super);
5444
5445 ReceiverType = Context.getObjCObjectPointerType(
5446 Context.getObjCInterfaceType(IFace));
5447 }
5448
Douglas Gregor36ecb042009-11-17 23:22:23 +00005449 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005450 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005451 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005452 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005453 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005454
Douglas Gregor36ecb042009-11-17 23:22:23 +00005455 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005456
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005457 // If this is a send-to-super, try to add the special "super" send
5458 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005459 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005460 if (ObjCMethodDecl *SuperMethod
5461 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5462 Results))
5463 Results.Ignore(SuperMethod);
5464 }
5465
Douglas Gregor265f7492010-08-27 15:29:55 +00005466 // If we're inside an Objective-C method definition, prefer its selector to
5467 // others.
5468 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5469 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005470
Douglas Gregord36adf52010-09-16 16:06:31 +00005471 // Keep track of the selectors we've already added.
5472 VisitedSelectorSet Selectors;
5473
Douglas Gregorf74a4192009-11-18 00:06:18 +00005474 // Handle messages to Class. This really isn't a message to an instance
5475 // method, so we treat it the same way we would treat a message send to a
5476 // class method.
5477 if (ReceiverType->isObjCClassType() ||
5478 ReceiverType->isObjCQualifiedClassType()) {
5479 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5480 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005481 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005482 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005483 }
5484 }
5485 // Handle messages to a qualified ID ("id<foo>").
5486 else if (const ObjCObjectPointerType *QualID
5487 = ReceiverType->getAsObjCQualifiedIdType()) {
5488 // Search protocols for instance methods.
5489 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5490 E = QualID->qual_end();
5491 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005492 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005493 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005494 }
5495 // Handle messages to a pointer to interface type.
5496 else if (const ObjCObjectPointerType *IFacePtr
5497 = ReceiverType->getAsObjCInterfacePointerType()) {
5498 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005499 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005500 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5501 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005502
5503 // Search protocols for instance methods.
5504 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5505 E = IFacePtr->qual_end();
5506 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005507 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005508 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005509 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005510 // Handle messages to "id".
5511 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005512 // We're messaging "id", so provide all instance methods we know
5513 // about as code-completion results.
5514
5515 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005516 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005517 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005518 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5519 I != N; ++I) {
5520 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005521 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005522 continue;
5523
Sebastian Redldb9d2142010-08-02 23:18:59 +00005524 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005525 }
5526 }
5527
Sebastian Redldb9d2142010-08-02 23:18:59 +00005528 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5529 MEnd = MethodPool.end();
5530 M != MEnd; ++M) {
5531 for (ObjCMethodList *MethList = &M->second.first;
5532 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005533 MethList = MethList->Next) {
5534 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5535 NumSelIdents))
5536 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005537
5538 if (!Selectors.insert(MethList->Method->getSelector()))
5539 continue;
5540
Douglas Gregor13438f92010-04-06 16:40:00 +00005541 Result R(MethList->Method, 0);
5542 R.StartParameter = NumSelIdents;
5543 R.AllParametersAreInformative = false;
5544 Results.MaybeAddResult(R, CurContext);
5545 }
5546 }
5547 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005548 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005549
5550
5551 // If we're actually at the argument expression (rather than prior to the
5552 // selector), we're actually performing code completion for an expression.
5553 // Determine whether we have a single, best method. If so, we can
5554 // code-complete the expression using the corresponding parameter type as
5555 // our preferred type, improving completion results.
5556 if (AtArgumentExpression) {
5557 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5558 NumSelIdents);
5559 if (PreferredType.isNull())
5560 CodeCompleteOrdinaryName(S, PCC_Expression);
5561 else
5562 CodeCompleteExpression(S, PreferredType);
5563 return;
5564 }
5565
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005566 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005567 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005568 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005569}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005570
Douglas Gregorfb629412010-08-23 21:17:50 +00005571void Sema::CodeCompleteObjCForCollection(Scope *S,
5572 DeclGroupPtrTy IterationVar) {
5573 CodeCompleteExpressionData Data;
5574 Data.ObjCCollection = true;
5575
5576 if (IterationVar.getAsOpaquePtr()) {
5577 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5578 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5579 if (*I)
5580 Data.IgnoreDecls.push_back(*I);
5581 }
5582 }
5583
5584 CodeCompleteExpression(S, Data);
5585}
5586
Douglas Gregor458433d2010-08-26 15:07:07 +00005587void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5588 unsigned NumSelIdents) {
5589 // If we have an external source, load the entire class method
5590 // pool from the AST file.
5591 if (ExternalSource) {
5592 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5593 I != N; ++I) {
5594 Selector Sel = ExternalSource->GetExternalSelector(I);
5595 if (Sel.isNull() || MethodPool.count(Sel))
5596 continue;
5597
5598 ReadMethodPool(Sel);
5599 }
5600 }
5601
Douglas Gregor218937c2011-02-01 19:23:04 +00005602 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005603 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005604 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005605 Results.EnterNewScope();
5606 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5607 MEnd = MethodPool.end();
5608 M != MEnd; ++M) {
5609
5610 Selector Sel = M->first;
5611 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5612 continue;
5613
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005614 CodeCompletionBuilder Builder(Results.getAllocator(),
5615 Results.getCodeCompletionTUInfo());
Douglas Gregor458433d2010-08-26 15:07:07 +00005616 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005617 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005618 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005619 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005620 continue;
5621 }
5622
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005623 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005624 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005625 if (I == NumSelIdents) {
5626 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005627 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005628 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005629 Accumulator.clear();
5630 }
5631 }
5632
Benjamin Kramera0651c52011-07-26 16:59:25 +00005633 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005634 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005635 }
Douglas Gregordae68752011-02-01 22:57:45 +00005636 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005637 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005638 }
5639 Results.ExitScope();
5640
5641 HandleCodeCompleteResults(this, CodeCompleter,
5642 CodeCompletionContext::CCC_SelectorName,
5643 Results.data(), Results.size());
5644}
5645
Douglas Gregor55385fe2009-11-18 04:19:12 +00005646/// \brief Add all of the protocol declarations that we find in the given
5647/// (translation unit) context.
5648static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005649 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005650 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005651 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005652
5653 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5654 DEnd = Ctx->decls_end();
5655 D != DEnd; ++D) {
5656 // Record any protocols we find.
5657 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005658 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005659 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005660 }
5661}
5662
5663void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5664 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005665 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005666 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005667 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005668
Douglas Gregor70c23352010-12-09 21:44:02 +00005669 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5670 Results.EnterNewScope();
5671
5672 // Tell the result set to ignore all of the protocols we have
5673 // already seen.
5674 // FIXME: This doesn't work when caching code-completion results.
5675 for (unsigned I = 0; I != NumProtocols; ++I)
5676 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5677 Protocols[I].second))
5678 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005679
Douglas Gregor70c23352010-12-09 21:44:02 +00005680 // Add all protocols.
5681 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5682 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005683
Douglas Gregor70c23352010-12-09 21:44:02 +00005684 Results.ExitScope();
5685 }
5686
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005687 HandleCodeCompleteResults(this, CodeCompleter,
5688 CodeCompletionContext::CCC_ObjCProtocolName,
5689 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005690}
5691
5692void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005693 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005694 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005695 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005696
Douglas Gregor70c23352010-12-09 21:44:02 +00005697 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5698 Results.EnterNewScope();
5699
5700 // Add all protocols.
5701 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5702 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005703
Douglas Gregor70c23352010-12-09 21:44:02 +00005704 Results.ExitScope();
5705 }
5706
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005707 HandleCodeCompleteResults(this, CodeCompleter,
5708 CodeCompletionContext::CCC_ObjCProtocolName,
5709 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005710}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005711
5712/// \brief Add all of the Objective-C interface declarations that we find in
5713/// the given (translation unit) context.
5714static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5715 bool OnlyForwardDeclarations,
5716 bool OnlyUnimplemented,
5717 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005718 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005719
5720 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5721 DEnd = Ctx->decls_end();
5722 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005723 // Record any interfaces we find.
5724 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005725 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005726 (!OnlyUnimplemented || !Class->getImplementation()))
5727 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005728 }
5729}
5730
5731void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005732 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005733 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005734 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005735 Results.EnterNewScope();
5736
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005737 if (CodeCompleter->includeGlobals()) {
5738 // Add all classes.
5739 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5740 false, Results);
5741 }
5742
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005743 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005744
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005745 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005746 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005747 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005748}
5749
Douglas Gregorc83c6872010-04-15 22:33:43 +00005750void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5751 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005752 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005753 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005754 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005755 Results.EnterNewScope();
5756
5757 // Make sure that we ignore the class we're currently defining.
5758 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005759 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005760 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005761 Results.Ignore(CurClass);
5762
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005763 if (CodeCompleter->includeGlobals()) {
5764 // Add all classes.
5765 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5766 false, Results);
5767 }
5768
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005769 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005770
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005771 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005772 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005773 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005774}
5775
5776void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005777 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005778 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005779 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005780 Results.EnterNewScope();
5781
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005782 if (CodeCompleter->includeGlobals()) {
5783 // Add all unimplemented classes.
5784 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5785 true, Results);
5786 }
5787
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005788 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005789
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005790 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005791 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005792 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005793}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005794
5795void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005796 IdentifierInfo *ClassName,
5797 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005798 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005799
Douglas Gregor218937c2011-02-01 19:23:04 +00005800 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005801 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005802 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005803
5804 // Ignore any categories we find that have already been implemented by this
5805 // interface.
5806 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5807 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005808 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005809 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5810 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5811 Category = Category->getNextClassCategory())
5812 CategoryNames.insert(Category->getIdentifier());
5813
5814 // Add all of the categories we know about.
5815 Results.EnterNewScope();
5816 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5817 for (DeclContext::decl_iterator D = TU->decls_begin(),
5818 DEnd = TU->decls_end();
5819 D != DEnd; ++D)
5820 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5821 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005822 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005823 Results.ExitScope();
5824
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005825 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005826 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005827 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005828}
5829
5830void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005831 IdentifierInfo *ClassName,
5832 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005833 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005834
5835 // Find the corresponding interface. If we couldn't find the interface, the
5836 // program itself is ill-formed. However, we'll try to be helpful still by
5837 // providing the list of all of the categories we know about.
5838 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005839 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005840 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5841 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005842 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005843
Douglas Gregor218937c2011-02-01 19:23:04 +00005844 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005845 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005846 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005847
5848 // Add all of the categories that have have corresponding interface
5849 // declarations in this class and any of its superclasses, except for
5850 // already-implemented categories in the class itself.
5851 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5852 Results.EnterNewScope();
5853 bool IgnoreImplemented = true;
5854 while (Class) {
5855 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5856 Category = Category->getNextClassCategory())
5857 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5858 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005859 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005860
5861 Class = Class->getSuperClass();
5862 IgnoreImplemented = false;
5863 }
5864 Results.ExitScope();
5865
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005866 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005867 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005868 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005869}
Douglas Gregor322328b2009-11-18 22:32:06 +00005870
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005871void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005872 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005873 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005874 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005875
5876 // Figure out where this @synthesize lives.
5877 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005878 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005879 if (!Container ||
5880 (!isa<ObjCImplementationDecl>(Container) &&
5881 !isa<ObjCCategoryImplDecl>(Container)))
5882 return;
5883
5884 // Ignore any properties that have already been implemented.
Douglas Gregorb92a4082012-06-12 13:44:08 +00005885 Container = getContainerDef(Container);
5886 for (DeclContext::decl_iterator D = Container->decls_begin(),
Douglas Gregor322328b2009-11-18 22:32:06 +00005887 DEnd = Container->decls_end();
5888 D != DEnd; ++D)
5889 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5890 Results.Ignore(PropertyImpl->getPropertyDecl());
5891
5892 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005893 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005894 Results.EnterNewScope();
5895 if (ObjCImplementationDecl *ClassImpl
5896 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005897 AddObjCProperties(ClassImpl->getClassInterface(), false,
5898 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005899 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005900 else
5901 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005902 false, /*AllowNullaryMethods=*/false, CurContext,
5903 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005904 Results.ExitScope();
5905
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005906 HandleCodeCompleteResults(this, CodeCompleter,
5907 CodeCompletionContext::CCC_Other,
5908 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005909}
5910
5911void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005912 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005913 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005914 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005915 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005916 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005917
5918 // Figure out where this @synthesize lives.
5919 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005920 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005921 if (!Container ||
5922 (!isa<ObjCImplementationDecl>(Container) &&
5923 !isa<ObjCCategoryImplDecl>(Container)))
5924 return;
5925
5926 // Figure out which interface we're looking into.
5927 ObjCInterfaceDecl *Class = 0;
5928 if (ObjCImplementationDecl *ClassImpl
5929 = dyn_cast<ObjCImplementationDecl>(Container))
5930 Class = ClassImpl->getClassInterface();
5931 else
5932 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5933 ->getClassInterface();
5934
Douglas Gregore8426052011-04-18 14:40:46 +00005935 // Determine the type of the property we're synthesizing.
5936 QualType PropertyType = Context.getObjCIdType();
5937 if (Class) {
5938 if (ObjCPropertyDecl *Property
5939 = Class->FindPropertyDeclaration(PropertyName)) {
5940 PropertyType
5941 = Property->getType().getNonReferenceType().getUnqualifiedType();
5942
5943 // Give preference to ivars
5944 Results.setPreferredType(PropertyType);
5945 }
5946 }
5947
Douglas Gregor322328b2009-11-18 22:32:06 +00005948 // Add all of the instance variables in this class and its superclasses.
5949 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005950 bool SawSimilarlyNamedIvar = false;
5951 std::string NameWithPrefix;
5952 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005953 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005954 std::string NameWithSuffix = PropertyName->getName().str();
5955 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005956 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005957 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5958 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005959 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5960
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005961 // Determine whether we've seen an ivar with a name similar to the
5962 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005963 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005964 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005965 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005966 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005967
5968 // Reduce the priority of this result by one, to give it a slight
5969 // advantage over other results whose names don't match so closely.
5970 if (Results.size() &&
5971 Results.data()[Results.size() - 1].Kind
5972 == CodeCompletionResult::RK_Declaration &&
5973 Results.data()[Results.size() - 1].Declaration == Ivar)
5974 Results.data()[Results.size() - 1].Priority--;
5975 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005976 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005977 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005978
5979 if (!SawSimilarlyNamedIvar) {
5980 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005981 // an ivar of the appropriate type.
5982 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005983 typedef CodeCompletionResult Result;
5984 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005985 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
5986 Priority,CXAvailability_Available);
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005987
Douglas Gregor8987b232011-09-27 23:30:47 +00005988 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00005989 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005990 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005991 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5992 Results.AddResult(Result(Builder.TakeString(), Priority,
5993 CXCursor_ObjCIvarDecl));
5994 }
5995
Douglas Gregor322328b2009-11-18 22:32:06 +00005996 Results.ExitScope();
5997
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005998 HandleCodeCompleteResults(this, CodeCompleter,
5999 CodeCompletionContext::CCC_Other,
6000 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00006001}
Douglas Gregore8f5a172010-04-07 00:21:17 +00006002
Douglas Gregor408be5a2010-08-25 01:08:01 +00006003// Mapping from selectors to the methods that implement that selector, along
6004// with the "in original class" flag.
6005typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
6006 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006007
6008/// \brief Find all of the methods that reside in the given container
6009/// (and its superclasses, protocols, etc.) that meet the given
6010/// criteria. Insert those methods into the map of known methods,
6011/// indexed by selector so they can be easily found.
6012static void FindImplementableMethods(ASTContext &Context,
6013 ObjCContainerDecl *Container,
6014 bool WantInstanceMethods,
6015 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00006016 KnownMethodsMap &KnownMethods,
6017 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006018 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006019 // Make sure we have a definition; that's what we'll walk.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006020 if (!IFace->hasDefinition())
6021 return;
Douglas Gregorb92a4082012-06-12 13:44:08 +00006022
6023 IFace = IFace->getDefinition();
6024 Container = IFace;
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006025
Douglas Gregore8f5a172010-04-07 00:21:17 +00006026 const ObjCList<ObjCProtocolDecl> &Protocols
6027 = IFace->getReferencedProtocols();
6028 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006029 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006030 I != E; ++I)
6031 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006032 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006033
Douglas Gregorea766182010-10-18 18:21:28 +00006034 // Add methods from any class extensions and categories.
6035 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
6036 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00006037 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
6038 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006039 KnownMethods, false);
6040
6041 // Visit the superclass.
6042 if (IFace->getSuperClass())
6043 FindImplementableMethods(Context, IFace->getSuperClass(),
6044 WantInstanceMethods, ReturnType,
6045 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006046 }
6047
6048 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6049 // Recurse into protocols.
6050 const ObjCList<ObjCProtocolDecl> &Protocols
6051 = Category->getReferencedProtocols();
6052 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006053 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006054 I != E; ++I)
6055 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006056 KnownMethods, InOriginalClass);
6057
6058 // If this category is the original class, jump to the interface.
6059 if (InOriginalClass && Category->getClassInterface())
6060 FindImplementableMethods(Context, Category->getClassInterface(),
6061 WantInstanceMethods, ReturnType, KnownMethods,
6062 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006063 }
6064
6065 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006066 // Make sure we have a definition; that's what we'll walk.
6067 if (!Protocol->hasDefinition())
6068 return;
6069 Protocol = Protocol->getDefinition();
6070 Container = Protocol;
6071
6072 // Recurse into protocols.
6073 const ObjCList<ObjCProtocolDecl> &Protocols
6074 = Protocol->getReferencedProtocols();
6075 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6076 E = Protocols.end();
6077 I != E; ++I)
6078 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6079 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006080 }
6081
6082 // Add methods in this container. This operation occurs last because
6083 // we want the methods from this container to override any methods
6084 // we've previously seen with the same selector.
6085 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
6086 MEnd = Container->meth_end();
6087 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00006088 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006089 if (!ReturnType.isNull() &&
David Blaikie262bc182012-04-30 02:36:29 +00006090 !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006091 continue;
6092
David Blaikie581deb32012-06-06 20:45:41 +00006093 KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006094 }
6095 }
6096}
6097
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006098/// \brief Add the parenthesized return or parameter type chunk to a code
6099/// completion string.
6100static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor90f5f472012-04-10 18:35:07 +00006101 unsigned ObjCDeclQuals,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006102 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006103 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006104 CodeCompletionBuilder &Builder) {
6105 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor90f5f472012-04-10 18:35:07 +00006106 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
6107 if (!Quals.empty())
6108 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor8987b232011-09-27 23:30:47 +00006109 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006110 Builder.getAllocator()));
6111 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6112}
6113
6114/// \brief Determine whether the given class is or inherits from a class by
6115/// the given name.
6116static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00006117 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006118 if (!Class)
6119 return false;
6120
6121 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6122 return true;
6123
6124 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6125}
6126
6127/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6128/// Key-Value Observing (KVO).
6129static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6130 bool IsInstanceMethod,
6131 QualType ReturnType,
6132 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006133 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006134 ResultBuilder &Results) {
6135 IdentifierInfo *PropName = Property->getIdentifier();
6136 if (!PropName || PropName->getLength() == 0)
6137 return;
6138
Douglas Gregor8987b232011-09-27 23:30:47 +00006139 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6140
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006141 // Builder that will create each code completion.
6142 typedef CodeCompletionResult Result;
6143 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006144 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006145
6146 // The selector table.
6147 SelectorTable &Selectors = Context.Selectors;
6148
6149 // The property name, copied into the code completion allocation region
6150 // on demand.
6151 struct KeyHolder {
6152 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006153 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006154 const char *CopiedKey;
6155
Chris Lattner5f9e2722011-07-23 10:55:15 +00006156 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006157 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6158
6159 operator const char *() {
6160 if (CopiedKey)
6161 return CopiedKey;
6162
6163 return CopiedKey = Allocator.CopyString(Key);
6164 }
6165 } Key(Allocator, PropName->getName());
6166
6167 // The uppercased name of the property name.
6168 std::string UpperKey = PropName->getName();
6169 if (!UpperKey.empty())
6170 UpperKey[0] = toupper(UpperKey[0]);
6171
6172 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6173 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6174 Property->getType());
6175 bool ReturnTypeMatchesVoid
6176 = ReturnType.isNull() || ReturnType->isVoidType();
6177
6178 // Add the normal accessor -(type)key.
6179 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006180 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006181 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6182 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006183 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6184 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006185
6186 Builder.AddTypedTextChunk(Key);
6187 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6188 CXCursor_ObjCInstanceMethodDecl));
6189 }
6190
6191 // If we have an integral or boolean property (or the user has provided
6192 // an integral or boolean return type), add the accessor -(type)isKey.
6193 if (IsInstanceMethod &&
6194 ((!ReturnType.isNull() &&
6195 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6196 (ReturnType.isNull() &&
6197 (Property->getType()->isIntegerType() ||
6198 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006199 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006200 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006201 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006202 if (ReturnType.isNull()) {
6203 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6204 Builder.AddTextChunk("BOOL");
6205 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6206 }
6207
6208 Builder.AddTypedTextChunk(
6209 Allocator.CopyString(SelectorId->getName()));
6210 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6211 CXCursor_ObjCInstanceMethodDecl));
6212 }
6213 }
6214
6215 // Add the normal mutator.
6216 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6217 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006218 std::string SelectorName = (Twine("set") + 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.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006221 if (ReturnType.isNull()) {
6222 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6223 Builder.AddTextChunk("void");
6224 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6225 }
6226
6227 Builder.AddTypedTextChunk(
6228 Allocator.CopyString(SelectorId->getName()));
6229 Builder.AddTypedTextChunk(":");
Douglas Gregor90f5f472012-04-10 18:35:07 +00006230 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6231 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006232 Builder.AddTextChunk(Key);
6233 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6234 CXCursor_ObjCInstanceMethodDecl));
6235 }
6236 }
6237
6238 // Indexed and unordered accessors
6239 unsigned IndexedGetterPriority = CCP_CodePattern;
6240 unsigned IndexedSetterPriority = CCP_CodePattern;
6241 unsigned UnorderedGetterPriority = CCP_CodePattern;
6242 unsigned UnorderedSetterPriority = CCP_CodePattern;
6243 if (const ObjCObjectPointerType *ObjCPointer
6244 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6245 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6246 // If this interface type is not provably derived from a known
6247 // collection, penalize the corresponding completions.
6248 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6249 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6250 if (!InheritsFromClassNamed(IFace, "NSArray"))
6251 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6252 }
6253
6254 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6255 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6256 if (!InheritsFromClassNamed(IFace, "NSSet"))
6257 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6258 }
6259 }
6260 } else {
6261 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6262 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6263 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6264 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6265 }
6266
6267 // Add -(NSUInteger)countOf<key>
6268 if (IsInstanceMethod &&
6269 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006270 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006271 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006272 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006273 if (ReturnType.isNull()) {
6274 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6275 Builder.AddTextChunk("NSUInteger");
6276 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6277 }
6278
6279 Builder.AddTypedTextChunk(
6280 Allocator.CopyString(SelectorId->getName()));
6281 Results.AddResult(Result(Builder.TakeString(),
6282 std::min(IndexedGetterPriority,
6283 UnorderedGetterPriority),
6284 CXCursor_ObjCInstanceMethodDecl));
6285 }
6286 }
6287
6288 // Indexed getters
6289 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6290 if (IsInstanceMethod &&
6291 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006292 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006293 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006294 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006295 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006296 if (ReturnType.isNull()) {
6297 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6298 Builder.AddTextChunk("id");
6299 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6300 }
6301
6302 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6303 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6304 Builder.AddTextChunk("NSUInteger");
6305 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6306 Builder.AddTextChunk("index");
6307 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6308 CXCursor_ObjCInstanceMethodDecl));
6309 }
6310 }
6311
6312 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6313 if (IsInstanceMethod &&
6314 (ReturnType.isNull() ||
6315 (ReturnType->isObjCObjectPointerType() &&
6316 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6317 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6318 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006319 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006320 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006321 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006322 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006323 if (ReturnType.isNull()) {
6324 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6325 Builder.AddTextChunk("NSArray *");
6326 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6327 }
6328
6329 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6330 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6331 Builder.AddTextChunk("NSIndexSet *");
6332 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6333 Builder.AddTextChunk("indexes");
6334 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6335 CXCursor_ObjCInstanceMethodDecl));
6336 }
6337 }
6338
6339 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6340 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006341 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006342 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006343 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006344 &Context.Idents.get("range")
6345 };
6346
Douglas Gregore74c25c2011-05-04 23:50:46 +00006347 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006348 if (ReturnType.isNull()) {
6349 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6350 Builder.AddTextChunk("void");
6351 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6352 }
6353
6354 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6355 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6356 Builder.AddPlaceholderChunk("object-type");
6357 Builder.AddTextChunk(" **");
6358 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6359 Builder.AddTextChunk("buffer");
6360 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6361 Builder.AddTypedTextChunk("range:");
6362 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6363 Builder.AddTextChunk("NSRange");
6364 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6365 Builder.AddTextChunk("inRange");
6366 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6367 CXCursor_ObjCInstanceMethodDecl));
6368 }
6369 }
6370
6371 // Mutable indexed accessors
6372
6373 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6374 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006375 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006376 IdentifierInfo *SelectorIds[2] = {
6377 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006378 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006379 };
6380
Douglas Gregore74c25c2011-05-04 23:50:46 +00006381 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006382 if (ReturnType.isNull()) {
6383 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6384 Builder.AddTextChunk("void");
6385 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6386 }
6387
6388 Builder.AddTypedTextChunk("insertObject:");
6389 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6390 Builder.AddPlaceholderChunk("object-type");
6391 Builder.AddTextChunk(" *");
6392 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6393 Builder.AddTextChunk("object");
6394 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6395 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6396 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6397 Builder.AddPlaceholderChunk("NSUInteger");
6398 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6399 Builder.AddTextChunk("index");
6400 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6401 CXCursor_ObjCInstanceMethodDecl));
6402 }
6403 }
6404
6405 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6406 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006407 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006408 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006409 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006410 &Context.Idents.get("atIndexes")
6411 };
6412
Douglas Gregore74c25c2011-05-04 23:50:46 +00006413 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006414 if (ReturnType.isNull()) {
6415 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6416 Builder.AddTextChunk("void");
6417 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6418 }
6419
6420 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6421 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6422 Builder.AddTextChunk("NSArray *");
6423 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6424 Builder.AddTextChunk("array");
6425 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6426 Builder.AddTypedTextChunk("atIndexes:");
6427 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6428 Builder.AddPlaceholderChunk("NSIndexSet *");
6429 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6430 Builder.AddTextChunk("indexes");
6431 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6432 CXCursor_ObjCInstanceMethodDecl));
6433 }
6434 }
6435
6436 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6437 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006438 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006439 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006440 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006441 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006442 if (ReturnType.isNull()) {
6443 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6444 Builder.AddTextChunk("void");
6445 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6446 }
6447
6448 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6449 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6450 Builder.AddTextChunk("NSUInteger");
6451 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6452 Builder.AddTextChunk("index");
6453 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6454 CXCursor_ObjCInstanceMethodDecl));
6455 }
6456 }
6457
6458 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6459 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006460 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006461 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006462 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006463 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006464 if (ReturnType.isNull()) {
6465 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6466 Builder.AddTextChunk("void");
6467 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6468 }
6469
6470 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6471 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6472 Builder.AddTextChunk("NSIndexSet *");
6473 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6474 Builder.AddTextChunk("indexes");
6475 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6476 CXCursor_ObjCInstanceMethodDecl));
6477 }
6478 }
6479
6480 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6481 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006482 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006483 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006484 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006485 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006486 &Context.Idents.get("withObject")
6487 };
6488
Douglas Gregore74c25c2011-05-04 23:50:46 +00006489 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006490 if (ReturnType.isNull()) {
6491 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6492 Builder.AddTextChunk("void");
6493 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6494 }
6495
6496 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6497 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6498 Builder.AddPlaceholderChunk("NSUInteger");
6499 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6500 Builder.AddTextChunk("index");
6501 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6502 Builder.AddTypedTextChunk("withObject:");
6503 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6504 Builder.AddTextChunk("id");
6505 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6506 Builder.AddTextChunk("object");
6507 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6508 CXCursor_ObjCInstanceMethodDecl));
6509 }
6510 }
6511
6512 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6513 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006514 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006515 = (Twine("replace") + UpperKey + "AtIndexes").str();
6516 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006517 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006518 &Context.Idents.get(SelectorName1),
6519 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006520 };
6521
Douglas Gregore74c25c2011-05-04 23:50:46 +00006522 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006523 if (ReturnType.isNull()) {
6524 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6525 Builder.AddTextChunk("void");
6526 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6527 }
6528
6529 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6530 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6531 Builder.AddPlaceholderChunk("NSIndexSet *");
6532 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6533 Builder.AddTextChunk("indexes");
6534 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6535 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6536 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6537 Builder.AddTextChunk("NSArray *");
6538 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6539 Builder.AddTextChunk("array");
6540 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6541 CXCursor_ObjCInstanceMethodDecl));
6542 }
6543 }
6544
6545 // Unordered getters
6546 // - (NSEnumerator *)enumeratorOfKey
6547 if (IsInstanceMethod &&
6548 (ReturnType.isNull() ||
6549 (ReturnType->isObjCObjectPointerType() &&
6550 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6551 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6552 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006553 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006554 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006555 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006556 if (ReturnType.isNull()) {
6557 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6558 Builder.AddTextChunk("NSEnumerator *");
6559 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6560 }
6561
6562 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6563 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6564 CXCursor_ObjCInstanceMethodDecl));
6565 }
6566 }
6567
6568 // - (type *)memberOfKey:(type *)object
6569 if (IsInstanceMethod &&
6570 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006571 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006572 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006573 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006574 if (ReturnType.isNull()) {
6575 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6576 Builder.AddPlaceholderChunk("object-type");
6577 Builder.AddTextChunk(" *");
6578 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6579 }
6580
6581 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6582 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6583 if (ReturnType.isNull()) {
6584 Builder.AddPlaceholderChunk("object-type");
6585 Builder.AddTextChunk(" *");
6586 } else {
6587 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006588 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006589 Builder.getAllocator()));
6590 }
6591 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6592 Builder.AddTextChunk("object");
6593 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6594 CXCursor_ObjCInstanceMethodDecl));
6595 }
6596 }
6597
6598 // Mutable unordered accessors
6599 // - (void)addKeyObject:(type *)object
6600 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006601 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006602 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006603 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006604 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006605 if (ReturnType.isNull()) {
6606 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6607 Builder.AddTextChunk("void");
6608 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6609 }
6610
6611 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6612 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6613 Builder.AddPlaceholderChunk("object-type");
6614 Builder.AddTextChunk(" *");
6615 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6616 Builder.AddTextChunk("object");
6617 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6618 CXCursor_ObjCInstanceMethodDecl));
6619 }
6620 }
6621
6622 // - (void)addKey:(NSSet *)objects
6623 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006624 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006625 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006626 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006627 if (ReturnType.isNull()) {
6628 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6629 Builder.AddTextChunk("void");
6630 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6631 }
6632
6633 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6634 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6635 Builder.AddTextChunk("NSSet *");
6636 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6637 Builder.AddTextChunk("objects");
6638 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6639 CXCursor_ObjCInstanceMethodDecl));
6640 }
6641 }
6642
6643 // - (void)removeKeyObject:(type *)object
6644 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006645 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006646 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006647 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006648 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006649 if (ReturnType.isNull()) {
6650 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6651 Builder.AddTextChunk("void");
6652 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6653 }
6654
6655 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6656 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6657 Builder.AddPlaceholderChunk("object-type");
6658 Builder.AddTextChunk(" *");
6659 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6660 Builder.AddTextChunk("object");
6661 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6662 CXCursor_ObjCInstanceMethodDecl));
6663 }
6664 }
6665
6666 // - (void)removeKey:(NSSet *)objects
6667 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006668 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006669 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006670 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006671 if (ReturnType.isNull()) {
6672 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6673 Builder.AddTextChunk("void");
6674 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6675 }
6676
6677 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6678 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6679 Builder.AddTextChunk("NSSet *");
6680 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6681 Builder.AddTextChunk("objects");
6682 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6683 CXCursor_ObjCInstanceMethodDecl));
6684 }
6685 }
6686
6687 // - (void)intersectKey:(NSSet *)objects
6688 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006689 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006690 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006691 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006692 if (ReturnType.isNull()) {
6693 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6694 Builder.AddTextChunk("void");
6695 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6696 }
6697
6698 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6699 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6700 Builder.AddTextChunk("NSSet *");
6701 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6702 Builder.AddTextChunk("objects");
6703 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6704 CXCursor_ObjCInstanceMethodDecl));
6705 }
6706 }
6707
6708 // Key-Value Observing
6709 // + (NSSet *)keyPathsForValuesAffectingKey
6710 if (!IsInstanceMethod &&
6711 (ReturnType.isNull() ||
6712 (ReturnType->isObjCObjectPointerType() &&
6713 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6714 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6715 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006716 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006717 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006718 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006719 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006720 if (ReturnType.isNull()) {
6721 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6722 Builder.AddTextChunk("NSSet *");
6723 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6724 }
6725
6726 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6727 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006728 CXCursor_ObjCClassMethodDecl));
6729 }
6730 }
6731
6732 // + (BOOL)automaticallyNotifiesObserversForKey
6733 if (!IsInstanceMethod &&
6734 (ReturnType.isNull() ||
6735 ReturnType->isIntegerType() ||
6736 ReturnType->isBooleanType())) {
6737 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006738 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006739 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6740 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6741 if (ReturnType.isNull()) {
6742 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6743 Builder.AddTextChunk("BOOL");
6744 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6745 }
6746
6747 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6748 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6749 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006750 }
6751 }
6752}
6753
Douglas Gregore8f5a172010-04-07 00:21:17 +00006754void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6755 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006756 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006757 // Determine the return type of the method we're declaring, if
6758 // provided.
6759 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006760 Decl *IDecl = 0;
6761 if (CurContext->isObjCContainer()) {
6762 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6763 IDecl = cast<Decl>(OCD);
6764 }
Douglas Gregorea766182010-10-18 18:21:28 +00006765 // Determine where we should start searching for methods.
6766 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006767 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006768 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006769 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6770 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006771 IsInImplementation = true;
6772 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006773 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006774 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006775 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006776 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006777 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006778 }
6779
6780 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006781 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006782 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006783 }
6784
Douglas Gregorea766182010-10-18 18:21:28 +00006785 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006786 HandleCodeCompleteResults(this, CodeCompleter,
6787 CodeCompletionContext::CCC_Other,
6788 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006789 return;
6790 }
6791
6792 // Find all of the methods that we could declare/implement here.
6793 KnownMethodsMap KnownMethods;
6794 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006795 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006796
Douglas Gregore8f5a172010-04-07 00:21:17 +00006797 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006798 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006799 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006800 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006801 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006802 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006803 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006804 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6805 MEnd = KnownMethods.end();
6806 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006807 ObjCMethodDecl *Method = M->second.first;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006808 CodeCompletionBuilder Builder(Results.getAllocator(),
6809 Results.getCodeCompletionTUInfo());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006810
6811 // If the result type was not already provided, add it to the
6812 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006813 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006814 AddObjCPassingTypeChunk(Method->getResultType(),
6815 Method->getObjCDeclQualifier(),
6816 Context, Policy,
6817 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006818
6819 Selector Sel = Method->getSelector();
6820
6821 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006822 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006823 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006824
6825 // Add parameters to the pattern.
6826 unsigned I = 0;
6827 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6828 PEnd = Method->param_end();
6829 P != PEnd; (void)++P, ++I) {
6830 // Add the part of the selector name.
6831 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006832 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006833 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006834 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6835 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006836 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006837 } else
6838 break;
6839
6840 // Add the parameter type.
Douglas Gregor90f5f472012-04-10 18:35:07 +00006841 AddObjCPassingTypeChunk((*P)->getOriginalType(),
6842 (*P)->getObjCDeclQualifier(),
6843 Context, Policy,
Douglas Gregor8987b232011-09-27 23:30:47 +00006844 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006845
6846 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006847 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006848 }
6849
6850 if (Method->isVariadic()) {
6851 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006852 Builder.AddChunk(CodeCompletionString::CK_Comma);
6853 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006854 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006855
Douglas Gregor447107d2010-05-28 00:57:46 +00006856 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006857 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006858 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6859 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6860 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006861 if (!Method->getResultType()->isVoidType()) {
6862 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006863 Builder.AddTextChunk("return");
6864 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6865 Builder.AddPlaceholderChunk("expression");
6866 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006867 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006868 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006869
Douglas Gregor218937c2011-02-01 19:23:04 +00006870 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6871 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006872 }
6873
Douglas Gregor408be5a2010-08-25 01:08:01 +00006874 unsigned Priority = CCP_CodePattern;
6875 if (!M->second.second)
6876 Priority += CCD_InBaseClass;
6877
Douglas Gregorba103062012-03-27 23:34:16 +00006878 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006879 }
6880
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006881 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6882 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006883 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006884 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006885 Containers.push_back(SearchDecl);
6886
Douglas Gregore74c25c2011-05-04 23:50:46 +00006887 VisitedSelectorSet KnownSelectors;
6888 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6889 MEnd = KnownMethods.end();
6890 M != MEnd; ++M)
6891 KnownSelectors.insert(M->first);
6892
6893
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006894 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6895 if (!IFace)
6896 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6897 IFace = Category->getClassInterface();
6898
6899 if (IFace) {
6900 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6901 Category = Category->getNextClassCategory())
6902 Containers.push_back(Category);
6903 }
6904
6905 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6906 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6907 PEnd = Containers[I]->prop_end();
6908 P != PEnd; ++P) {
David Blaikie581deb32012-06-06 20:45:41 +00006909 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006910 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006911 }
6912 }
6913 }
6914
Douglas Gregore8f5a172010-04-07 00:21:17 +00006915 Results.ExitScope();
6916
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006917 HandleCodeCompleteResults(this, CodeCompleter,
6918 CodeCompletionContext::CCC_Other,
6919 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006920}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006921
6922void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6923 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006924 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006925 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006926 IdentifierInfo **SelIdents,
6927 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006928 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006929 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006930 if (ExternalSource) {
6931 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6932 I != N; ++I) {
6933 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006934 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006935 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006936
6937 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006938 }
6939 }
6940
6941 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006942 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006943 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006944 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006945 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006946
6947 if (ReturnTy)
6948 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006949
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006950 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006951 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6952 MEnd = MethodPool.end();
6953 M != MEnd; ++M) {
6954 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6955 &M->second.second;
6956 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006957 MethList = MethList->Next) {
6958 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6959 NumSelIdents))
6960 continue;
6961
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006962 if (AtParameterName) {
6963 // Suggest parameter names we've seen before.
6964 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6965 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6966 if (Param->getIdentifier()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006967 CodeCompletionBuilder Builder(Results.getAllocator(),
6968 Results.getCodeCompletionTUInfo());
Douglas Gregordae68752011-02-01 22:57:45 +00006969 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006970 Param->getIdentifier()->getName()));
6971 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006972 }
6973 }
6974
6975 continue;
6976 }
6977
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006978 Result R(MethList->Method, 0);
6979 R.StartParameter = NumSelIdents;
6980 R.AllParametersAreInformative = false;
6981 R.DeclaringEntity = true;
6982 Results.MaybeAddResult(R, CurContext);
6983 }
6984 }
6985
6986 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006987 HandleCodeCompleteResults(this, CodeCompleter,
6988 CodeCompletionContext::CCC_Other,
6989 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006990}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006991
Douglas Gregorf29c5232010-08-24 22:20:20 +00006992void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006993 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006994 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006995 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006996 Results.EnterNewScope();
6997
6998 // #if <condition>
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006999 CodeCompletionBuilder Builder(Results.getAllocator(),
7000 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007001 Builder.AddTypedTextChunk("if");
7002 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7003 Builder.AddPlaceholderChunk("condition");
7004 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007005
7006 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007007 Builder.AddTypedTextChunk("ifdef");
7008 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7009 Builder.AddPlaceholderChunk("macro");
7010 Results.AddResult(Builder.TakeString());
7011
Douglas Gregorf44e8542010-08-24 19:08:16 +00007012 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007013 Builder.AddTypedTextChunk("ifndef");
7014 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7015 Builder.AddPlaceholderChunk("macro");
7016 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007017
7018 if (InConditional) {
7019 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00007020 Builder.AddTypedTextChunk("elif");
7021 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7022 Builder.AddPlaceholderChunk("condition");
7023 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007024
7025 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00007026 Builder.AddTypedTextChunk("else");
7027 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007028
7029 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00007030 Builder.AddTypedTextChunk("endif");
7031 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007032 }
7033
7034 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007035 Builder.AddTypedTextChunk("include");
7036 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7037 Builder.AddTextChunk("\"");
7038 Builder.AddPlaceholderChunk("header");
7039 Builder.AddTextChunk("\"");
7040 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007041
7042 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007043 Builder.AddTypedTextChunk("include");
7044 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7045 Builder.AddTextChunk("<");
7046 Builder.AddPlaceholderChunk("header");
7047 Builder.AddTextChunk(">");
7048 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007049
7050 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007051 Builder.AddTypedTextChunk("define");
7052 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7053 Builder.AddPlaceholderChunk("macro");
7054 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007055
7056 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00007057 Builder.AddTypedTextChunk("define");
7058 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7059 Builder.AddPlaceholderChunk("macro");
7060 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7061 Builder.AddPlaceholderChunk("args");
7062 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7063 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007064
7065 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007066 Builder.AddTypedTextChunk("undef");
7067 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7068 Builder.AddPlaceholderChunk("macro");
7069 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007070
7071 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00007072 Builder.AddTypedTextChunk("line");
7073 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7074 Builder.AddPlaceholderChunk("number");
7075 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007076
7077 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00007078 Builder.AddTypedTextChunk("line");
7079 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7080 Builder.AddPlaceholderChunk("number");
7081 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7082 Builder.AddTextChunk("\"");
7083 Builder.AddPlaceholderChunk("filename");
7084 Builder.AddTextChunk("\"");
7085 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007086
7087 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007088 Builder.AddTypedTextChunk("error");
7089 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7090 Builder.AddPlaceholderChunk("message");
7091 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007092
7093 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00007094 Builder.AddTypedTextChunk("pragma");
7095 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7096 Builder.AddPlaceholderChunk("arguments");
7097 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007098
David Blaikie4e4d0842012-03-11 07:00:24 +00007099 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00007100 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007101 Builder.AddTypedTextChunk("import");
7102 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7103 Builder.AddTextChunk("\"");
7104 Builder.AddPlaceholderChunk("header");
7105 Builder.AddTextChunk("\"");
7106 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007107
7108 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007109 Builder.AddTypedTextChunk("import");
7110 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7111 Builder.AddTextChunk("<");
7112 Builder.AddPlaceholderChunk("header");
7113 Builder.AddTextChunk(">");
7114 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007115 }
7116
7117 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007118 Builder.AddTypedTextChunk("include_next");
7119 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7120 Builder.AddTextChunk("\"");
7121 Builder.AddPlaceholderChunk("header");
7122 Builder.AddTextChunk("\"");
7123 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007124
7125 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007126 Builder.AddTypedTextChunk("include_next");
7127 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7128 Builder.AddTextChunk("<");
7129 Builder.AddPlaceholderChunk("header");
7130 Builder.AddTextChunk(">");
7131 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007132
7133 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007134 Builder.AddTypedTextChunk("warning");
7135 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7136 Builder.AddPlaceholderChunk("message");
7137 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007138
7139 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7140 // completions for them. And __include_macros is a Clang-internal extension
7141 // that we don't want to encourage anyone to use.
7142
7143 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7144 Results.ExitScope();
7145
Douglas Gregorf44e8542010-08-24 19:08:16 +00007146 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00007147 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00007148 Results.data(), Results.size());
7149}
7150
7151void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007152 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007153 S->getFnParent()? Sema::PCC_RecoveryInFunction
7154 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007155}
7156
Douglas Gregorf29c5232010-08-24 22:20:20 +00007157void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007158 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007159 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007160 IsDefinition? CodeCompletionContext::CCC_MacroName
7161 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007162 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7163 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007164 CodeCompletionBuilder Builder(Results.getAllocator(),
7165 Results.getCodeCompletionTUInfo());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007166 Results.EnterNewScope();
7167 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7168 MEnd = PP.macro_end();
7169 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007170 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007171 M->first->getName()));
Argyrios Kyrtzidisc04bb922012-09-27 00:24:09 +00007172 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7173 CCP_CodePattern,
7174 CXCursor_MacroDefinition));
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007175 }
7176 Results.ExitScope();
7177 } else if (IsDefinition) {
7178 // FIXME: Can we detect when the user just wrote an include guard above?
7179 }
7180
Douglas Gregor52779fb2010-09-23 23:01:17 +00007181 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007182 Results.data(), Results.size());
7183}
7184
Douglas Gregorf29c5232010-08-24 22:20:20 +00007185void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007186 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007187 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007188 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007189
7190 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00007191 AddMacroResults(PP, Results, true);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007192
7193 // defined (<macro>)
7194 Results.EnterNewScope();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007195 CodeCompletionBuilder Builder(Results.getAllocator(),
7196 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007197 Builder.AddTypedTextChunk("defined");
7198 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7199 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7200 Builder.AddPlaceholderChunk("macro");
7201 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7202 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007203 Results.ExitScope();
7204
7205 HandleCodeCompleteResults(this, CodeCompleter,
7206 CodeCompletionContext::CCC_PreprocessorExpression,
7207 Results.data(), Results.size());
7208}
7209
7210void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7211 IdentifierInfo *Macro,
7212 MacroInfo *MacroInfo,
7213 unsigned Argument) {
7214 // FIXME: In the future, we could provide "overload" results, much like we
7215 // do for function calls.
7216
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007217 // Now just ignore this. There will be another code-completion callback
7218 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007219}
7220
Douglas Gregor55817af2010-08-25 17:04:25 +00007221void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007222 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007223 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007224 0, 0);
7225}
7226
Douglas Gregordae68752011-02-01 22:57:45 +00007227void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007228 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007229 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007230 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7231 CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007232 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7233 CodeCompletionDeclConsumer Consumer(Builder,
7234 Context.getTranslationUnitDecl());
7235 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7236 Consumer);
7237 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007238
7239 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00007240 AddMacroResults(PP, Builder, true);
Douglas Gregor87c08a52010-08-13 22:48:40 +00007241
7242 Results.clear();
7243 Results.insert(Results.end(),
7244 Builder.data(), Builder.data() + Builder.size());
7245}