blob: 15737b39282bb4aca939f8f7e666450b1c9e6cd6 [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());
2486 Pattern->ParentKind = Result.getParentKind();
2487 Pattern->ParentName = Result.getParentName();
2488 }
2489
Douglas Gregor218937c2011-02-01 19:23:04 +00002490 return Pattern;
2491 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002492
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002493 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002494 Result.AddTypedTextChunk(Keyword);
2495 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002496 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002497
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002498 if (Kind == RK_Macro) {
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002499 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002500 assert(MI && "Not a macro?");
2501
Douglas Gregordae68752011-02-01 22:57:45 +00002502 Result.AddTypedTextChunk(
2503 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002504
2505 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002506 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002507
2508 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002509 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregore4244702011-07-30 08:17:44 +00002510 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002511
2512 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2513 if (MI->isC99Varargs()) {
2514 --AEnd;
2515
2516 if (A == AEnd) {
2517 Result.AddPlaceholderChunk("...");
2518 }
Douglas Gregore4244702011-07-30 08:17:44 +00002519 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002520
Douglas Gregore4244702011-07-30 08:17:44 +00002521 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002522 if (A != MI->arg_begin())
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002523 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002524
2525 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002526 SmallString<32> Arg = (*A)->getName();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002527 if (MI->isC99Varargs())
2528 Arg += ", ...";
2529 else
2530 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002531 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002532 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002533 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002534
2535 // Non-variadic macros are simple.
2536 Result.AddPlaceholderChunk(
2537 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002538 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002539 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002540 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002541 }
2542
Douglas Gregord8e8a582010-05-25 21:41:55 +00002543 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002544 NamedDecl *ND = Declaration;
Douglas Gregorba103062012-03-27 23:34:16 +00002545 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002546
2547 if (IncludeBriefComments) {
2548 // Add documentation comment, if it exists.
Dmitri Gribenkof50555e2012-08-11 00:51:43 +00002549 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002550 Result.addBriefComment(RC->getBriefText(Ctx));
2551 }
2552 }
2553
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002554 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002555 Result.AddTypedTextChunk(
2556 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002557 Result.AddTextChunk("::");
2558 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002559 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002560
2561 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2562 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2563 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2564 }
2565 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002566
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002567 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002568
Douglas Gregor86d9a522009-09-21 16:56:56 +00002569 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002570 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002571 Ctx, Policy);
2572 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002573 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002574 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002575 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002576 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002577 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002578 }
2579
2580 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002581 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002582 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002583 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002584 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002585
Douglas Gregor86d9a522009-09-21 16:56:56 +00002586 // Figure out which template parameters are deduced (or have default
2587 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002588 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002589 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002590 unsigned LastDeducibleArgument;
2591 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2592 --LastDeducibleArgument) {
2593 if (!Deduced[LastDeducibleArgument - 1]) {
2594 // C++0x: Figure out if the template argument has a default. If so,
2595 // the user doesn't need to type this argument.
2596 // FIXME: We need to abstract template parameters better!
2597 bool HasDefaultArg = false;
2598 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002599 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002600 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2601 HasDefaultArg = TTP->hasDefaultArgument();
2602 else if (NonTypeTemplateParmDecl *NTTP
2603 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2604 HasDefaultArg = NTTP->hasDefaultArgument();
2605 else {
2606 assert(isa<TemplateTemplateParmDecl>(Param));
2607 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002608 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002609 }
2610
2611 if (!HasDefaultArg)
2612 break;
2613 }
2614 }
2615
2616 if (LastDeducibleArgument) {
2617 // Some of the function template arguments cannot be deduced from a
2618 // function call, so we introduce an explicit template argument list
2619 // containing all of the arguments up to the first deducible argument.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002620 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002621 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002622 LastDeducibleArgument);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002623 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002624 }
2625
2626 // Add the function parameters
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002627 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002628 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002629 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002630 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002631 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002632 }
2633
2634 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002635 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002636 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002637 Result.AddTypedTextChunk(
2638 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002639 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002640 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002641 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor218937c2011-02-01 19:23:04 +00002642 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002643 }
2644
Douglas Gregor9630eb62009-11-17 16:44:22 +00002645 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002646 Selector Sel = Method->getSelector();
2647 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002648 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002649 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002650 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002651 }
2652
Douglas Gregor813d8342011-02-18 22:29:55 +00002653 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002654 SelName += ':';
2655 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002656 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002657 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002658 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002659
2660 // If there is only one parameter, and we're past it, add an empty
2661 // typed-text chunk since there is nothing to type.
2662 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002663 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002664 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002665 unsigned Idx = 0;
2666 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2667 PEnd = Method->param_end();
2668 P != PEnd; (void)++P, ++Idx) {
2669 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002670 std::string Keyword;
2671 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002672 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002673 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002674 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002675 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002676 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002677 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002678 else
Douglas Gregordae68752011-02-01 22:57:45 +00002679 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002680 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002681
2682 // If we're before the starting parameter, skip the placeholder.
2683 if (Idx < StartParameter)
2684 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002685
2686 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002687
2688 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002689 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002690 else {
John McCallf85e1932011-06-15 23:02:42 +00002691 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002692 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2693 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002694 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002695 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002696 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002697 }
2698
Douglas Gregore17794f2010-08-31 05:13:43 +00002699 if (Method->isVariadic() && (P + 1) == PEnd)
2700 Arg += ", ...";
2701
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002702 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002703 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002704 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002705 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002706 else
Douglas Gregordae68752011-02-01 22:57:45 +00002707 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002708 }
2709
Douglas Gregor2a17af02009-12-23 00:21:46 +00002710 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002711 if (Method->param_size() == 0) {
2712 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002713 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002714 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002715 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002716 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002717 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002718 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002719
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002720 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002721 }
2722
Douglas Gregor218937c2011-02-01 19:23:04 +00002723 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002724 }
2725
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002726 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002727 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002728 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002729
Douglas Gregordae68752011-02-01 22:57:45 +00002730 Result.AddTypedTextChunk(
2731 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002732 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002733}
2734
Douglas Gregor86d802e2009-09-23 00:34:09 +00002735CodeCompletionString *
2736CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2737 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002738 Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002739 CodeCompletionAllocator &Allocator,
2740 CodeCompletionTUInfo &CCTUInfo) const {
Douglas Gregor8987b232011-09-27 23:30:47 +00002741 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002742
Douglas Gregor218937c2011-02-01 19:23:04 +00002743 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002744 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002745 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002746 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002747 const FunctionProtoType *Proto
2748 = dyn_cast<FunctionProtoType>(getFunctionType());
2749 if (!FDecl && !Proto) {
2750 // Function without a prototype. Just give the return type and a
2751 // highlighted ellipsis.
2752 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002753 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002754 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002755 Result.getAllocator()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002756 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2757 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2758 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002759 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002760 }
2761
2762 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002763 Result.AddTextChunk(
2764 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002765 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002766 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002767 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002768 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002769
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002770 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002771 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2772 for (unsigned I = 0; I != NumParams; ++I) {
2773 if (I)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002774 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002775
2776 std::string ArgString;
2777 QualType ArgType;
2778
2779 if (FDecl) {
2780 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2781 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2782 } else {
2783 ArgType = Proto->getArgType(I);
2784 }
2785
John McCallf85e1932011-06-15 23:02:42 +00002786 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002787
2788 if (I == CurrentArg)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002789 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2790 Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002791 else
Douglas Gregordae68752011-02-01 22:57:45 +00002792 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002793 }
2794
2795 if (Proto && Proto->isVariadic()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002796 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002797 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002798 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002799 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002800 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002801 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002802 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002803
Douglas Gregor218937c2011-02-01 19:23:04 +00002804 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002805}
2806
Chris Lattner5f9e2722011-07-23 10:55:15 +00002807unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002808 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002809 bool PreferredTypeIsPointer) {
2810 unsigned Priority = CCP_Macro;
2811
Douglas Gregorb05496d2010-09-20 21:11:48 +00002812 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2813 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2814 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002815 Priority = CCP_Constant;
2816 if (PreferredTypeIsPointer)
2817 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002818 }
2819 // Treat "YES", "NO", "true", and "false" as constants.
2820 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2821 MacroName.equals("true") || MacroName.equals("false"))
2822 Priority = CCP_Constant;
2823 // Treat "bool" as a type.
2824 else if (MacroName.equals("bool"))
2825 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2826
Douglas Gregor1827e102010-08-16 16:18:59 +00002827
2828 return Priority;
2829}
2830
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002831CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2832 if (!D)
2833 return CXCursor_UnexposedDecl;
2834
2835 switch (D->getKind()) {
2836 case Decl::Enum: return CXCursor_EnumDecl;
2837 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2838 case Decl::Field: return CXCursor_FieldDecl;
2839 case Decl::Function:
2840 return CXCursor_FunctionDecl;
2841 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2842 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002843 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002844
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002845 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002846 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2847 case Decl::ObjCMethod:
2848 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2849 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2850 case Decl::CXXMethod: return CXCursor_CXXMethod;
2851 case Decl::CXXConstructor: return CXCursor_Constructor;
2852 case Decl::CXXDestructor: return CXCursor_Destructor;
2853 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2854 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002855 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002856 case Decl::ParmVar: return CXCursor_ParmDecl;
2857 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002858 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002859 case Decl::Var: return CXCursor_VarDecl;
2860 case Decl::Namespace: return CXCursor_Namespace;
2861 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2862 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2863 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2864 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2865 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2866 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002867 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002868 case Decl::ClassTemplatePartialSpecialization:
2869 return CXCursor_ClassTemplatePartialSpecialization;
2870 case Decl::UsingDirective: return CXCursor_UsingDirective;
Douglas Gregor8e5900c2012-04-30 23:41:16 +00002871 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002872
2873 case Decl::Using:
2874 case Decl::UnresolvedUsingValue:
2875 case Decl::UnresolvedUsingTypename:
2876 return CXCursor_UsingDeclaration;
2877
Douglas Gregor352697a2011-06-03 23:08:58 +00002878 case Decl::ObjCPropertyImpl:
2879 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2880 case ObjCPropertyImplDecl::Dynamic:
2881 return CXCursor_ObjCDynamicDecl;
2882
2883 case ObjCPropertyImplDecl::Synthesize:
2884 return CXCursor_ObjCSynthesizeDecl;
2885 }
Douglas Gregor352697a2011-06-03 23:08:58 +00002886
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002887 default:
2888 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2889 switch (TD->getTagKind()) {
Joao Matos6666ed42012-08-31 18:45:21 +00002890 case TTK_Interface: // fall through
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002891 case TTK_Struct: return CXCursor_StructDecl;
2892 case TTK_Class: return CXCursor_ClassDecl;
2893 case TTK_Union: return CXCursor_UnionDecl;
2894 case TTK_Enum: return CXCursor_EnumDecl;
2895 }
2896 }
2897 }
2898
2899 return CXCursor_UnexposedDecl;
2900}
2901
Douglas Gregor590c7d52010-07-08 20:55:51 +00002902static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2903 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002904 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002905
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002906 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002907
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002908 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2909 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002910 M != MEnd; ++M) {
Alexander Kornienko8a64bb52012-08-29 00:20:03 +00002911 // FIXME: Eventually, we'd want to be able to look back to the macro
2912 // definition that was actually active at the point of code completion (even
2913 // if that macro has since been #undef'd).
2914 if (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) {
John McCall0a2c5e22010-08-25 06:19:51 +00003136 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003137 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003138 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003139 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003140 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003141
Douglas Gregor01dfea02010-01-10 23:08:15 +00003142 // Determine how to filter results, e.g., so that the names of
3143 // values (functions, enumerators, function templates, etc.) are
3144 // only allowed where we can have an expression.
3145 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003146 case PCC_Namespace:
3147 case PCC_Class:
3148 case PCC_ObjCInterface:
3149 case PCC_ObjCImplementation:
3150 case PCC_ObjCInstanceVariableList:
3151 case PCC_Template:
3152 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003153 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003154 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003155 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3156 break;
3157
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003158 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003159 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003160 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003161 case PCC_ForInit:
3162 case PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00003163 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003164 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3165 else
3166 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003167
David Blaikie4e4d0842012-03-11 07:00:24 +00003168 if (getLangOpts().CPlusPlus)
Douglas Gregorf6961522010-08-27 21:18:54 +00003169 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003170 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003171
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003172 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003173 // Unfiltered
3174 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003175 }
3176
Douglas Gregor3cdee122010-08-26 16:36:48 +00003177 // If we are in a C++ non-static member function, check the qualifiers on
3178 // the member function to filter/prioritize the results list.
3179 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3180 if (CurMethod->isInstance())
3181 Results.setObjectTypeQualifiers(
3182 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3183
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003184 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003185 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3186 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003187
Douglas Gregorbca403c2010-01-13 23:51:12 +00003188 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003189 Results.ExitScope();
3190
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003191 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003192 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003193 case PCC_Expression:
3194 case PCC_Statement:
3195 case PCC_RecoveryInFunction:
3196 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003197 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor72db1082010-08-24 01:11:00 +00003198 break;
3199
3200 case PCC_Namespace:
3201 case PCC_Class:
3202 case PCC_ObjCInterface:
3203 case PCC_ObjCImplementation:
3204 case PCC_ObjCInstanceVariableList:
3205 case PCC_Template:
3206 case PCC_MemberTemplate:
3207 case PCC_ForInit:
3208 case PCC_Condition:
3209 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003210 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003211 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003212 }
3213
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003214 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003215 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003216
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003217 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003218 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003219}
3220
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003221static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3222 ParsedType Receiver,
3223 IdentifierInfo **SelIdents,
3224 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003225 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003226 bool IsSuper,
3227 ResultBuilder &Results);
3228
3229void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3230 bool AllowNonIdentifiers,
3231 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003232 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003233 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003234 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003235 AllowNestedNameSpecifiers
3236 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3237 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003238 Results.EnterNewScope();
3239
3240 // Type qualifiers can come after names.
3241 Results.AddResult(Result("const"));
3242 Results.AddResult(Result("volatile"));
David Blaikie4e4d0842012-03-11 07:00:24 +00003243 if (getLangOpts().C99)
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003244 Results.AddResult(Result("restrict"));
3245
David Blaikie4e4d0842012-03-11 07:00:24 +00003246 if (getLangOpts().CPlusPlus) {
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003247 if (AllowNonIdentifiers) {
3248 Results.AddResult(Result("operator"));
3249 }
3250
3251 // Add nested-name-specifiers.
3252 if (AllowNestedNameSpecifiers) {
3253 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003254 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003255 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3256 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3257 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003258 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003259 }
3260 }
3261 Results.ExitScope();
3262
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003263 // If we're in a context where we might have an expression (rather than a
3264 // declaration), and what we've seen so far is an Objective-C type that could
3265 // be a receiver of a class message, this may be a class message send with
3266 // the initial opening bracket '[' missing. Add appropriate completions.
3267 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3268 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3269 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3270 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3271 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3272 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3273 DS.getTypeQualifiers() == 0 &&
3274 S &&
3275 (S->getFlags() & Scope::DeclScope) != 0 &&
3276 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3277 Scope::FunctionPrototypeScope |
3278 Scope::AtCatchScope)) == 0) {
3279 ParsedType T = DS.getRepAsType();
3280 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003281 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003282 }
3283
Douglas Gregor4497dd42010-08-24 04:59:56 +00003284 // Note that we intentionally suppress macro results here, since we do not
3285 // encourage using macros to produce the names of entities.
3286
Douglas Gregor52779fb2010-09-23 23:01:17 +00003287 HandleCodeCompleteResults(this, CodeCompleter,
3288 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003289 Results.data(), Results.size());
3290}
3291
Douglas Gregorfb629412010-08-23 21:17:50 +00003292struct Sema::CodeCompleteExpressionData {
3293 CodeCompleteExpressionData(QualType PreferredType = QualType())
3294 : PreferredType(PreferredType), IntegralConstantExpression(false),
3295 ObjCCollection(false) { }
3296
3297 QualType PreferredType;
3298 bool IntegralConstantExpression;
3299 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003300 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003301};
3302
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003303/// \brief Perform code-completion in an expression context when we know what
3304/// type we're looking for.
Douglas Gregorfb629412010-08-23 21:17:50 +00003305void Sema::CodeCompleteExpression(Scope *S,
3306 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00003307 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003308 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003309 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003310 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003311 if (Data.ObjCCollection)
3312 Results.setFilter(&ResultBuilder::IsObjCCollection);
3313 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003314 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikie4e4d0842012-03-11 07:00:24 +00003315 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003316 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3317 else
3318 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003319
3320 if (!Data.PreferredType.isNull())
3321 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3322
3323 // Ignore any declarations that we were told that we don't care about.
3324 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3325 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003326
3327 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003328 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3329 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003330
3331 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003332 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003333 Results.ExitScope();
3334
Douglas Gregor590c7d52010-07-08 20:55:51 +00003335 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003336 if (!Data.PreferredType.isNull())
3337 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3338 || Data.PreferredType->isMemberPointerType()
3339 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003340
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003341 if (S->getFnParent() &&
3342 !Data.ObjCCollection &&
3343 !Data.IntegralConstantExpression)
David Blaikie4e4d0842012-03-11 07:00:24 +00003344 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003345
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003346 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003347 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003348 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003349 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3350 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003351 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003352}
3353
Douglas Gregorac5fd842010-09-18 01:28:11 +00003354void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3355 if (E.isInvalid())
3356 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikie4e4d0842012-03-11 07:00:24 +00003357 else if (getLangOpts().ObjC1)
Douglas Gregorac5fd842010-09-18 01:28:11 +00003358 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003359}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003360
Douglas Gregor73449212010-12-09 23:01:55 +00003361/// \brief The set of properties that have already been added, referenced by
3362/// property name.
3363typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3364
Douglas Gregorb92a4082012-06-12 13:44:08 +00003365/// \brief Retrieve the container definition, if any?
3366static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3367 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3368 if (Interface->hasDefinition())
3369 return Interface->getDefinition();
3370
3371 return Interface;
3372 }
3373
3374 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3375 if (Protocol->hasDefinition())
3376 return Protocol->getDefinition();
3377
3378 return Protocol;
3379 }
3380 return Container;
3381}
3382
3383static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003384 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003385 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003386 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003387 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003388 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003389 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003390
Douglas Gregorb92a4082012-06-12 13:44:08 +00003391 // Retrieve the definition.
3392 Container = getContainerDef(Container);
3393
Douglas Gregor95ac6552009-11-18 01:29:26 +00003394 // Add properties in this container.
3395 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3396 PEnd = Container->prop_end();
3397 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003398 ++P) {
3399 if (AddedProperties.insert(P->getIdentifier()))
David Blaikie581deb32012-06-06 20:45:41 +00003400 Results.MaybeAddResult(Result(*P, 0), CurContext);
Douglas Gregor73449212010-12-09 23:01:55 +00003401 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003402
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003403 // Add nullary methods
3404 if (AllowNullaryMethods) {
3405 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003406 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003407 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3408 MEnd = Container->meth_end();
3409 M != MEnd; ++M) {
3410 if (M->getSelector().isUnarySelector())
3411 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3412 if (AddedProperties.insert(Name)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003413 CodeCompletionBuilder Builder(Results.getAllocator(),
3414 Results.getCodeCompletionTUInfo());
David Blaikie581deb32012-06-06 20:45:41 +00003415 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003416 Builder.AddTypedTextChunk(
3417 Results.getAllocator().CopyString(Name->getName()));
3418
David Blaikie581deb32012-06-06 20:45:41 +00003419 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
Douglas Gregorba103062012-03-27 23:34:16 +00003420 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003421 CurContext);
3422 }
3423 }
3424 }
3425
3426
Douglas Gregor95ac6552009-11-18 01:29:26 +00003427 // Add properties in referenced protocols.
3428 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3429 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3430 PEnd = Protocol->protocol_end();
3431 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003432 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3433 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003434 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003435 if (AllowCategories) {
3436 // Look through categories.
3437 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3438 Category; Category = Category->getNextClassCategory())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003439 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3440 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003441 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003442
3443 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003444 for (ObjCInterfaceDecl::all_protocol_iterator
3445 I = IFace->all_referenced_protocol_begin(),
3446 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003447 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3448 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003449
3450 // Look in the superclass.
3451 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003452 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3453 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003454 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003455 } else if (const ObjCCategoryDecl *Category
3456 = dyn_cast<ObjCCategoryDecl>(Container)) {
3457 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003458 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3459 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003460 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003461 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3462 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003463 }
3464}
3465
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003466void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003467 SourceLocation OpLoc,
3468 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003469 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003470 return;
3471
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003472 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3473 if (ConvertedBase.isInvalid())
3474 return;
3475 Base = ConvertedBase.get();
3476
John McCall0a2c5e22010-08-25 06:19:51 +00003477 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003478
Douglas Gregor81b747b2009-09-17 21:32:03 +00003479 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003480
3481 if (IsArrow) {
3482 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3483 BaseType = Ptr->getPointeeType();
3484 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003485 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003486 else
3487 return;
3488 }
3489
Douglas Gregor3da626b2011-07-07 16:03:39 +00003490 enum CodeCompletionContext::Kind contextKind;
3491
3492 if (IsArrow) {
3493 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3494 }
3495 else {
3496 if (BaseType->isObjCObjectPointerType() ||
3497 BaseType->isObjCObjectOrInterfaceType()) {
3498 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3499 }
3500 else {
3501 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3502 }
3503 }
3504
Douglas Gregor218937c2011-02-01 19:23:04 +00003505 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003506 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003507 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003508 BaseType),
3509 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003510 Results.EnterNewScope();
3511 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003512 // Indicate that we are performing a member access, and the cv-qualifiers
3513 // for the base object type.
3514 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3515
Douglas Gregor95ac6552009-11-18 01:29:26 +00003516 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003517 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003518 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003519 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3520 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003521
David Blaikie4e4d0842012-03-11 07:00:24 +00003522 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003523 if (!Results.empty()) {
3524 // The "template" keyword can follow "->" or "." in the grammar.
3525 // However, we only want to suggest the template keyword if something
3526 // is dependent.
3527 bool IsDependent = BaseType->isDependentType();
3528 if (!IsDependent) {
3529 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3530 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3531 IsDependent = Ctx->isDependentContext();
3532 break;
3533 }
3534 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003535
Douglas Gregor95ac6552009-11-18 01:29:26 +00003536 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003537 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003538 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003539 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003540 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3541 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003542 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003543
3544 // Add property results based on our interface.
3545 const ObjCObjectPointerType *ObjCPtr
3546 = BaseType->getAsObjCInterfacePointerType();
3547 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003548 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3549 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003550 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003551
3552 // Add properties from the protocols in a qualified interface.
3553 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3554 E = ObjCPtr->qual_end();
3555 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003556 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3557 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003558 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003559 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003560 // Objective-C instance variable access.
3561 ObjCInterfaceDecl *Class = 0;
3562 if (const ObjCObjectPointerType *ObjCPtr
3563 = BaseType->getAs<ObjCObjectPointerType>())
3564 Class = ObjCPtr->getInterfaceDecl();
3565 else
John McCallc12c5bb2010-05-15 11:32:37 +00003566 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003567
3568 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003569 if (Class) {
3570 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3571 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003572 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3573 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003574 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003575 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003576
3577 // FIXME: How do we cope with isa?
3578
3579 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003580
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003581 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003582 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003583 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003584 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003585}
3586
Douglas Gregor374929f2009-09-18 15:37:17 +00003587void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3588 if (!CodeCompleter)
3589 return;
3590
John McCall0a2c5e22010-08-25 06:19:51 +00003591 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003592 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003593 enum CodeCompletionContext::Kind ContextKind
3594 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003595 switch ((DeclSpec::TST)TagSpec) {
3596 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003597 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003598 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003599 break;
3600
3601 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003602 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003603 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003604 break;
3605
3606 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003607 case DeclSpec::TST_class:
Joao Matos6666ed42012-08-31 18:45:21 +00003608 case DeclSpec::TST_interface:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003609 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003610 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003611 break;
3612
3613 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003614 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003615 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003616
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003617 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3618 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003619 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003620
3621 // First pass: look for tags.
3622 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003623 LookupVisibleDecls(S, LookupTagName, Consumer,
3624 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003625
Douglas Gregor8071e422010-08-15 06:18:01 +00003626 if (CodeCompleter->includeGlobals()) {
3627 // Second pass: look for nested name specifiers.
3628 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3629 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3630 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003631
Douglas Gregor52779fb2010-09-23 23:01:17 +00003632 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003633 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003634}
3635
Douglas Gregor1a480c42010-08-27 17:35:51 +00003636void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003637 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003638 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003639 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003640 Results.EnterNewScope();
3641 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3642 Results.AddResult("const");
3643 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3644 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003645 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003646 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3647 Results.AddResult("restrict");
3648 Results.ExitScope();
3649 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003650 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003651 Results.data(), Results.size());
3652}
3653
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003654void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003655 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003656 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003657
John McCall781472f2010-08-25 08:40:02 +00003658 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003659 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3660 if (!type->isEnumeralType()) {
3661 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003662 Data.IntegralConstantExpression = true;
3663 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003664 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003665 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003666
3667 // Code-complete the cases of a switch statement over an enumeration type
3668 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003669 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregorb92a4082012-06-12 13:44:08 +00003670 if (EnumDecl *Def = Enum->getDefinition())
3671 Enum = Def;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003672
3673 // Determine which enumerators we have already seen in the switch statement.
3674 // FIXME: Ideally, we would also be able to look *past* the code-completion
3675 // token, in case we are code-completing in the middle of the switch and not
3676 // at the end. However, we aren't able to do so at the moment.
3677 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003678 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003679 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3680 SC = SC->getNextSwitchCase()) {
3681 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3682 if (!Case)
3683 continue;
3684
3685 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3686 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3687 if (EnumConstantDecl *Enumerator
3688 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3689 // We look into the AST of the case statement to determine which
3690 // enumerator was named. Alternatively, we could compute the value of
3691 // the integral constant expression, then compare it against the
3692 // values of each enumerator. However, value-based approach would not
3693 // work as well with C++ templates where enumerators declared within a
3694 // template are type- and value-dependent.
3695 EnumeratorsSeen.insert(Enumerator);
3696
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003697 // If this is a qualified-id, keep track of the nested-name-specifier
3698 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003699 //
3700 // switch (TagD.getKind()) {
3701 // case TagDecl::TK_enum:
3702 // break;
3703 // case XXX
3704 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003705 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003706 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3707 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003708 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003709 }
3710 }
3711
David Blaikie4e4d0842012-03-11 07:00:24 +00003712 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003713 // If there are no prior enumerators in C++, check whether we have to
3714 // qualify the names of the enumerators that we suggest, because they
3715 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003716 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003717 }
3718
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003719 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003720 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003721 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003722 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003723 Results.EnterNewScope();
3724 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3725 EEnd = Enum->enumerator_end();
3726 E != EEnd; ++E) {
David Blaikie581deb32012-06-06 20:45:41 +00003727 if (EnumeratorsSeen.count(*E))
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003728 continue;
3729
David Blaikie581deb32012-06-06 20:45:41 +00003730 CodeCompletionResult R(*E, Qualifier);
Douglas Gregor5c722c702011-02-18 23:30:37 +00003731 R.Priority = CCP_EnumInCase;
3732 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003733 }
3734 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003735
Douglas Gregor3da626b2011-07-07 16:03:39 +00003736 //We need to make sure we're setting the right context,
3737 //so only say we include macros if the code completer says we do
3738 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3739 if (CodeCompleter->includeMacros()) {
Douglas Gregorbca403c2010-01-13 23:51:12 +00003740 AddMacroResults(PP, Results);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003741 kind = CodeCompletionContext::CCC_OtherWithMacros;
3742 }
3743
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003744 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003745 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003746 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003747}
3748
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003749namespace {
3750 struct IsBetterOverloadCandidate {
3751 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003752 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003753
3754 public:
John McCall5769d612010-02-08 23:07:23 +00003755 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3756 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003757
3758 bool
3759 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003760 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003761 }
3762 };
3763}
3764
Ahmed Charles13a140c2012-02-25 11:00:22 +00003765static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3766 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003767 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003768
3769 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003770 if (!Args[I])
3771 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003772
Douglas Gregord28dcd72010-05-30 06:10:08 +00003773 return false;
3774}
3775
Richard Trieuf81e5a92011-09-09 02:00:50 +00003776void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charles13a140c2012-02-25 11:00:22 +00003777 llvm::ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003778 if (!CodeCompleter)
3779 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003780
3781 // When we're code-completing for a call, we fall back to ordinary
3782 // name code-completion whenever we can't produce specific
3783 // results. We may want to revisit this strategy in the future,
3784 // e.g., by merging the two kinds of results.
3785
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003786 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003787
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003788 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003789 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3790 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003791 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003792 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003793 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003794
John McCall3b4294e2009-12-16 12:17:52 +00003795 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003796 SourceLocation Loc = Fn->getExprLoc();
3797 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003798
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003799 // FIXME: What if we're calling something that isn't a function declaration?
3800 // FIXME: What if we're calling a pseudo-destructor?
3801 // FIXME: What if we're calling a member function?
3802
Douglas Gregorc0265402010-01-21 15:46:19 +00003803 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003804 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003805
John McCall3b4294e2009-12-16 12:17:52 +00003806 Expr *NakedFn = Fn->IgnoreParenCasts();
3807 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003808 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003809 /*PartialOverloading=*/ true);
3810 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3811 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003812 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003813 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003814 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003815 Results.push_back(ResultCandidate(FDecl));
3816 else
John McCall86820f52010-01-26 01:37:31 +00003817 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003818 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3819 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003820 }
John McCall3b4294e2009-12-16 12:17:52 +00003821 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003822
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003823 QualType ParamType;
3824
Douglas Gregorc0265402010-01-21 15:46:19 +00003825 if (!CandidateSet.empty()) {
3826 // Sort the overload candidate set by placing the best overloads first.
3827 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003828 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003829
Douglas Gregorc0265402010-01-21 15:46:19 +00003830 // Add the remaining viable overload candidates as code-completion reslults.
3831 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3832 CandEnd = CandidateSet.end();
3833 Cand != CandEnd; ++Cand) {
3834 if (Cand->Viable)
3835 Results.push_back(ResultCandidate(Cand->Function));
3836 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003837
3838 // From the viable candidates, try to determine the type of this parameter.
3839 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3840 if (const FunctionType *FType = Results[I].getFunctionType())
3841 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003842 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003843 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003844 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003845 else if (!Context.hasSameUnqualifiedType(
3846 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003847 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003848 ParamType = QualType();
3849 break;
3850 }
3851 }
3852 }
3853 } else {
3854 // Try to determine the parameter type from the type of the expression
3855 // being called.
3856 QualType FunctionType = Fn->getType();
3857 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3858 FunctionType = Ptr->getPointeeType();
3859 else if (const BlockPointerType *BlockPtr
3860 = FunctionType->getAs<BlockPointerType>())
3861 FunctionType = BlockPtr->getPointeeType();
3862 else if (const MemberPointerType *MemPtr
3863 = FunctionType->getAs<MemberPointerType>())
3864 FunctionType = MemPtr->getPointeeType();
3865
3866 if (const FunctionProtoType *Proto
3867 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003868 if (Args.size() < Proto->getNumArgs())
3869 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003870 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003871 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003872
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003873 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003874 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003875 else
3876 CodeCompleteExpression(S, ParamType);
3877
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003878 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003879 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003880 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003881}
3882
John McCalld226f652010-08-21 09:40:31 +00003883void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3884 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003885 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003886 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003887 return;
3888 }
3889
3890 CodeCompleteExpression(S, VD->getType());
3891}
3892
3893void Sema::CodeCompleteReturn(Scope *S) {
3894 QualType ResultType;
3895 if (isa<BlockDecl>(CurContext)) {
3896 if (BlockScopeInfo *BSI = getCurBlock())
3897 ResultType = BSI->ReturnType;
3898 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3899 ResultType = Function->getResultType();
3900 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3901 ResultType = Method->getResultType();
3902
3903 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003904 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003905 else
3906 CodeCompleteExpression(S, ResultType);
3907}
3908
Douglas Gregord2d8be62011-07-30 08:36:53 +00003909void Sema::CodeCompleteAfterIf(Scope *S) {
3910 typedef CodeCompletionResult Result;
3911 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003912 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord2d8be62011-07-30 08:36:53 +00003913 mapCodeCompletionContext(*this, PCC_Statement));
3914 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3915 Results.EnterNewScope();
3916
3917 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3918 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3919 CodeCompleter->includeGlobals());
3920
3921 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3922
3923 // "else" block
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003924 CodeCompletionBuilder Builder(Results.getAllocator(),
3925 Results.getCodeCompletionTUInfo());
Douglas Gregord2d8be62011-07-30 08:36:53 +00003926 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00003927 if (Results.includeCodePatterns()) {
3928 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3929 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3930 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3931 Builder.AddPlaceholderChunk("statements");
3932 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3933 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3934 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003935 Results.AddResult(Builder.TakeString());
3936
3937 // "else if" block
3938 Builder.AddTypedTextChunk("else");
3939 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3940 Builder.AddTextChunk("if");
3941 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3942 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00003943 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00003944 Builder.AddPlaceholderChunk("condition");
3945 else
3946 Builder.AddPlaceholderChunk("expression");
3947 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00003948 if (Results.includeCodePatterns()) {
3949 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3950 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3951 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3952 Builder.AddPlaceholderChunk("statements");
3953 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3954 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3955 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003956 Results.AddResult(Builder.TakeString());
3957
3958 Results.ExitScope();
3959
3960 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003961 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003962
3963 if (CodeCompleter->includeMacros())
3964 AddMacroResults(PP, Results);
3965
3966 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3967 Results.data(),Results.size());
3968}
3969
Richard Trieuf81e5a92011-09-09 02:00:50 +00003970void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003971 if (LHS)
3972 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3973 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003974 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003975}
3976
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003977void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003978 bool EnteringContext) {
3979 if (!SS.getScopeRep() || !CodeCompleter)
3980 return;
3981
Douglas Gregor86d9a522009-09-21 16:56:56 +00003982 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3983 if (!Ctx)
3984 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003985
3986 // Try to instantiate any non-dependent declaration contexts before
3987 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003988 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003989 return;
3990
Douglas Gregor218937c2011-02-01 19:23:04 +00003991 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003992 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003993 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003994 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003995
Douglas Gregor86d9a522009-09-21 16:56:56 +00003996 // The "template" keyword can follow "::" in the grammar, but only
3997 // put it into the grammar if the nested-name-specifier is dependent.
3998 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3999 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00004000 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00004001
4002 // Add calls to overridden virtual functions, if there are any.
4003 //
4004 // FIXME: This isn't wonderful, because we don't know whether we're actually
4005 // in a context that permits expressions. This is a general issue with
4006 // qualified-id completions.
4007 if (!EnteringContext)
4008 MaybeAddOverrideCalls(*this, Ctx, Results);
4009 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004010
Douglas Gregorf6961522010-08-27 21:18:54 +00004011 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4012 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
4013
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004014 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00004015 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004016 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00004017}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004018
4019void Sema::CodeCompleteUsing(Scope *S) {
4020 if (!CodeCompleter)
4021 return;
4022
Douglas Gregor218937c2011-02-01 19:23:04 +00004023 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004024 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004025 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4026 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004027 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004028
4029 // If we aren't in class scope, we could see the "namespace" keyword.
4030 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00004031 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004032
4033 // After "using", we can see anything that would start a
4034 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004035 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004036 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4037 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004038 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004039
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004040 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004041 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004042 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004043}
4044
4045void Sema::CodeCompleteUsingDirective(Scope *S) {
4046 if (!CodeCompleter)
4047 return;
4048
Douglas Gregor86d9a522009-09-21 16:56:56 +00004049 // After "using namespace", we expect to see a namespace name or namespace
4050 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004051 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004052 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004053 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004054 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004055 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004056 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004057 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4058 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004059 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004060 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004061 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004062 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004063}
4064
4065void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4066 if (!CodeCompleter)
4067 return;
4068
Douglas Gregor86d9a522009-09-21 16:56:56 +00004069 DeclContext *Ctx = (DeclContext *)S->getEntity();
4070 if (!S->getParent())
4071 Ctx = Context.getTranslationUnitDecl();
4072
Douglas Gregor52779fb2010-09-23 23:01:17 +00004073 bool SuppressedGlobalResults
4074 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4075
Douglas Gregor218937c2011-02-01 19:23:04 +00004076 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004077 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004078 SuppressedGlobalResults
4079 ? CodeCompletionContext::CCC_Namespace
4080 : CodeCompletionContext::CCC_Other,
4081 &ResultBuilder::IsNamespace);
4082
4083 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004084 // We only want to see those namespaces that have already been defined
4085 // within this scope, because its likely that the user is creating an
4086 // extended namespace declaration. Keep track of the most recent
4087 // definition of each namespace.
4088 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4089 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4090 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4091 NS != NSEnd; ++NS)
David Blaikie581deb32012-06-06 20:45:41 +00004092 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004093
4094 // Add the most recent definition (or extended definition) of each
4095 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004096 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004097 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregorba103062012-03-27 23:34:16 +00004098 NS = OrigToLatest.begin(),
4099 NSEnd = OrigToLatest.end();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004100 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004101 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004102 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004103 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004104 }
4105
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004106 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004107 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004108 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004109}
4110
4111void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4112 if (!CodeCompleter)
4113 return;
4114
Douglas Gregor86d9a522009-09-21 16:56:56 +00004115 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004116 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004117 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004118 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004119 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004120 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004121 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4122 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004123 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004124 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004125 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004126}
4127
Douglas Gregored8d3222009-09-18 20:05:18 +00004128void Sema::CodeCompleteOperatorName(Scope *S) {
4129 if (!CodeCompleter)
4130 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004131
John McCall0a2c5e22010-08-25 06:19:51 +00004132 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004133 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004134 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004135 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004136 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004137 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004138
Douglas Gregor86d9a522009-09-21 16:56:56 +00004139 // Add the names of overloadable operators.
4140#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4141 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004142 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004143#include "clang/Basic/OperatorKinds.def"
4144
4145 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004146 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004147 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004148 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4149 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004150
4151 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004152 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004153 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004154
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004155 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004156 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004157 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004158}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004159
Douglas Gregor0133f522010-08-28 00:00:50 +00004160void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004161 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004162 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004163 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004164 CXXConstructorDecl *Constructor
4165 = static_cast<CXXConstructorDecl *>(ConstructorD);
4166 if (!Constructor)
4167 return;
4168
Douglas Gregor218937c2011-02-01 19:23:04 +00004169 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004170 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004171 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004172 Results.EnterNewScope();
4173
4174 // Fill in any already-initialized fields or base classes.
4175 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4176 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4177 for (unsigned I = 0; I != NumInitializers; ++I) {
4178 if (Initializers[I]->isBaseInitializer())
4179 InitializedBases.insert(
4180 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4181 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004182 InitializedFields.insert(cast<FieldDecl>(
4183 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004184 }
4185
4186 // Add completions for base classes.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004187 CodeCompletionBuilder Builder(Results.getAllocator(),
4188 Results.getCodeCompletionTUInfo());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004189 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004190 CXXRecordDecl *ClassDecl = Constructor->getParent();
4191 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4192 BaseEnd = ClassDecl->bases_end();
4193 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004194 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4195 SawLastInitializer
4196 = NumInitializers > 0 &&
4197 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4198 Context.hasSameUnqualifiedType(Base->getType(),
4199 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004200 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004201 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004202
Douglas Gregor218937c2011-02-01 19:23:04 +00004203 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004204 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004205 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004206 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4207 Builder.AddPlaceholderChunk("args");
4208 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4209 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004210 SawLastInitializer? CCP_NextInitializer
4211 : CCP_MemberDeclaration));
4212 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004213 }
4214
4215 // Add completions for virtual base classes.
4216 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4217 BaseEnd = ClassDecl->vbases_end();
4218 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004219 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4220 SawLastInitializer
4221 = NumInitializers > 0 &&
4222 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4223 Context.hasSameUnqualifiedType(Base->getType(),
4224 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004225 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004226 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004227
Douglas Gregor218937c2011-02-01 19:23:04 +00004228 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004229 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004230 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004231 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4232 Builder.AddPlaceholderChunk("args");
4233 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4234 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004235 SawLastInitializer? CCP_NextInitializer
4236 : CCP_MemberDeclaration));
4237 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004238 }
4239
4240 // Add completions for members.
4241 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4242 FieldEnd = ClassDecl->field_end();
4243 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004244 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4245 SawLastInitializer
4246 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004247 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
David Blaikie581deb32012-06-06 20:45:41 +00004248 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004249 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004250 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004251
4252 if (!Field->getDeclName())
4253 continue;
4254
Douglas Gregordae68752011-02-01 22:57:45 +00004255 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004256 Field->getIdentifier()->getName()));
4257 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4258 Builder.AddPlaceholderChunk("args");
4259 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4260 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004261 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004262 : CCP_MemberDeclaration,
Douglas Gregorba103062012-03-27 23:34:16 +00004263 CXCursor_MemberRef,
4264 CXAvailability_Available,
David Blaikie581deb32012-06-06 20:45:41 +00004265 *Field));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004266 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004267 }
4268 Results.ExitScope();
4269
Douglas Gregor52779fb2010-09-23 23:01:17 +00004270 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004271 Results.data(), Results.size());
4272}
4273
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004274/// \brief Determine whether this scope denotes a namespace.
4275static bool isNamespaceScope(Scope *S) {
4276 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4277 if (!DC)
4278 return false;
4279
4280 return DC->isFileContext();
4281}
4282
4283void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4284 bool AfterAmpersand) {
4285 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004286 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004287 CodeCompletionContext::CCC_Other);
4288 Results.EnterNewScope();
4289
4290 // Note what has already been captured.
4291 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4292 bool IncludedThis = false;
4293 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4294 CEnd = Intro.Captures.end();
4295 C != CEnd; ++C) {
4296 if (C->Kind == LCK_This) {
4297 IncludedThis = true;
4298 continue;
4299 }
4300
4301 Known.insert(C->Id);
4302 }
4303
4304 // Look for other capturable variables.
4305 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4306 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4307 D != DEnd; ++D) {
4308 VarDecl *Var = dyn_cast<VarDecl>(*D);
4309 if (!Var ||
4310 !Var->hasLocalStorage() ||
4311 Var->hasAttr<BlocksAttr>())
4312 continue;
4313
4314 if (Known.insert(Var->getIdentifier()))
4315 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4316 }
4317 }
4318
4319 // Add 'this', if it would be valid.
4320 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4321 addThisCompletion(*this, Results);
4322
4323 Results.ExitScope();
4324
4325 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4326 Results.data(), Results.size());
4327}
4328
James Dennetta40f7922012-06-14 03:11:41 +00004329/// Macro that optionally prepends an "@" to the string literal passed in via
4330/// Keyword, depending on whether NeedAt is true or false.
4331#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4332
Douglas Gregorbca403c2010-01-13 23:51:12 +00004333static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004334 ResultBuilder &Results,
4335 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004336 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004337 // Since we have an implementation, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004338 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004339
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004340 CodeCompletionBuilder Builder(Results.getAllocator(),
4341 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004342 if (LangOpts.ObjC2) {
4343 // @dynamic
James Dennetta40f7922012-06-14 03:11:41 +00004344 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004345 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4346 Builder.AddPlaceholderChunk("property");
4347 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004348
4349 // @synthesize
James Dennetta40f7922012-06-14 03:11:41 +00004350 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004351 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4352 Builder.AddPlaceholderChunk("property");
4353 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004354 }
4355}
4356
Douglas Gregorbca403c2010-01-13 23:51:12 +00004357static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004358 ResultBuilder &Results,
4359 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004360 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004361
4362 // Since we have an interface or protocol, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004363 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004364
4365 if (LangOpts.ObjC2) {
4366 // @property
James Dennetta40f7922012-06-14 03:11:41 +00004367 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004368
4369 // @required
James Dennetta40f7922012-06-14 03:11:41 +00004370 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004371
4372 // @optional
James Dennetta40f7922012-06-14 03:11:41 +00004373 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004374 }
4375}
4376
Douglas Gregorbca403c2010-01-13 23:51:12 +00004377static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004378 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004379 CodeCompletionBuilder Builder(Results.getAllocator(),
4380 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004381
4382 // @class name ;
James Dennetta40f7922012-06-14 03:11:41 +00004383 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004384 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4385 Builder.AddPlaceholderChunk("name");
4386 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004387
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004388 if (Results.includeCodePatterns()) {
4389 // @interface name
4390 // FIXME: Could introduce the whole pattern, including superclasses and
4391 // such.
James Dennetta40f7922012-06-14 03:11:41 +00004392 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004393 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4394 Builder.AddPlaceholderChunk("class");
4395 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004396
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004397 // @protocol name
James Dennetta40f7922012-06-14 03:11:41 +00004398 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004399 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4400 Builder.AddPlaceholderChunk("protocol");
4401 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004402
4403 // @implementation name
James Dennetta40f7922012-06-14 03:11:41 +00004404 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004405 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4406 Builder.AddPlaceholderChunk("class");
4407 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004408 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004409
4410 // @compatibility_alias name
James Dennetta40f7922012-06-14 03:11:41 +00004411 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004412 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4413 Builder.AddPlaceholderChunk("alias");
4414 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4415 Builder.AddPlaceholderChunk("class");
4416 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004417}
4418
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004419void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004420 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004421 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004422 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004423 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004424 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004425 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004426 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004427 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004428 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004429 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004430 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004431 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004432 HandleCodeCompleteResults(this, CodeCompleter,
4433 CodeCompletionContext::CCC_Other,
4434 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004435}
4436
Douglas Gregorbca403c2010-01-13 23:51:12 +00004437static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004438 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004439 CodeCompletionBuilder Builder(Results.getAllocator(),
4440 Results.getCodeCompletionTUInfo());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004441
4442 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004443 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004444 if (Results.getSema().getLangOpts().CPlusPlus ||
4445 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004446 EncodeType = "const char[]";
Douglas Gregor8ca72082011-10-18 21:20:17 +00004447 Builder.AddResultTypeChunk(EncodeType);
James Dennetta40f7922012-06-14 03:11:41 +00004448 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004449 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4450 Builder.AddPlaceholderChunk("type-name");
4451 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4452 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004453
4454 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004455 Builder.AddResultTypeChunk("Protocol *");
James Dennetta40f7922012-06-14 03:11:41 +00004456 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004457 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4458 Builder.AddPlaceholderChunk("protocol-name");
4459 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4460 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004461
4462 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004463 Builder.AddResultTypeChunk("SEL");
James Dennetta40f7922012-06-14 03:11:41 +00004464 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004465 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4466 Builder.AddPlaceholderChunk("selector");
4467 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4468 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004469
4470 // @"string"
4471 Builder.AddResultTypeChunk("NSString *");
4472 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
4473 Builder.AddPlaceholderChunk("string");
4474 Builder.AddTextChunk("\"");
4475 Results.AddResult(Result(Builder.TakeString()));
4476
Douglas Gregor79615892012-07-17 23:24:47 +00004477 // @[objects, ...]
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004478 Builder.AddResultTypeChunk("NSArray *");
James Dennetta40f7922012-06-14 03:11:41 +00004479 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004480 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004481 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4482 Results.AddResult(Result(Builder.TakeString()));
4483
Douglas Gregor79615892012-07-17 23:24:47 +00004484 // @{key : object, ...}
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004485 Builder.AddResultTypeChunk("NSDictionary *");
James Dennetta40f7922012-06-14 03:11:41 +00004486 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004487 Builder.AddPlaceholderChunk("key");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004488 Builder.AddChunk(CodeCompletionString::CK_Colon);
4489 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4490 Builder.AddPlaceholderChunk("object, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004491 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4492 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004493
Douglas Gregor79615892012-07-17 23:24:47 +00004494 // @(expression)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004495 Builder.AddResultTypeChunk("id");
4496 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004497 Builder.AddPlaceholderChunk("expression");
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004498 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4499 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004500}
4501
Douglas Gregorbca403c2010-01-13 23:51:12 +00004502static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004503 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004504 CodeCompletionBuilder Builder(Results.getAllocator(),
4505 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004506
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004507 if (Results.includeCodePatterns()) {
4508 // @try { statements } @catch ( declaration ) { statements } @finally
4509 // { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004510 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004511 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4512 Builder.AddPlaceholderChunk("statements");
4513 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4514 Builder.AddTextChunk("@catch");
4515 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4516 Builder.AddPlaceholderChunk("parameter");
4517 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4518 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4519 Builder.AddPlaceholderChunk("statements");
4520 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4521 Builder.AddTextChunk("@finally");
4522 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4523 Builder.AddPlaceholderChunk("statements");
4524 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4525 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004526 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004527
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004528 // @throw
James Dennetta40f7922012-06-14 03:11:41 +00004529 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004530 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4531 Builder.AddPlaceholderChunk("expression");
4532 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004533
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004534 if (Results.includeCodePatterns()) {
4535 // @synchronized ( expression ) { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004536 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004537 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4538 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4539 Builder.AddPlaceholderChunk("expression");
4540 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4541 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4542 Builder.AddPlaceholderChunk("statements");
4543 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4544 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004545 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004546}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004547
Douglas Gregorbca403c2010-01-13 23:51:12 +00004548static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004549 ResultBuilder &Results,
4550 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004551 typedef CodeCompletionResult Result;
James Dennetta40f7922012-06-14 03:11:41 +00004552 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
4553 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
4554 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004555 if (LangOpts.ObjC2)
James Dennetta40f7922012-06-14 03:11:41 +00004556 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004557}
4558
4559void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004560 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004561 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004562 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004563 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004564 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004565 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004566 HandleCodeCompleteResults(this, CodeCompleter,
4567 CodeCompletionContext::CCC_Other,
4568 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004569}
4570
4571void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004572 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004573 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004574 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004575 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004576 AddObjCStatementResults(Results, false);
4577 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004578 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004579 HandleCodeCompleteResults(this, CodeCompleter,
4580 CodeCompletionContext::CCC_Other,
4581 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004582}
4583
4584void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004585 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004586 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004587 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004588 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004589 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004590 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004591 HandleCodeCompleteResults(this, CodeCompleter,
4592 CodeCompletionContext::CCC_Other,
4593 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004594}
4595
Douglas Gregor988358f2009-11-19 00:14:45 +00004596/// \brief Determine whether the addition of the given flag to an Objective-C
4597/// property's attributes will cause a conflict.
4598static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4599 // Check if we've already added this flag.
4600 if (Attributes & NewFlag)
4601 return true;
4602
4603 Attributes |= NewFlag;
4604
4605 // Check for collisions with "readonly".
4606 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
Jordan Rosed7403a72012-08-20 20:01:13 +00004607 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregor988358f2009-11-19 00:14:45 +00004608 return true;
4609
Jordan Rosed7403a72012-08-20 20:01:13 +00004610 // Check for more than one of { assign, copy, retain, strong, weak }.
Douglas Gregor988358f2009-11-19 00:14:45 +00004611 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004612 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004613 ObjCDeclSpec::DQ_PR_copy |
Jordan Rosed7403a72012-08-20 20:01:13 +00004614 ObjCDeclSpec::DQ_PR_retain |
4615 ObjCDeclSpec::DQ_PR_strong |
4616 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregor988358f2009-11-19 00:14:45 +00004617 if (AssignCopyRetMask &&
4618 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004619 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004620 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004621 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rosed7403a72012-08-20 20:01:13 +00004622 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
4623 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregor988358f2009-11-19 00:14:45 +00004624 return true;
4625
4626 return false;
4627}
4628
Douglas Gregora93b1082009-11-18 23:08:07 +00004629void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004630 if (!CodeCompleter)
4631 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004632
Steve Naroffece8e712009-10-08 21:55:05 +00004633 unsigned Attributes = ODS.getPropertyAttributes();
4634
John McCall0a2c5e22010-08-25 06:19:51 +00004635 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004636 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004637 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004638 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004639 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004640 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004641 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004642 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004643 Results.AddResult(CodeCompletionResult("assign"));
John McCallf85e1932011-06-15 23:02:42 +00004644 if (!ObjCPropertyFlagConflicts(Attributes,
4645 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4646 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004647 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004648 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004649 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004650 Results.AddResult(CodeCompletionResult("retain"));
John McCallf85e1932011-06-15 23:02:42 +00004651 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4652 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004653 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004654 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004655 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004656 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004657 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4658 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rosed7403a72012-08-20 20:01:13 +00004659
4660 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall0a7dd782012-08-21 02:47:43 +00004661 if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Jordan Rosed7403a72012-08-20 20:01:13 +00004662 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
4663 Results.AddResult(CodeCompletionResult("weak"));
4664
Douglas Gregor988358f2009-11-19 00:14:45 +00004665 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004666 CodeCompletionBuilder Setter(Results.getAllocator(),
4667 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004668 Setter.AddTypedTextChunk("setter");
4669 Setter.AddTextChunk(" = ");
4670 Setter.AddPlaceholderChunk("method");
4671 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004672 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004673 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004674 CodeCompletionBuilder Getter(Results.getAllocator(),
4675 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004676 Getter.AddTypedTextChunk("getter");
4677 Getter.AddTextChunk(" = ");
4678 Getter.AddPlaceholderChunk("method");
4679 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004680 }
Steve Naroffece8e712009-10-08 21:55:05 +00004681 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004682 HandleCodeCompleteResults(this, CodeCompleter,
4683 CodeCompletionContext::CCC_Other,
4684 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004685}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004686
James Dennettde23c7e2012-06-17 05:33:25 +00004687/// \brief Describes the kind of Objective-C method that we want to find
Douglas Gregor4ad96852009-11-19 07:41:15 +00004688/// via code completion.
4689enum ObjCMethodKind {
Dmitri Gribenko49fdccb2012-06-08 23:13:42 +00004690 MK_Any, ///< Any kind of method, provided it means other specified criteria.
4691 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
4692 MK_OneArgSelector ///< One-argument selector.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004693};
4694
Douglas Gregor458433d2010-08-26 15:07:07 +00004695static bool isAcceptableObjCSelector(Selector Sel,
4696 ObjCMethodKind WantKind,
4697 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004698 unsigned NumSelIdents,
4699 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004700 if (NumSelIdents > Sel.getNumArgs())
4701 return false;
4702
4703 switch (WantKind) {
4704 case MK_Any: break;
4705 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4706 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4707 }
4708
Douglas Gregorcf544262010-11-17 21:36:08 +00004709 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4710 return false;
4711
Douglas Gregor458433d2010-08-26 15:07:07 +00004712 for (unsigned I = 0; I != NumSelIdents; ++I)
4713 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4714 return false;
4715
4716 return true;
4717}
4718
Douglas Gregor4ad96852009-11-19 07:41:15 +00004719static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4720 ObjCMethodKind WantKind,
4721 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004722 unsigned NumSelIdents,
4723 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004724 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004725 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004726}
Douglas Gregord36adf52010-09-16 16:06:31 +00004727
4728namespace {
4729 /// \brief A set of selectors, which is used to avoid introducing multiple
4730 /// completions with the same selector into the result set.
4731 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4732}
4733
Douglas Gregor36ecb042009-11-17 23:22:23 +00004734/// \brief Add all of the Objective-C methods in the given Objective-C
4735/// container to the set of results.
4736///
4737/// The container will be a class, protocol, category, or implementation of
4738/// any of the above. This mether will recurse to include methods from
4739/// the superclasses of classes along with their categories, protocols, and
4740/// implementations.
4741///
4742/// \param Container the container in which we'll look to find methods.
4743///
James Dennetta40f7922012-06-14 03:11:41 +00004744/// \param WantInstanceMethods Whether to add instance methods (only); if
4745/// false, this routine will add factory methods (only).
Douglas Gregor36ecb042009-11-17 23:22:23 +00004746///
4747/// \param CurContext the context in which we're performing the lookup that
4748/// finds methods.
4749///
Douglas Gregorcf544262010-11-17 21:36:08 +00004750/// \param AllowSameLength Whether we allow a method to be added to the list
4751/// when it has the same number of parameters as we have selector identifiers.
4752///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004753/// \param Results the structure into which we'll add results.
4754static void AddObjCMethods(ObjCContainerDecl *Container,
4755 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004756 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004757 IdentifierInfo **SelIdents,
4758 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004759 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004760 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004761 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004762 ResultBuilder &Results,
4763 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004764 typedef CodeCompletionResult Result;
Douglas Gregorb92a4082012-06-12 13:44:08 +00004765 Container = getContainerDef(Container);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004766 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4767 MEnd = Container->meth_end();
4768 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00004769 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004770 // Check whether the selector identifiers we've been given are a
4771 // subset of the identifiers for this particular method.
David Blaikie581deb32012-06-06 20:45:41 +00004772 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004773 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004774 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004775
David Blaikie262bc182012-04-30 02:36:29 +00004776 if (!Selectors.insert(M->getSelector()))
Douglas Gregord36adf52010-09-16 16:06:31 +00004777 continue;
4778
David Blaikie581deb32012-06-06 20:45:41 +00004779 Result R = Result(*M, 0);
Douglas Gregord3c68542009-11-19 01:08:35 +00004780 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004781 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004782 if (!InOriginalClass)
4783 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004784 Results.MaybeAddResult(R, CurContext);
4785 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004786 }
4787
Douglas Gregore396c7b2010-09-16 15:34:59 +00004788 // Visit the protocols of protocols.
4789 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004790 if (Protocol->hasDefinition()) {
4791 const ObjCList<ObjCProtocolDecl> &Protocols
4792 = Protocol->getReferencedProtocols();
4793 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4794 E = Protocols.end();
4795 I != E; ++I)
4796 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4797 NumSelIdents, CurContext, Selectors, AllowSameLength,
4798 Results, false);
4799 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004800 }
4801
Douglas Gregor36ecb042009-11-17 23:22:23 +00004802 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004803 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004804 return;
4805
4806 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004807 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4808 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004809 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004810 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004811 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004812
4813 // Add methods in categories.
4814 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4815 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004816 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004817 NumSelIdents, CurContext, Selectors, AllowSameLength,
4818 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004819
4820 // Add a categories protocol methods.
4821 const ObjCList<ObjCProtocolDecl> &Protocols
4822 = CatDecl->getReferencedProtocols();
4823 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4824 E = Protocols.end();
4825 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004826 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004827 NumSelIdents, CurContext, Selectors, AllowSameLength,
4828 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004829
4830 // Add methods in category implementations.
4831 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004832 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004833 NumSelIdents, CurContext, Selectors, AllowSameLength,
4834 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004835 }
4836
4837 // Add methods in superclass.
4838 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004839 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004840 SelIdents, NumSelIdents, CurContext, Selectors,
4841 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004842
4843 // Add methods in our implementation, if any.
4844 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004845 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004846 NumSelIdents, CurContext, Selectors, AllowSameLength,
4847 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004848}
4849
4850
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004851void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004852 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004853
4854 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004855 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004856 if (!Class) {
4857 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004858 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004859 Class = Category->getClassInterface();
4860
4861 if (!Class)
4862 return;
4863 }
4864
4865 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004866 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004867 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004868 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004869 Results.EnterNewScope();
4870
Douglas Gregord36adf52010-09-16 16:06:31 +00004871 VisitedSelectorSet Selectors;
4872 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004873 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004874 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004875 HandleCodeCompleteResults(this, CodeCompleter,
4876 CodeCompletionContext::CCC_Other,
4877 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004878}
4879
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004880void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004881 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004882
4883 // Try to find the interface where setters might live.
4884 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004885 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004886 if (!Class) {
4887 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004888 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004889 Class = Category->getClassInterface();
4890
4891 if (!Class)
4892 return;
4893 }
4894
4895 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004896 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004897 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004898 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004899 Results.EnterNewScope();
4900
Douglas Gregord36adf52010-09-16 16:06:31 +00004901 VisitedSelectorSet Selectors;
4902 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004903 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004904
4905 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004906 HandleCodeCompleteResults(this, CodeCompleter,
4907 CodeCompletionContext::CCC_Other,
4908 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004909}
4910
Douglas Gregorafc45782011-02-15 22:19:42 +00004911void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4912 bool IsParameter) {
John McCall0a2c5e22010-08-25 06:19:51 +00004913 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004914 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004915 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004916 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004917 Results.EnterNewScope();
4918
4919 // Add context-sensitive, Objective-C parameter-passing keywords.
4920 bool AddedInOut = false;
4921 if ((DS.getObjCDeclQualifier() &
4922 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4923 Results.AddResult("in");
4924 Results.AddResult("inout");
4925 AddedInOut = true;
4926 }
4927 if ((DS.getObjCDeclQualifier() &
4928 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4929 Results.AddResult("out");
4930 if (!AddedInOut)
4931 Results.AddResult("inout");
4932 }
4933 if ((DS.getObjCDeclQualifier() &
4934 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4935 ObjCDeclSpec::DQ_Oneway)) == 0) {
4936 Results.AddResult("bycopy");
4937 Results.AddResult("byref");
4938 Results.AddResult("oneway");
4939 }
4940
Douglas Gregorafc45782011-02-15 22:19:42 +00004941 // If we're completing the return type of an Objective-C method and the
4942 // identifier IBAction refers to a macro, provide a completion item for
4943 // an action, e.g.,
4944 // IBAction)<#selector#>:(id)sender
4945 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4946 Context.Idents.get("IBAction").hasMacroDefinition()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004947 CodeCompletionBuilder Builder(Results.getAllocator(),
4948 Results.getCodeCompletionTUInfo(),
4949 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorafc45782011-02-15 22:19:42 +00004950 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004951 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004952 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004953 Builder.AddChunk(CodeCompletionString::CK_Colon);
4954 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004955 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004956 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004957 Builder.AddTextChunk("sender");
4958 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4959 }
4960
Douglas Gregord32b0222010-08-24 01:06:58 +00004961 // Add various builtin type names and specifiers.
4962 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4963 Results.ExitScope();
4964
4965 // Add the various type names
4966 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4967 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4968 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4969 CodeCompleter->includeGlobals());
4970
4971 if (CodeCompleter->includeMacros())
4972 AddMacroResults(PP, Results);
4973
4974 HandleCodeCompleteResults(this, CodeCompleter,
4975 CodeCompletionContext::CCC_Type,
4976 Results.data(), Results.size());
4977}
4978
Douglas Gregor22f56992010-04-06 19:22:33 +00004979/// \brief When we have an expression with type "id", we may assume
4980/// that it has some more-specific class type based on knowledge of
4981/// common uses of Objective-C. This routine returns that class type,
4982/// or NULL if no better result could be determined.
4983static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004984 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004985 if (!Msg)
4986 return 0;
4987
4988 Selector Sel = Msg->getSelector();
4989 if (Sel.isNull())
4990 return 0;
4991
4992 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4993 if (!Id)
4994 return 0;
4995
4996 ObjCMethodDecl *Method = Msg->getMethodDecl();
4997 if (!Method)
4998 return 0;
4999
5000 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00005001 ObjCInterfaceDecl *IFace = 0;
5002 switch (Msg->getReceiverKind()) {
5003 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00005004 if (const ObjCObjectType *ObjType
5005 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5006 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00005007 break;
5008
5009 case ObjCMessageExpr::Instance: {
5010 QualType T = Msg->getInstanceReceiver()->getType();
5011 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5012 IFace = Ptr->getInterfaceDecl();
5013 break;
5014 }
5015
5016 case ObjCMessageExpr::SuperInstance:
5017 case ObjCMessageExpr::SuperClass:
5018 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00005019 }
5020
5021 if (!IFace)
5022 return 0;
5023
5024 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5025 if (Method->isInstanceMethod())
5026 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5027 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00005028 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00005029 .Case("autorelease", IFace)
5030 .Case("copy", IFace)
5031 .Case("copyWithZone", IFace)
5032 .Case("mutableCopy", IFace)
5033 .Case("mutableCopyWithZone", IFace)
5034 .Case("awakeFromCoder", IFace)
5035 .Case("replacementObjectFromCoder", IFace)
5036 .Case("class", IFace)
5037 .Case("classForCoder", IFace)
5038 .Case("superclass", Super)
5039 .Default(0);
5040
5041 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5042 .Case("new", IFace)
5043 .Case("alloc", IFace)
5044 .Case("allocWithZone", IFace)
5045 .Case("class", IFace)
5046 .Case("superclass", Super)
5047 .Default(0);
5048}
5049
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005050// Add a special completion for a message send to "super", which fills in the
5051// most likely case of forwarding all of our arguments to the superclass
5052// function.
5053///
5054/// \param S The semantic analysis object.
5055///
Dmitri Gribenko70517ca2012-08-23 17:58:28 +00005056/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005057/// the "super" keyword. Otherwise, we just need to provide the arguments.
5058///
5059/// \param SelIdents The identifiers in the selector that have already been
5060/// provided as arguments for a send to "super".
5061///
5062/// \param NumSelIdents The number of identifiers in \p SelIdents.
5063///
5064/// \param Results The set of results to augment.
5065///
5066/// \returns the Objective-C method declaration that would be invoked by
5067/// this "super" completion. If NULL, no completion was added.
5068static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
5069 IdentifierInfo **SelIdents,
5070 unsigned NumSelIdents,
5071 ResultBuilder &Results) {
5072 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5073 if (!CurMethod)
5074 return 0;
5075
5076 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5077 if (!Class)
5078 return 0;
5079
5080 // Try to find a superclass method with the same selector.
5081 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00005082 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5083 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005084 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5085 CurMethod->isInstanceMethod());
5086
Douglas Gregor78bcd912011-02-16 00:51:18 +00005087 // Check in categories or class extensions.
5088 if (!SuperMethod) {
5089 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5090 Category = Category->getNextClassCategory())
5091 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
5092 CurMethod->isInstanceMethod())))
5093 break;
5094 }
5095 }
5096
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005097 if (!SuperMethod)
5098 return 0;
5099
5100 // Check whether the superclass method has the same signature.
5101 if (CurMethod->param_size() != SuperMethod->param_size() ||
5102 CurMethod->isVariadic() != SuperMethod->isVariadic())
5103 return 0;
5104
5105 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5106 CurPEnd = CurMethod->param_end(),
5107 SuperP = SuperMethod->param_begin();
5108 CurP != CurPEnd; ++CurP, ++SuperP) {
5109 // Make sure the parameter types are compatible.
5110 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5111 (*SuperP)->getType()))
5112 return 0;
5113
5114 // Make sure we have a parameter name to forward!
5115 if (!(*CurP)->getIdentifier())
5116 return 0;
5117 }
5118
5119 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005120 CodeCompletionBuilder Builder(Results.getAllocator(),
5121 Results.getCodeCompletionTUInfo());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005122
5123 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005124 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5125 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005126
5127 // If we need the "super" keyword, add it (plus some spacing).
5128 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005129 Builder.AddTypedTextChunk("super");
5130 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005131 }
5132
5133 Selector Sel = CurMethod->getSelector();
5134 if (Sel.isUnarySelector()) {
5135 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005136 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005137 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005138 else
Douglas Gregordae68752011-02-01 22:57:45 +00005139 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005140 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005141 } else {
5142 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5143 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5144 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005145 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005146
5147 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005148 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005149 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005150 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005151 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005152 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005153 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005154 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005155 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005156 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005157 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005158 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005159 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005160 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005161 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005162 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005163 }
5164 }
5165 }
5166
Douglas Gregorba103062012-03-27 23:34:16 +00005167 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5168 CCP_SuperCompletion));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005169 return SuperMethod;
5170}
5171
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005172void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005173 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005174 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005175 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005176 CodeCompletionContext::CCC_ObjCMessageReceiver,
David Blaikie4e4d0842012-03-11 07:00:24 +00005177 getLangOpts().CPlusPlus0x
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005178 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5179 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005180
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005181 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5182 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005183 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5184 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005185
5186 // If we are in an Objective-C method inside a class that has a superclass,
5187 // add "super" as an option.
5188 if (ObjCMethodDecl *Method = getCurMethodDecl())
5189 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005190 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005191 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005192
5193 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5194 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005195
David Blaikie4e4d0842012-03-11 07:00:24 +00005196 if (getLangOpts().CPlusPlus0x)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005197 addThisCompletion(*this, Results);
5198
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005199 Results.ExitScope();
5200
5201 if (CodeCompleter->includeMacros())
5202 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005203 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005204 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005205
5206}
5207
Douglas Gregor2725ca82010-04-21 19:57:20 +00005208void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5209 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005210 unsigned NumSelIdents,
5211 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005212 ObjCInterfaceDecl *CDecl = 0;
5213 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5214 // Figure out which interface we're in.
5215 CDecl = CurMethod->getClassInterface();
5216 if (!CDecl)
5217 return;
5218
5219 // Find the superclass of this class.
5220 CDecl = CDecl->getSuperClass();
5221 if (!CDecl)
5222 return;
5223
5224 if (CurMethod->isInstanceMethod()) {
5225 // We are inside an instance method, which means that the message
5226 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005227 // current object.
5228 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005229 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005230 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005231 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005232 }
5233
5234 // Fall through to send to the superclass in CDecl.
5235 } else {
5236 // "super" may be the name of a type or variable. Figure out which
5237 // it is.
5238 IdentifierInfo *Super = &Context.Idents.get("super");
5239 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5240 LookupOrdinaryName);
5241 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5242 // "super" names an interface. Use it.
5243 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005244 if (const ObjCObjectType *Iface
5245 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5246 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005247 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5248 // "super" names an unresolved type; we can't be more specific.
5249 } else {
5250 // Assume that "super" names some kind of value and parse that way.
5251 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005252 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005253 UnqualifiedId id;
5254 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005255 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5256 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005257 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005258 SelIdents, NumSelIdents,
5259 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005260 }
5261
5262 // Fall through
5263 }
5264
John McCallb3d87482010-08-24 05:47:05 +00005265 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005266 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005267 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005268 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005269 NumSelIdents, AtArgumentExpression,
5270 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005271}
5272
Douglas Gregorb9d77572010-09-21 00:03:25 +00005273/// \brief Given a set of code-completion results for the argument of a message
5274/// send, determine the preferred type (if any) for that argument expression.
5275static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5276 unsigned NumSelIdents) {
5277 typedef CodeCompletionResult Result;
5278 ASTContext &Context = Results.getSema().Context;
5279
5280 QualType PreferredType;
5281 unsigned BestPriority = CCP_Unlikely * 2;
5282 Result *ResultsData = Results.data();
5283 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5284 Result &R = ResultsData[I];
5285 if (R.Kind == Result::RK_Declaration &&
5286 isa<ObjCMethodDecl>(R.Declaration)) {
5287 if (R.Priority <= BestPriority) {
5288 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5289 if (NumSelIdents <= Method->param_size()) {
5290 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5291 ->getType();
5292 if (R.Priority < BestPriority || PreferredType.isNull()) {
5293 BestPriority = R.Priority;
5294 PreferredType = MyPreferredType;
5295 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5296 MyPreferredType)) {
5297 PreferredType = QualType();
5298 }
5299 }
5300 }
5301 }
5302 }
5303
5304 return PreferredType;
5305}
5306
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005307static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5308 ParsedType Receiver,
5309 IdentifierInfo **SelIdents,
5310 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005311 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005312 bool IsSuper,
5313 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005314 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005315 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005316
Douglas Gregor24a069f2009-11-17 17:59:40 +00005317 // If the given name refers to an interface type, retrieve the
5318 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005319 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005320 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005321 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005322 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5323 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005324 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005325
Douglas Gregor36ecb042009-11-17 23:22:23 +00005326 // Add all of the factory methods in this Objective-C class, its protocols,
5327 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005328 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005329
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005330 // If this is a send-to-super, try to add the special "super" send
5331 // completion.
5332 if (IsSuper) {
5333 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005334 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5335 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005336 Results.Ignore(SuperMethod);
5337 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005338
Douglas Gregor265f7492010-08-27 15:29:55 +00005339 // If we're inside an Objective-C method definition, prefer its selector to
5340 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005341 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005342 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005343
Douglas Gregord36adf52010-09-16 16:06:31 +00005344 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005345 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005346 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005347 SemaRef.CurContext, Selectors, AtArgumentExpression,
5348 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005349 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005350 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005351
Douglas Gregor719770d2010-04-06 17:30:22 +00005352 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005353 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005354 if (SemaRef.ExternalSource) {
5355 for (uint32_t I = 0,
5356 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005357 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005358 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5359 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005360 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005361
5362 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005363 }
5364 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005365
5366 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5367 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005368 M != MEnd; ++M) {
5369 for (ObjCMethodList *MethList = &M->second.second;
5370 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005371 MethList = MethList->Next) {
5372 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5373 NumSelIdents))
5374 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005375
Douglas Gregor13438f92010-04-06 16:40:00 +00005376 Result R(MethList->Method, 0);
5377 R.StartParameter = NumSelIdents;
5378 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005379 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005380 }
5381 }
5382 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005383
5384 Results.ExitScope();
5385}
Douglas Gregor13438f92010-04-06 16:40:00 +00005386
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005387void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5388 IdentifierInfo **SelIdents,
5389 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005390 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005391 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005392
5393 QualType T = this->GetTypeFromParser(Receiver);
5394
Douglas Gregor218937c2011-02-01 19:23:04 +00005395 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005396 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005397 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005398 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005399
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005400 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5401 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005402
5403 // If we're actually at the argument expression (rather than prior to the
5404 // selector), we're actually performing code completion for an expression.
5405 // Determine whether we have a single, best method. If so, we can
5406 // code-complete the expression using the corresponding parameter type as
5407 // our preferred type, improving completion results.
5408 if (AtArgumentExpression) {
5409 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005410 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005411 if (PreferredType.isNull())
5412 CodeCompleteOrdinaryName(S, PCC_Expression);
5413 else
5414 CodeCompleteExpression(S, PreferredType);
5415 return;
5416 }
5417
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005418 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005419 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005420 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005421}
5422
Richard Trieuf81e5a92011-09-09 02:00:50 +00005423void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005424 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005425 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005426 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005427 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005428 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005429
5430 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005431
Douglas Gregor36ecb042009-11-17 23:22:23 +00005432 // If necessary, apply function/array conversion to the receiver.
5433 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005434 if (RecExpr) {
5435 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5436 if (Conv.isInvalid()) // conversion failed. bail.
5437 return;
5438 RecExpr = Conv.take();
5439 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005440 QualType ReceiverType = RecExpr? RecExpr->getType()
5441 : Super? Context.getObjCObjectPointerType(
5442 Context.getObjCInterfaceType(Super))
5443 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005444
Douglas Gregorda892642010-11-08 21:12:30 +00005445 // If we're messaging an expression with type "id" or "Class", check
5446 // whether we know something special about the receiver that allows
5447 // us to assume a more-specific receiver type.
5448 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5449 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5450 if (ReceiverType->isObjCClassType())
5451 return CodeCompleteObjCClassMessage(S,
5452 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5453 SelIdents, NumSelIdents,
5454 AtArgumentExpression, Super);
5455
5456 ReceiverType = Context.getObjCObjectPointerType(
5457 Context.getObjCInterfaceType(IFace));
5458 }
5459
Douglas Gregor36ecb042009-11-17 23:22:23 +00005460 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005461 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005462 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005463 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005464 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005465
Douglas Gregor36ecb042009-11-17 23:22:23 +00005466 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005467
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005468 // If this is a send-to-super, try to add the special "super" send
5469 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005470 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005471 if (ObjCMethodDecl *SuperMethod
5472 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5473 Results))
5474 Results.Ignore(SuperMethod);
5475 }
5476
Douglas Gregor265f7492010-08-27 15:29:55 +00005477 // If we're inside an Objective-C method definition, prefer its selector to
5478 // others.
5479 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5480 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005481
Douglas Gregord36adf52010-09-16 16:06:31 +00005482 // Keep track of the selectors we've already added.
5483 VisitedSelectorSet Selectors;
5484
Douglas Gregorf74a4192009-11-18 00:06:18 +00005485 // Handle messages to Class. This really isn't a message to an instance
5486 // method, so we treat it the same way we would treat a message send to a
5487 // class method.
5488 if (ReceiverType->isObjCClassType() ||
5489 ReceiverType->isObjCQualifiedClassType()) {
5490 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5491 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005492 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005493 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005494 }
5495 }
5496 // Handle messages to a qualified ID ("id<foo>").
5497 else if (const ObjCObjectPointerType *QualID
5498 = ReceiverType->getAsObjCQualifiedIdType()) {
5499 // Search protocols for instance methods.
5500 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5501 E = QualID->qual_end();
5502 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005503 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005504 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005505 }
5506 // Handle messages to a pointer to interface type.
5507 else if (const ObjCObjectPointerType *IFacePtr
5508 = ReceiverType->getAsObjCInterfacePointerType()) {
5509 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005510 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005511 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5512 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005513
5514 // Search protocols for instance methods.
5515 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5516 E = IFacePtr->qual_end();
5517 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005518 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005519 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005520 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005521 // Handle messages to "id".
5522 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005523 // We're messaging "id", so provide all instance methods we know
5524 // about as code-completion results.
5525
5526 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005527 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005528 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005529 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5530 I != N; ++I) {
5531 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005532 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005533 continue;
5534
Sebastian Redldb9d2142010-08-02 23:18:59 +00005535 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005536 }
5537 }
5538
Sebastian Redldb9d2142010-08-02 23:18:59 +00005539 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5540 MEnd = MethodPool.end();
5541 M != MEnd; ++M) {
5542 for (ObjCMethodList *MethList = &M->second.first;
5543 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005544 MethList = MethList->Next) {
5545 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5546 NumSelIdents))
5547 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005548
5549 if (!Selectors.insert(MethList->Method->getSelector()))
5550 continue;
5551
Douglas Gregor13438f92010-04-06 16:40:00 +00005552 Result R(MethList->Method, 0);
5553 R.StartParameter = NumSelIdents;
5554 R.AllParametersAreInformative = false;
5555 Results.MaybeAddResult(R, CurContext);
5556 }
5557 }
5558 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005559 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005560
5561
5562 // If we're actually at the argument expression (rather than prior to the
5563 // selector), we're actually performing code completion for an expression.
5564 // Determine whether we have a single, best method. If so, we can
5565 // code-complete the expression using the corresponding parameter type as
5566 // our preferred type, improving completion results.
5567 if (AtArgumentExpression) {
5568 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5569 NumSelIdents);
5570 if (PreferredType.isNull())
5571 CodeCompleteOrdinaryName(S, PCC_Expression);
5572 else
5573 CodeCompleteExpression(S, PreferredType);
5574 return;
5575 }
5576
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005577 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005578 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005579 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005580}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005581
Douglas Gregorfb629412010-08-23 21:17:50 +00005582void Sema::CodeCompleteObjCForCollection(Scope *S,
5583 DeclGroupPtrTy IterationVar) {
5584 CodeCompleteExpressionData Data;
5585 Data.ObjCCollection = true;
5586
5587 if (IterationVar.getAsOpaquePtr()) {
5588 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5589 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5590 if (*I)
5591 Data.IgnoreDecls.push_back(*I);
5592 }
5593 }
5594
5595 CodeCompleteExpression(S, Data);
5596}
5597
Douglas Gregor458433d2010-08-26 15:07:07 +00005598void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5599 unsigned NumSelIdents) {
5600 // If we have an external source, load the entire class method
5601 // pool from the AST file.
5602 if (ExternalSource) {
5603 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5604 I != N; ++I) {
5605 Selector Sel = ExternalSource->GetExternalSelector(I);
5606 if (Sel.isNull() || MethodPool.count(Sel))
5607 continue;
5608
5609 ReadMethodPool(Sel);
5610 }
5611 }
5612
Douglas Gregor218937c2011-02-01 19:23:04 +00005613 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005614 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005615 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005616 Results.EnterNewScope();
5617 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5618 MEnd = MethodPool.end();
5619 M != MEnd; ++M) {
5620
5621 Selector Sel = M->first;
5622 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5623 continue;
5624
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005625 CodeCompletionBuilder Builder(Results.getAllocator(),
5626 Results.getCodeCompletionTUInfo());
Douglas Gregor458433d2010-08-26 15:07:07 +00005627 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005628 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005629 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005630 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005631 continue;
5632 }
5633
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005634 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005635 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005636 if (I == NumSelIdents) {
5637 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005638 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005639 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005640 Accumulator.clear();
5641 }
5642 }
5643
Benjamin Kramera0651c52011-07-26 16:59:25 +00005644 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005645 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005646 }
Douglas Gregordae68752011-02-01 22:57:45 +00005647 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005648 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005649 }
5650 Results.ExitScope();
5651
5652 HandleCodeCompleteResults(this, CodeCompleter,
5653 CodeCompletionContext::CCC_SelectorName,
5654 Results.data(), Results.size());
5655}
5656
Douglas Gregor55385fe2009-11-18 04:19:12 +00005657/// \brief Add all of the protocol declarations that we find in the given
5658/// (translation unit) context.
5659static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005660 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005661 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005662 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005663
5664 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5665 DEnd = Ctx->decls_end();
5666 D != DEnd; ++D) {
5667 // Record any protocols we find.
5668 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005669 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005670 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005671 }
5672}
5673
5674void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5675 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005676 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005677 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005678 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005679
Douglas Gregor70c23352010-12-09 21:44:02 +00005680 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5681 Results.EnterNewScope();
5682
5683 // Tell the result set to ignore all of the protocols we have
5684 // already seen.
5685 // FIXME: This doesn't work when caching code-completion results.
5686 for (unsigned I = 0; I != NumProtocols; ++I)
5687 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5688 Protocols[I].second))
5689 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005690
Douglas Gregor70c23352010-12-09 21:44:02 +00005691 // Add all protocols.
5692 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5693 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005694
Douglas Gregor70c23352010-12-09 21:44:02 +00005695 Results.ExitScope();
5696 }
5697
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005698 HandleCodeCompleteResults(this, CodeCompleter,
5699 CodeCompletionContext::CCC_ObjCProtocolName,
5700 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005701}
5702
5703void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005704 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005705 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005706 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005707
Douglas Gregor70c23352010-12-09 21:44:02 +00005708 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5709 Results.EnterNewScope();
5710
5711 // Add all protocols.
5712 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5713 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005714
Douglas Gregor70c23352010-12-09 21:44:02 +00005715 Results.ExitScope();
5716 }
5717
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005718 HandleCodeCompleteResults(this, CodeCompleter,
5719 CodeCompletionContext::CCC_ObjCProtocolName,
5720 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005721}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005722
5723/// \brief Add all of the Objective-C interface declarations that we find in
5724/// the given (translation unit) context.
5725static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5726 bool OnlyForwardDeclarations,
5727 bool OnlyUnimplemented,
5728 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005729 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005730
5731 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5732 DEnd = Ctx->decls_end();
5733 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005734 // Record any interfaces we find.
5735 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005736 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005737 (!OnlyUnimplemented || !Class->getImplementation()))
5738 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005739 }
5740}
5741
5742void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005743 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005744 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005745 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005746 Results.EnterNewScope();
5747
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005748 if (CodeCompleter->includeGlobals()) {
5749 // Add all classes.
5750 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5751 false, Results);
5752 }
5753
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005754 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005755
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005756 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005757 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005758 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005759}
5760
Douglas Gregorc83c6872010-04-15 22:33:43 +00005761void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5762 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005763 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005764 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005765 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005766 Results.EnterNewScope();
5767
5768 // Make sure that we ignore the class we're currently defining.
5769 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005770 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005771 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005772 Results.Ignore(CurClass);
5773
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005774 if (CodeCompleter->includeGlobals()) {
5775 // Add all classes.
5776 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5777 false, Results);
5778 }
5779
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005780 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005781
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005782 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005783 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005784 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005785}
5786
5787void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005788 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005789 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005790 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005791 Results.EnterNewScope();
5792
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005793 if (CodeCompleter->includeGlobals()) {
5794 // Add all unimplemented classes.
5795 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5796 true, Results);
5797 }
5798
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005799 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005800
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005801 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005802 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005803 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005804}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005805
5806void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005807 IdentifierInfo *ClassName,
5808 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005809 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005810
Douglas Gregor218937c2011-02-01 19:23:04 +00005811 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005812 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005813 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005814
5815 // Ignore any categories we find that have already been implemented by this
5816 // interface.
5817 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5818 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005819 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005820 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5821 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5822 Category = Category->getNextClassCategory())
5823 CategoryNames.insert(Category->getIdentifier());
5824
5825 // Add all of the categories we know about.
5826 Results.EnterNewScope();
5827 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5828 for (DeclContext::decl_iterator D = TU->decls_begin(),
5829 DEnd = TU->decls_end();
5830 D != DEnd; ++D)
5831 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5832 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005833 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005834 Results.ExitScope();
5835
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005836 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005837 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005838 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005839}
5840
5841void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005842 IdentifierInfo *ClassName,
5843 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005844 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005845
5846 // Find the corresponding interface. If we couldn't find the interface, the
5847 // program itself is ill-formed. However, we'll try to be helpful still by
5848 // providing the list of all of the categories we know about.
5849 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005850 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005851 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5852 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005853 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005854
Douglas Gregor218937c2011-02-01 19:23:04 +00005855 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005856 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005857 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005858
5859 // Add all of the categories that have have corresponding interface
5860 // declarations in this class and any of its superclasses, except for
5861 // already-implemented categories in the class itself.
5862 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5863 Results.EnterNewScope();
5864 bool IgnoreImplemented = true;
5865 while (Class) {
5866 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5867 Category = Category->getNextClassCategory())
5868 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5869 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005870 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005871
5872 Class = Class->getSuperClass();
5873 IgnoreImplemented = false;
5874 }
5875 Results.ExitScope();
5876
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005877 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005878 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005879 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005880}
Douglas Gregor322328b2009-11-18 22:32:06 +00005881
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005882void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005883 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005884 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005885 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005886 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005887
5888 // Figure out where this @synthesize lives.
5889 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005890 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005891 if (!Container ||
5892 (!isa<ObjCImplementationDecl>(Container) &&
5893 !isa<ObjCCategoryImplDecl>(Container)))
5894 return;
5895
5896 // Ignore any properties that have already been implemented.
Douglas Gregorb92a4082012-06-12 13:44:08 +00005897 Container = getContainerDef(Container);
5898 for (DeclContext::decl_iterator D = Container->decls_begin(),
Douglas Gregor322328b2009-11-18 22:32:06 +00005899 DEnd = Container->decls_end();
5900 D != DEnd; ++D)
5901 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5902 Results.Ignore(PropertyImpl->getPropertyDecl());
5903
5904 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005905 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005906 Results.EnterNewScope();
5907 if (ObjCImplementationDecl *ClassImpl
5908 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005909 AddObjCProperties(ClassImpl->getClassInterface(), false,
5910 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005911 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005912 else
5913 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005914 false, /*AllowNullaryMethods=*/false, CurContext,
5915 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005916 Results.ExitScope();
5917
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005918 HandleCodeCompleteResults(this, CodeCompleter,
5919 CodeCompletionContext::CCC_Other,
5920 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005921}
5922
5923void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005924 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005925 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005926 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005927 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005928 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005929
5930 // Figure out where this @synthesize lives.
5931 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005932 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005933 if (!Container ||
5934 (!isa<ObjCImplementationDecl>(Container) &&
5935 !isa<ObjCCategoryImplDecl>(Container)))
5936 return;
5937
5938 // Figure out which interface we're looking into.
5939 ObjCInterfaceDecl *Class = 0;
5940 if (ObjCImplementationDecl *ClassImpl
5941 = dyn_cast<ObjCImplementationDecl>(Container))
5942 Class = ClassImpl->getClassInterface();
5943 else
5944 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5945 ->getClassInterface();
5946
Douglas Gregore8426052011-04-18 14:40:46 +00005947 // Determine the type of the property we're synthesizing.
5948 QualType PropertyType = Context.getObjCIdType();
5949 if (Class) {
5950 if (ObjCPropertyDecl *Property
5951 = Class->FindPropertyDeclaration(PropertyName)) {
5952 PropertyType
5953 = Property->getType().getNonReferenceType().getUnqualifiedType();
5954
5955 // Give preference to ivars
5956 Results.setPreferredType(PropertyType);
5957 }
5958 }
5959
Douglas Gregor322328b2009-11-18 22:32:06 +00005960 // Add all of the instance variables in this class and its superclasses.
5961 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005962 bool SawSimilarlyNamedIvar = false;
5963 std::string NameWithPrefix;
5964 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005965 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005966 std::string NameWithSuffix = PropertyName->getName().str();
5967 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005968 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005969 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5970 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005971 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5972
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005973 // Determine whether we've seen an ivar with a name similar to the
5974 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005975 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005976 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005977 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005978 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005979
5980 // Reduce the priority of this result by one, to give it a slight
5981 // advantage over other results whose names don't match so closely.
5982 if (Results.size() &&
5983 Results.data()[Results.size() - 1].Kind
5984 == CodeCompletionResult::RK_Declaration &&
5985 Results.data()[Results.size() - 1].Declaration == Ivar)
5986 Results.data()[Results.size() - 1].Priority--;
5987 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005988 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005989 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005990
5991 if (!SawSimilarlyNamedIvar) {
5992 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005993 // an ivar of the appropriate type.
5994 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005995 typedef CodeCompletionResult Result;
5996 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005997 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
5998 Priority,CXAvailability_Available);
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005999
Douglas Gregor8987b232011-09-27 23:30:47 +00006000 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00006001 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006002 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006003 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
6004 Results.AddResult(Result(Builder.TakeString(), Priority,
6005 CXCursor_ObjCIvarDecl));
6006 }
6007
Douglas Gregor322328b2009-11-18 22:32:06 +00006008 Results.ExitScope();
6009
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006010 HandleCodeCompleteResults(this, CodeCompleter,
6011 CodeCompletionContext::CCC_Other,
6012 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00006013}
Douglas Gregore8f5a172010-04-07 00:21:17 +00006014
Douglas Gregor408be5a2010-08-25 01:08:01 +00006015// Mapping from selectors to the methods that implement that selector, along
6016// with the "in original class" flag.
6017typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
6018 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006019
6020/// \brief Find all of the methods that reside in the given container
6021/// (and its superclasses, protocols, etc.) that meet the given
6022/// criteria. Insert those methods into the map of known methods,
6023/// indexed by selector so they can be easily found.
6024static void FindImplementableMethods(ASTContext &Context,
6025 ObjCContainerDecl *Container,
6026 bool WantInstanceMethods,
6027 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00006028 KnownMethodsMap &KnownMethods,
6029 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006030 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006031 // Make sure we have a definition; that's what we'll walk.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006032 if (!IFace->hasDefinition())
6033 return;
Douglas Gregorb92a4082012-06-12 13:44:08 +00006034
6035 IFace = IFace->getDefinition();
6036 Container = IFace;
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006037
Douglas Gregore8f5a172010-04-07 00:21:17 +00006038 const ObjCList<ObjCProtocolDecl> &Protocols
6039 = IFace->getReferencedProtocols();
6040 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006041 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006042 I != E; ++I)
6043 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006044 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006045
Douglas Gregorea766182010-10-18 18:21:28 +00006046 // Add methods from any class extensions and categories.
6047 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
6048 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00006049 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
6050 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006051 KnownMethods, false);
6052
6053 // Visit the superclass.
6054 if (IFace->getSuperClass())
6055 FindImplementableMethods(Context, IFace->getSuperClass(),
6056 WantInstanceMethods, ReturnType,
6057 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006058 }
6059
6060 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6061 // Recurse into protocols.
6062 const ObjCList<ObjCProtocolDecl> &Protocols
6063 = Category->getReferencedProtocols();
6064 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006065 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006066 I != E; ++I)
6067 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006068 KnownMethods, InOriginalClass);
6069
6070 // If this category is the original class, jump to the interface.
6071 if (InOriginalClass && Category->getClassInterface())
6072 FindImplementableMethods(Context, Category->getClassInterface(),
6073 WantInstanceMethods, ReturnType, KnownMethods,
6074 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006075 }
6076
6077 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006078 // Make sure we have a definition; that's what we'll walk.
6079 if (!Protocol->hasDefinition())
6080 return;
6081 Protocol = Protocol->getDefinition();
6082 Container = Protocol;
6083
6084 // Recurse into protocols.
6085 const ObjCList<ObjCProtocolDecl> &Protocols
6086 = Protocol->getReferencedProtocols();
6087 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6088 E = Protocols.end();
6089 I != E; ++I)
6090 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6091 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006092 }
6093
6094 // Add methods in this container. This operation occurs last because
6095 // we want the methods from this container to override any methods
6096 // we've previously seen with the same selector.
6097 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
6098 MEnd = Container->meth_end();
6099 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00006100 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006101 if (!ReturnType.isNull() &&
David Blaikie262bc182012-04-30 02:36:29 +00006102 !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006103 continue;
6104
David Blaikie581deb32012-06-06 20:45:41 +00006105 KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006106 }
6107 }
6108}
6109
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006110/// \brief Add the parenthesized return or parameter type chunk to a code
6111/// completion string.
6112static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor90f5f472012-04-10 18:35:07 +00006113 unsigned ObjCDeclQuals,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006114 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006115 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006116 CodeCompletionBuilder &Builder) {
6117 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor90f5f472012-04-10 18:35:07 +00006118 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
6119 if (!Quals.empty())
6120 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor8987b232011-09-27 23:30:47 +00006121 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006122 Builder.getAllocator()));
6123 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6124}
6125
6126/// \brief Determine whether the given class is or inherits from a class by
6127/// the given name.
6128static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00006129 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006130 if (!Class)
6131 return false;
6132
6133 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6134 return true;
6135
6136 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6137}
6138
6139/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6140/// Key-Value Observing (KVO).
6141static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6142 bool IsInstanceMethod,
6143 QualType ReturnType,
6144 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006145 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006146 ResultBuilder &Results) {
6147 IdentifierInfo *PropName = Property->getIdentifier();
6148 if (!PropName || PropName->getLength() == 0)
6149 return;
6150
Douglas Gregor8987b232011-09-27 23:30:47 +00006151 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6152
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006153 // Builder that will create each code completion.
6154 typedef CodeCompletionResult Result;
6155 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006156 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006157
6158 // The selector table.
6159 SelectorTable &Selectors = Context.Selectors;
6160
6161 // The property name, copied into the code completion allocation region
6162 // on demand.
6163 struct KeyHolder {
6164 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006165 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006166 const char *CopiedKey;
6167
Chris Lattner5f9e2722011-07-23 10:55:15 +00006168 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006169 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6170
6171 operator const char *() {
6172 if (CopiedKey)
6173 return CopiedKey;
6174
6175 return CopiedKey = Allocator.CopyString(Key);
6176 }
6177 } Key(Allocator, PropName->getName());
6178
6179 // The uppercased name of the property name.
6180 std::string UpperKey = PropName->getName();
6181 if (!UpperKey.empty())
6182 UpperKey[0] = toupper(UpperKey[0]);
6183
6184 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6185 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6186 Property->getType());
6187 bool ReturnTypeMatchesVoid
6188 = ReturnType.isNull() || ReturnType->isVoidType();
6189
6190 // Add the normal accessor -(type)key.
6191 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006192 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006193 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6194 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006195 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6196 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006197
6198 Builder.AddTypedTextChunk(Key);
6199 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6200 CXCursor_ObjCInstanceMethodDecl));
6201 }
6202
6203 // If we have an integral or boolean property (or the user has provided
6204 // an integral or boolean return type), add the accessor -(type)isKey.
6205 if (IsInstanceMethod &&
6206 ((!ReturnType.isNull() &&
6207 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6208 (ReturnType.isNull() &&
6209 (Property->getType()->isIntegerType() ||
6210 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006211 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006212 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006213 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006214 if (ReturnType.isNull()) {
6215 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6216 Builder.AddTextChunk("BOOL");
6217 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6218 }
6219
6220 Builder.AddTypedTextChunk(
6221 Allocator.CopyString(SelectorId->getName()));
6222 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6223 CXCursor_ObjCInstanceMethodDecl));
6224 }
6225 }
6226
6227 // Add the normal mutator.
6228 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6229 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006230 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006231 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006232 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006233 if (ReturnType.isNull()) {
6234 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6235 Builder.AddTextChunk("void");
6236 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6237 }
6238
6239 Builder.AddTypedTextChunk(
6240 Allocator.CopyString(SelectorId->getName()));
6241 Builder.AddTypedTextChunk(":");
Douglas Gregor90f5f472012-04-10 18:35:07 +00006242 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6243 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006244 Builder.AddTextChunk(Key);
6245 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6246 CXCursor_ObjCInstanceMethodDecl));
6247 }
6248 }
6249
6250 // Indexed and unordered accessors
6251 unsigned IndexedGetterPriority = CCP_CodePattern;
6252 unsigned IndexedSetterPriority = CCP_CodePattern;
6253 unsigned UnorderedGetterPriority = CCP_CodePattern;
6254 unsigned UnorderedSetterPriority = CCP_CodePattern;
6255 if (const ObjCObjectPointerType *ObjCPointer
6256 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6257 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6258 // If this interface type is not provably derived from a known
6259 // collection, penalize the corresponding completions.
6260 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6261 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6262 if (!InheritsFromClassNamed(IFace, "NSArray"))
6263 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6264 }
6265
6266 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6267 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6268 if (!InheritsFromClassNamed(IFace, "NSSet"))
6269 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6270 }
6271 }
6272 } else {
6273 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6274 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6275 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6276 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6277 }
6278
6279 // Add -(NSUInteger)countOf<key>
6280 if (IsInstanceMethod &&
6281 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006282 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006283 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006284 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006285 if (ReturnType.isNull()) {
6286 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6287 Builder.AddTextChunk("NSUInteger");
6288 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6289 }
6290
6291 Builder.AddTypedTextChunk(
6292 Allocator.CopyString(SelectorId->getName()));
6293 Results.AddResult(Result(Builder.TakeString(),
6294 std::min(IndexedGetterPriority,
6295 UnorderedGetterPriority),
6296 CXCursor_ObjCInstanceMethodDecl));
6297 }
6298 }
6299
6300 // Indexed getters
6301 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6302 if (IsInstanceMethod &&
6303 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006304 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006305 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006306 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006307 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006308 if (ReturnType.isNull()) {
6309 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6310 Builder.AddTextChunk("id");
6311 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6312 }
6313
6314 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6315 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6316 Builder.AddTextChunk("NSUInteger");
6317 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6318 Builder.AddTextChunk("index");
6319 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6320 CXCursor_ObjCInstanceMethodDecl));
6321 }
6322 }
6323
6324 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6325 if (IsInstanceMethod &&
6326 (ReturnType.isNull() ||
6327 (ReturnType->isObjCObjectPointerType() &&
6328 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6329 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6330 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006331 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006332 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006333 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006334 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006335 if (ReturnType.isNull()) {
6336 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6337 Builder.AddTextChunk("NSArray *");
6338 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6339 }
6340
6341 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6342 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6343 Builder.AddTextChunk("NSIndexSet *");
6344 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6345 Builder.AddTextChunk("indexes");
6346 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6347 CXCursor_ObjCInstanceMethodDecl));
6348 }
6349 }
6350
6351 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6352 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006353 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006354 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006355 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006356 &Context.Idents.get("range")
6357 };
6358
Douglas Gregore74c25c2011-05-04 23:50:46 +00006359 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006360 if (ReturnType.isNull()) {
6361 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6362 Builder.AddTextChunk("void");
6363 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6364 }
6365
6366 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6367 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6368 Builder.AddPlaceholderChunk("object-type");
6369 Builder.AddTextChunk(" **");
6370 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6371 Builder.AddTextChunk("buffer");
6372 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6373 Builder.AddTypedTextChunk("range:");
6374 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6375 Builder.AddTextChunk("NSRange");
6376 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6377 Builder.AddTextChunk("inRange");
6378 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6379 CXCursor_ObjCInstanceMethodDecl));
6380 }
6381 }
6382
6383 // Mutable indexed accessors
6384
6385 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6386 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006387 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006388 IdentifierInfo *SelectorIds[2] = {
6389 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006390 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006391 };
6392
Douglas Gregore74c25c2011-05-04 23:50:46 +00006393 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006394 if (ReturnType.isNull()) {
6395 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6396 Builder.AddTextChunk("void");
6397 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6398 }
6399
6400 Builder.AddTypedTextChunk("insertObject:");
6401 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6402 Builder.AddPlaceholderChunk("object-type");
6403 Builder.AddTextChunk(" *");
6404 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6405 Builder.AddTextChunk("object");
6406 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6407 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6408 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6409 Builder.AddPlaceholderChunk("NSUInteger");
6410 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6411 Builder.AddTextChunk("index");
6412 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6413 CXCursor_ObjCInstanceMethodDecl));
6414 }
6415 }
6416
6417 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6418 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006419 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006420 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006421 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006422 &Context.Idents.get("atIndexes")
6423 };
6424
Douglas Gregore74c25c2011-05-04 23:50:46 +00006425 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006426 if (ReturnType.isNull()) {
6427 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6428 Builder.AddTextChunk("void");
6429 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6430 }
6431
6432 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6433 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6434 Builder.AddTextChunk("NSArray *");
6435 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6436 Builder.AddTextChunk("array");
6437 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6438 Builder.AddTypedTextChunk("atIndexes:");
6439 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6440 Builder.AddPlaceholderChunk("NSIndexSet *");
6441 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6442 Builder.AddTextChunk("indexes");
6443 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6444 CXCursor_ObjCInstanceMethodDecl));
6445 }
6446 }
6447
6448 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6449 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006450 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006451 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006452 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006453 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006454 if (ReturnType.isNull()) {
6455 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6456 Builder.AddTextChunk("void");
6457 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6458 }
6459
6460 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6461 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6462 Builder.AddTextChunk("NSUInteger");
6463 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6464 Builder.AddTextChunk("index");
6465 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6466 CXCursor_ObjCInstanceMethodDecl));
6467 }
6468 }
6469
6470 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6471 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006472 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006473 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006474 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006475 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006476 if (ReturnType.isNull()) {
6477 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6478 Builder.AddTextChunk("void");
6479 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6480 }
6481
6482 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6483 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6484 Builder.AddTextChunk("NSIndexSet *");
6485 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6486 Builder.AddTextChunk("indexes");
6487 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6488 CXCursor_ObjCInstanceMethodDecl));
6489 }
6490 }
6491
6492 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6493 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006494 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006495 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006496 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006497 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006498 &Context.Idents.get("withObject")
6499 };
6500
Douglas Gregore74c25c2011-05-04 23:50:46 +00006501 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006502 if (ReturnType.isNull()) {
6503 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6504 Builder.AddTextChunk("void");
6505 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6506 }
6507
6508 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6509 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6510 Builder.AddPlaceholderChunk("NSUInteger");
6511 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6512 Builder.AddTextChunk("index");
6513 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6514 Builder.AddTypedTextChunk("withObject:");
6515 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6516 Builder.AddTextChunk("id");
6517 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6518 Builder.AddTextChunk("object");
6519 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6520 CXCursor_ObjCInstanceMethodDecl));
6521 }
6522 }
6523
6524 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6525 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006526 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006527 = (Twine("replace") + UpperKey + "AtIndexes").str();
6528 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006529 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006530 &Context.Idents.get(SelectorName1),
6531 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006532 };
6533
Douglas Gregore74c25c2011-05-04 23:50:46 +00006534 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006535 if (ReturnType.isNull()) {
6536 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6537 Builder.AddTextChunk("void");
6538 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6539 }
6540
6541 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6542 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6543 Builder.AddPlaceholderChunk("NSIndexSet *");
6544 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6545 Builder.AddTextChunk("indexes");
6546 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6547 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6548 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6549 Builder.AddTextChunk("NSArray *");
6550 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6551 Builder.AddTextChunk("array");
6552 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6553 CXCursor_ObjCInstanceMethodDecl));
6554 }
6555 }
6556
6557 // Unordered getters
6558 // - (NSEnumerator *)enumeratorOfKey
6559 if (IsInstanceMethod &&
6560 (ReturnType.isNull() ||
6561 (ReturnType->isObjCObjectPointerType() &&
6562 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6563 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6564 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006565 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006566 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006567 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006568 if (ReturnType.isNull()) {
6569 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6570 Builder.AddTextChunk("NSEnumerator *");
6571 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6572 }
6573
6574 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6575 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6576 CXCursor_ObjCInstanceMethodDecl));
6577 }
6578 }
6579
6580 // - (type *)memberOfKey:(type *)object
6581 if (IsInstanceMethod &&
6582 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006583 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006584 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006585 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006586 if (ReturnType.isNull()) {
6587 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6588 Builder.AddPlaceholderChunk("object-type");
6589 Builder.AddTextChunk(" *");
6590 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6591 }
6592
6593 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6594 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6595 if (ReturnType.isNull()) {
6596 Builder.AddPlaceholderChunk("object-type");
6597 Builder.AddTextChunk(" *");
6598 } else {
6599 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006600 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006601 Builder.getAllocator()));
6602 }
6603 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6604 Builder.AddTextChunk("object");
6605 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6606 CXCursor_ObjCInstanceMethodDecl));
6607 }
6608 }
6609
6610 // Mutable unordered accessors
6611 // - (void)addKeyObject:(type *)object
6612 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006613 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006614 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006615 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006616 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006617 if (ReturnType.isNull()) {
6618 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6619 Builder.AddTextChunk("void");
6620 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6621 }
6622
6623 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6624 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6625 Builder.AddPlaceholderChunk("object-type");
6626 Builder.AddTextChunk(" *");
6627 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6628 Builder.AddTextChunk("object");
6629 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6630 CXCursor_ObjCInstanceMethodDecl));
6631 }
6632 }
6633
6634 // - (void)addKey:(NSSet *)objects
6635 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006636 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006637 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006638 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006639 if (ReturnType.isNull()) {
6640 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6641 Builder.AddTextChunk("void");
6642 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6643 }
6644
6645 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6646 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6647 Builder.AddTextChunk("NSSet *");
6648 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6649 Builder.AddTextChunk("objects");
6650 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6651 CXCursor_ObjCInstanceMethodDecl));
6652 }
6653 }
6654
6655 // - (void)removeKeyObject:(type *)object
6656 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006657 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006658 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006659 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006660 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006661 if (ReturnType.isNull()) {
6662 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6663 Builder.AddTextChunk("void");
6664 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6665 }
6666
6667 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6668 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6669 Builder.AddPlaceholderChunk("object-type");
6670 Builder.AddTextChunk(" *");
6671 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6672 Builder.AddTextChunk("object");
6673 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6674 CXCursor_ObjCInstanceMethodDecl));
6675 }
6676 }
6677
6678 // - (void)removeKey:(NSSet *)objects
6679 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006680 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006681 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006682 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006683 if (ReturnType.isNull()) {
6684 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6685 Builder.AddTextChunk("void");
6686 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6687 }
6688
6689 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6690 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6691 Builder.AddTextChunk("NSSet *");
6692 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6693 Builder.AddTextChunk("objects");
6694 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6695 CXCursor_ObjCInstanceMethodDecl));
6696 }
6697 }
6698
6699 // - (void)intersectKey:(NSSet *)objects
6700 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006701 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006702 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006703 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006704 if (ReturnType.isNull()) {
6705 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6706 Builder.AddTextChunk("void");
6707 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6708 }
6709
6710 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6711 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6712 Builder.AddTextChunk("NSSet *");
6713 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6714 Builder.AddTextChunk("objects");
6715 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6716 CXCursor_ObjCInstanceMethodDecl));
6717 }
6718 }
6719
6720 // Key-Value Observing
6721 // + (NSSet *)keyPathsForValuesAffectingKey
6722 if (!IsInstanceMethod &&
6723 (ReturnType.isNull() ||
6724 (ReturnType->isObjCObjectPointerType() &&
6725 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6726 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6727 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006728 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006729 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006730 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006731 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006732 if (ReturnType.isNull()) {
6733 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6734 Builder.AddTextChunk("NSSet *");
6735 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6736 }
6737
6738 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6739 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006740 CXCursor_ObjCClassMethodDecl));
6741 }
6742 }
6743
6744 // + (BOOL)automaticallyNotifiesObserversForKey
6745 if (!IsInstanceMethod &&
6746 (ReturnType.isNull() ||
6747 ReturnType->isIntegerType() ||
6748 ReturnType->isBooleanType())) {
6749 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006750 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006751 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6752 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6753 if (ReturnType.isNull()) {
6754 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6755 Builder.AddTextChunk("BOOL");
6756 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6757 }
6758
6759 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6760 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6761 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006762 }
6763 }
6764}
6765
Douglas Gregore8f5a172010-04-07 00:21:17 +00006766void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6767 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006768 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006769 // Determine the return type of the method we're declaring, if
6770 // provided.
6771 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006772 Decl *IDecl = 0;
6773 if (CurContext->isObjCContainer()) {
6774 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6775 IDecl = cast<Decl>(OCD);
6776 }
Douglas Gregorea766182010-10-18 18:21:28 +00006777 // Determine where we should start searching for methods.
6778 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006779 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006780 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006781 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6782 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006783 IsInImplementation = true;
6784 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006785 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006786 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006787 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006788 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006789 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006790 }
6791
6792 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006793 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006794 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006795 }
6796
Douglas Gregorea766182010-10-18 18:21:28 +00006797 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006798 HandleCodeCompleteResults(this, CodeCompleter,
6799 CodeCompletionContext::CCC_Other,
6800 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006801 return;
6802 }
6803
6804 // Find all of the methods that we could declare/implement here.
6805 KnownMethodsMap KnownMethods;
6806 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006807 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006808
Douglas Gregore8f5a172010-04-07 00:21:17 +00006809 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006810 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006811 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006812 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006813 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006814 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006815 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006816 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6817 MEnd = KnownMethods.end();
6818 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006819 ObjCMethodDecl *Method = M->second.first;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006820 CodeCompletionBuilder Builder(Results.getAllocator(),
6821 Results.getCodeCompletionTUInfo());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006822
6823 // If the result type was not already provided, add it to the
6824 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006825 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006826 AddObjCPassingTypeChunk(Method->getResultType(),
6827 Method->getObjCDeclQualifier(),
6828 Context, Policy,
6829 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006830
6831 Selector Sel = Method->getSelector();
6832
6833 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006834 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006835 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006836
6837 // Add parameters to the pattern.
6838 unsigned I = 0;
6839 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6840 PEnd = Method->param_end();
6841 P != PEnd; (void)++P, ++I) {
6842 // Add the part of the selector name.
6843 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006844 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006845 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006846 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6847 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006848 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006849 } else
6850 break;
6851
6852 // Add the parameter type.
Douglas Gregor90f5f472012-04-10 18:35:07 +00006853 AddObjCPassingTypeChunk((*P)->getOriginalType(),
6854 (*P)->getObjCDeclQualifier(),
6855 Context, Policy,
Douglas Gregor8987b232011-09-27 23:30:47 +00006856 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006857
6858 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006859 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006860 }
6861
6862 if (Method->isVariadic()) {
6863 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006864 Builder.AddChunk(CodeCompletionString::CK_Comma);
6865 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006866 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006867
Douglas Gregor447107d2010-05-28 00:57:46 +00006868 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006869 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006870 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6871 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6872 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006873 if (!Method->getResultType()->isVoidType()) {
6874 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006875 Builder.AddTextChunk("return");
6876 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6877 Builder.AddPlaceholderChunk("expression");
6878 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006879 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006880 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006881
Douglas Gregor218937c2011-02-01 19:23:04 +00006882 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6883 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006884 }
6885
Douglas Gregor408be5a2010-08-25 01:08:01 +00006886 unsigned Priority = CCP_CodePattern;
6887 if (!M->second.second)
6888 Priority += CCD_InBaseClass;
6889
Douglas Gregorba103062012-03-27 23:34:16 +00006890 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006891 }
6892
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006893 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6894 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006895 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006896 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006897 Containers.push_back(SearchDecl);
6898
Douglas Gregore74c25c2011-05-04 23:50:46 +00006899 VisitedSelectorSet KnownSelectors;
6900 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6901 MEnd = KnownMethods.end();
6902 M != MEnd; ++M)
6903 KnownSelectors.insert(M->first);
6904
6905
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006906 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6907 if (!IFace)
6908 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6909 IFace = Category->getClassInterface();
6910
6911 if (IFace) {
6912 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6913 Category = Category->getNextClassCategory())
6914 Containers.push_back(Category);
6915 }
6916
6917 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6918 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6919 PEnd = Containers[I]->prop_end();
6920 P != PEnd; ++P) {
David Blaikie581deb32012-06-06 20:45:41 +00006921 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006922 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006923 }
6924 }
6925 }
6926
Douglas Gregore8f5a172010-04-07 00:21:17 +00006927 Results.ExitScope();
6928
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006929 HandleCodeCompleteResults(this, CodeCompleter,
6930 CodeCompletionContext::CCC_Other,
6931 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006932}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006933
6934void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6935 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006936 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006937 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006938 IdentifierInfo **SelIdents,
6939 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006940 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006941 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006942 if (ExternalSource) {
6943 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6944 I != N; ++I) {
6945 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006946 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006947 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006948
6949 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006950 }
6951 }
6952
6953 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006954 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006955 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006956 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006957 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006958
6959 if (ReturnTy)
6960 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006961
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006962 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006963 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6964 MEnd = MethodPool.end();
6965 M != MEnd; ++M) {
6966 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6967 &M->second.second;
6968 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006969 MethList = MethList->Next) {
6970 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6971 NumSelIdents))
6972 continue;
6973
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006974 if (AtParameterName) {
6975 // Suggest parameter names we've seen before.
6976 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6977 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6978 if (Param->getIdentifier()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006979 CodeCompletionBuilder Builder(Results.getAllocator(),
6980 Results.getCodeCompletionTUInfo());
Douglas Gregordae68752011-02-01 22:57:45 +00006981 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006982 Param->getIdentifier()->getName()));
6983 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006984 }
6985 }
6986
6987 continue;
6988 }
6989
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006990 Result R(MethList->Method, 0);
6991 R.StartParameter = NumSelIdents;
6992 R.AllParametersAreInformative = false;
6993 R.DeclaringEntity = true;
6994 Results.MaybeAddResult(R, CurContext);
6995 }
6996 }
6997
6998 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006999 HandleCodeCompleteResults(this, CodeCompleter,
7000 CodeCompletionContext::CCC_Other,
7001 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007002}
Douglas Gregor87c08a52010-08-13 22:48:40 +00007003
Douglas Gregorf29c5232010-08-24 22:20:20 +00007004void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007005 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007006 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007007 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007008 Results.EnterNewScope();
7009
7010 // #if <condition>
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007011 CodeCompletionBuilder Builder(Results.getAllocator(),
7012 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007013 Builder.AddTypedTextChunk("if");
7014 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7015 Builder.AddPlaceholderChunk("condition");
7016 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007017
7018 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007019 Builder.AddTypedTextChunk("ifdef");
7020 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7021 Builder.AddPlaceholderChunk("macro");
7022 Results.AddResult(Builder.TakeString());
7023
Douglas Gregorf44e8542010-08-24 19:08:16 +00007024 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007025 Builder.AddTypedTextChunk("ifndef");
7026 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7027 Builder.AddPlaceholderChunk("macro");
7028 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007029
7030 if (InConditional) {
7031 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00007032 Builder.AddTypedTextChunk("elif");
7033 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7034 Builder.AddPlaceholderChunk("condition");
7035 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007036
7037 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00007038 Builder.AddTypedTextChunk("else");
7039 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007040
7041 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00007042 Builder.AddTypedTextChunk("endif");
7043 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007044 }
7045
7046 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007047 Builder.AddTypedTextChunk("include");
7048 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7049 Builder.AddTextChunk("\"");
7050 Builder.AddPlaceholderChunk("header");
7051 Builder.AddTextChunk("\"");
7052 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007053
7054 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007055 Builder.AddTypedTextChunk("include");
7056 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7057 Builder.AddTextChunk("<");
7058 Builder.AddPlaceholderChunk("header");
7059 Builder.AddTextChunk(">");
7060 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007061
7062 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007063 Builder.AddTypedTextChunk("define");
7064 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7065 Builder.AddPlaceholderChunk("macro");
7066 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007067
7068 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00007069 Builder.AddTypedTextChunk("define");
7070 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7071 Builder.AddPlaceholderChunk("macro");
7072 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7073 Builder.AddPlaceholderChunk("args");
7074 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7075 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007076
7077 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007078 Builder.AddTypedTextChunk("undef");
7079 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7080 Builder.AddPlaceholderChunk("macro");
7081 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007082
7083 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00007084 Builder.AddTypedTextChunk("line");
7085 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7086 Builder.AddPlaceholderChunk("number");
7087 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007088
7089 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00007090 Builder.AddTypedTextChunk("line");
7091 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7092 Builder.AddPlaceholderChunk("number");
7093 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7094 Builder.AddTextChunk("\"");
7095 Builder.AddPlaceholderChunk("filename");
7096 Builder.AddTextChunk("\"");
7097 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007098
7099 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007100 Builder.AddTypedTextChunk("error");
7101 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7102 Builder.AddPlaceholderChunk("message");
7103 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007104
7105 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00007106 Builder.AddTypedTextChunk("pragma");
7107 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7108 Builder.AddPlaceholderChunk("arguments");
7109 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007110
David Blaikie4e4d0842012-03-11 07:00:24 +00007111 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00007112 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007113 Builder.AddTypedTextChunk("import");
7114 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7115 Builder.AddTextChunk("\"");
7116 Builder.AddPlaceholderChunk("header");
7117 Builder.AddTextChunk("\"");
7118 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007119
7120 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007121 Builder.AddTypedTextChunk("import");
7122 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7123 Builder.AddTextChunk("<");
7124 Builder.AddPlaceholderChunk("header");
7125 Builder.AddTextChunk(">");
7126 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007127 }
7128
7129 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007130 Builder.AddTypedTextChunk("include_next");
7131 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7132 Builder.AddTextChunk("\"");
7133 Builder.AddPlaceholderChunk("header");
7134 Builder.AddTextChunk("\"");
7135 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007136
7137 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007138 Builder.AddTypedTextChunk("include_next");
7139 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7140 Builder.AddTextChunk("<");
7141 Builder.AddPlaceholderChunk("header");
7142 Builder.AddTextChunk(">");
7143 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007144
7145 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007146 Builder.AddTypedTextChunk("warning");
7147 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7148 Builder.AddPlaceholderChunk("message");
7149 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007150
7151 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7152 // completions for them. And __include_macros is a Clang-internal extension
7153 // that we don't want to encourage anyone to use.
7154
7155 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7156 Results.ExitScope();
7157
Douglas Gregorf44e8542010-08-24 19:08:16 +00007158 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00007159 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00007160 Results.data(), Results.size());
7161}
7162
7163void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007164 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007165 S->getFnParent()? Sema::PCC_RecoveryInFunction
7166 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007167}
7168
Douglas Gregorf29c5232010-08-24 22:20:20 +00007169void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007170 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007171 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007172 IsDefinition? CodeCompletionContext::CCC_MacroName
7173 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007174 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7175 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007176 CodeCompletionBuilder Builder(Results.getAllocator(),
7177 Results.getCodeCompletionTUInfo());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007178 Results.EnterNewScope();
7179 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7180 MEnd = PP.macro_end();
7181 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007182 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007183 M->first->getName()));
7184 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007185 }
7186 Results.ExitScope();
7187 } else if (IsDefinition) {
7188 // FIXME: Can we detect when the user just wrote an include guard above?
7189 }
7190
Douglas Gregor52779fb2010-09-23 23:01:17 +00007191 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007192 Results.data(), Results.size());
7193}
7194
Douglas Gregorf29c5232010-08-24 22:20:20 +00007195void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007196 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007197 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007198 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007199
7200 if (!CodeCompleter || CodeCompleter->includeMacros())
7201 AddMacroResults(PP, Results);
7202
7203 // defined (<macro>)
7204 Results.EnterNewScope();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007205 CodeCompletionBuilder Builder(Results.getAllocator(),
7206 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007207 Builder.AddTypedTextChunk("defined");
7208 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7209 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7210 Builder.AddPlaceholderChunk("macro");
7211 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7212 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007213 Results.ExitScope();
7214
7215 HandleCodeCompleteResults(this, CodeCompleter,
7216 CodeCompletionContext::CCC_PreprocessorExpression,
7217 Results.data(), Results.size());
7218}
7219
7220void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7221 IdentifierInfo *Macro,
7222 MacroInfo *MacroInfo,
7223 unsigned Argument) {
7224 // FIXME: In the future, we could provide "overload" results, much like we
7225 // do for function calls.
7226
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007227 // Now just ignore this. There will be another code-completion callback
7228 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007229}
7230
Douglas Gregor55817af2010-08-25 17:04:25 +00007231void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007232 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007233 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007234 0, 0);
7235}
7236
Douglas Gregordae68752011-02-01 22:57:45 +00007237void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007238 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007239 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007240 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7241 CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007242 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7243 CodeCompletionDeclConsumer Consumer(Builder,
7244 Context.getTranslationUnitDecl());
7245 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7246 Consumer);
7247 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007248
7249 if (!CodeCompleter || CodeCompleter->includeMacros())
7250 AddMacroResults(PP, Builder);
7251
7252 Results.clear();
7253 Results.insert(Results.end(),
7254 Builder.data(), Builder.data() + Builder.size());
7255}