blob: bfe9fea058d8109736ab3f7f1ae96c7acc3b09ce [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();
1062
1063 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001064 return RD->getTagKind() == TTK_Class ||
1065 RD->getTagKind() == TTK_Struct;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001066
1067 return false;
1068}
1069
1070/// \brief Determines whether the given declaration is a union.
1071bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1072 // Allow us to find class templates, too.
1073 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1074 ND = ClassTemplate->getTemplatedDecl();
1075
1076 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001077 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001078
1079 return false;
1080}
1081
1082/// \brief Determines whether the given declaration is a namespace.
1083bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1084 return isa<NamespaceDecl>(ND);
1085}
1086
1087/// \brief Determines whether the given declaration is a namespace or
1088/// namespace alias.
1089bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1090 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1091}
1092
Douglas Gregor76282942009-12-11 17:31:05 +00001093/// \brief Determines whether the given declaration is a type.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001094bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregord32b0222010-08-24 01:06:58 +00001095 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1096 ND = Using->getTargetDecl();
1097
1098 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001099}
1100
Douglas Gregor76282942009-12-11 17:31:05 +00001101/// \brief Determines which members of a class should be visible via
1102/// "." or "->". Only value declarations, nested name specifiers, and
1103/// using declarations thereof should show up.
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001104bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor76282942009-12-11 17:31:05 +00001105 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1106 ND = Using->getTargetDecl();
1107
Douglas Gregorce821962009-12-11 18:14:22 +00001108 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1109 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001110}
1111
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001112static bool isObjCReceiverType(ASTContext &C, QualType T) {
1113 T = C.getCanonicalType(T);
1114 switch (T->getTypeClass()) {
1115 case Type::ObjCObject:
1116 case Type::ObjCInterface:
1117 case Type::ObjCObjectPointer:
1118 return true;
1119
1120 case Type::Builtin:
1121 switch (cast<BuiltinType>(T)->getKind()) {
1122 case BuiltinType::ObjCId:
1123 case BuiltinType::ObjCClass:
1124 case BuiltinType::ObjCSel:
1125 return true;
1126
1127 default:
1128 break;
1129 }
1130 return false;
1131
1132 default:
1133 break;
1134 }
1135
David Blaikie4e4d0842012-03-11 07:00:24 +00001136 if (!C.getLangOpts().CPlusPlus)
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001137 return false;
1138
1139 // FIXME: We could perform more analysis here to determine whether a
1140 // particular class type has any conversions to Objective-C types. For now,
1141 // just accept all class types.
1142 return T->isDependentType() || T->isRecordType();
1143}
1144
1145bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1146 QualType T = getDeclUsageType(SemaRef.Context, ND);
1147 if (T.isNull())
1148 return false;
1149
1150 T = SemaRef.Context.getBaseElementType(T);
1151 return isObjCReceiverType(SemaRef.Context, T);
1152}
1153
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001154bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const {
1155 if (IsObjCMessageReceiver(ND))
1156 return true;
1157
1158 VarDecl *Var = dyn_cast<VarDecl>(ND);
1159 if (!Var)
1160 return false;
1161
1162 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1163}
1164
Douglas Gregorfb629412010-08-23 21:17:50 +00001165bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
David Blaikie4e4d0842012-03-11 07:00:24 +00001166 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1167 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregorfb629412010-08-23 21:17:50 +00001168 return false;
1169
1170 QualType T = getDeclUsageType(SemaRef.Context, ND);
1171 if (T.isNull())
1172 return false;
1173
1174 T = SemaRef.Context.getBaseElementType(T);
1175 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1176 T->isObjCIdType() ||
David Blaikie4e4d0842012-03-11 07:00:24 +00001177 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregorfb629412010-08-23 21:17:50 +00001178}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001179
Douglas Gregor52779fb2010-09-23 23:01:17 +00001180bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1181 return false;
1182}
1183
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001184/// \rief Determines whether the given declaration is an Objective-C
1185/// instance variable.
1186bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1187 return isa<ObjCIvarDecl>(ND);
1188}
1189
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001190namespace {
1191 /// \brief Visible declaration consumer that adds a code-completion result
1192 /// for each visible declaration.
1193 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1194 ResultBuilder &Results;
1195 DeclContext *CurContext;
1196
1197 public:
1198 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1199 : Results(Results), CurContext(CurContext) { }
1200
Erik Verbruggend1205962011-10-06 07:27:49 +00001201 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1202 bool InBaseClass) {
1203 bool Accessible = true;
Douglas Gregor17015ef2011-11-03 16:51:37 +00001204 if (Ctx)
1205 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1206
Erik Verbruggend1205962011-10-06 07:27:49 +00001207 ResultBuilder::Result Result(ND, 0, false, Accessible);
1208 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001209 }
1210 };
1211}
1212
Douglas Gregor86d9a522009-09-21 16:56:56 +00001213/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001214static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001215 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001216 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001217 Results.AddResult(Result("short", CCP_Type));
1218 Results.AddResult(Result("long", CCP_Type));
1219 Results.AddResult(Result("signed", CCP_Type));
1220 Results.AddResult(Result("unsigned", CCP_Type));
1221 Results.AddResult(Result("void", CCP_Type));
1222 Results.AddResult(Result("char", CCP_Type));
1223 Results.AddResult(Result("int", CCP_Type));
1224 Results.AddResult(Result("float", CCP_Type));
1225 Results.AddResult(Result("double", CCP_Type));
1226 Results.AddResult(Result("enum", CCP_Type));
1227 Results.AddResult(Result("struct", CCP_Type));
1228 Results.AddResult(Result("union", CCP_Type));
1229 Results.AddResult(Result("const", CCP_Type));
1230 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001231
Douglas Gregor86d9a522009-09-21 16:56:56 +00001232 if (LangOpts.C99) {
1233 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001234 Results.AddResult(Result("_Complex", CCP_Type));
1235 Results.AddResult(Result("_Imaginary", CCP_Type));
1236 Results.AddResult(Result("_Bool", CCP_Type));
1237 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001238 }
1239
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001240 CodeCompletionBuilder Builder(Results.getAllocator(),
1241 Results.getCodeCompletionTUInfo());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001242 if (LangOpts.CPlusPlus) {
1243 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001244 Results.AddResult(Result("bool", CCP_Type +
1245 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001246 Results.AddResult(Result("class", CCP_Type));
1247 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001248
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001249 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001250 Builder.AddTypedTextChunk("typename");
1251 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1252 Builder.AddPlaceholderChunk("qualifier");
1253 Builder.AddTextChunk("::");
1254 Builder.AddPlaceholderChunk("name");
1255 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001256
Douglas Gregor86d9a522009-09-21 16:56:56 +00001257 if (LangOpts.CPlusPlus0x) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001258 Results.AddResult(Result("auto", CCP_Type));
1259 Results.AddResult(Result("char16_t", CCP_Type));
1260 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001261
Douglas Gregor218937c2011-02-01 19:23:04 +00001262 Builder.AddTypedTextChunk("decltype");
1263 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1264 Builder.AddPlaceholderChunk("expression");
1265 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1266 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001267 }
1268 }
1269
1270 // GNU extensions
1271 if (LangOpts.GNUMode) {
1272 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001273 // Results.AddResult(Result("_Decimal32"));
1274 // Results.AddResult(Result("_Decimal64"));
1275 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001276
Douglas Gregor218937c2011-02-01 19:23:04 +00001277 Builder.AddTypedTextChunk("typeof");
1278 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1279 Builder.AddPlaceholderChunk("expression");
1280 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001281
Douglas Gregor218937c2011-02-01 19:23:04 +00001282 Builder.AddTypedTextChunk("typeof");
1283 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1284 Builder.AddPlaceholderChunk("type");
1285 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1286 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001287 }
1288}
1289
John McCallf312b1e2010-08-26 23:41:50 +00001290static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001291 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001292 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001293 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001294 // Note: we don't suggest either "auto" or "register", because both
1295 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1296 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001297 Results.AddResult(Result("extern"));
1298 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001299}
1300
John McCallf312b1e2010-08-26 23:41:50 +00001301static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001302 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001303 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001304 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001305 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001306 case Sema::PCC_Class:
1307 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001308 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001309 Results.AddResult(Result("explicit"));
1310 Results.AddResult(Result("friend"));
1311 Results.AddResult(Result("mutable"));
1312 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001313 }
1314 // Fall through
1315
John McCallf312b1e2010-08-26 23:41:50 +00001316 case Sema::PCC_ObjCInterface:
1317 case Sema::PCC_ObjCImplementation:
1318 case Sema::PCC_Namespace:
1319 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001320 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001321 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001322 break;
1323
John McCallf312b1e2010-08-26 23:41:50 +00001324 case Sema::PCC_ObjCInstanceVariableList:
1325 case Sema::PCC_Expression:
1326 case Sema::PCC_Statement:
1327 case Sema::PCC_ForInit:
1328 case Sema::PCC_Condition:
1329 case Sema::PCC_RecoveryInFunction:
1330 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001331 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001332 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001333 break;
1334 }
1335}
1336
Douglas Gregorbca403c2010-01-13 23:51:12 +00001337static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1338static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1339static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001340 ResultBuilder &Results,
1341 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001342static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001343 ResultBuilder &Results,
1344 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001345static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001346 ResultBuilder &Results,
1347 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001348static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001349
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001350static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001351 CodeCompletionBuilder Builder(Results.getAllocator(),
1352 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00001353 Builder.AddTypedTextChunk("typedef");
1354 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1355 Builder.AddPlaceholderChunk("type");
1356 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1357 Builder.AddPlaceholderChunk("name");
1358 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001359}
1360
John McCallf312b1e2010-08-26 23:41:50 +00001361static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001362 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001363 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001364 case Sema::PCC_Namespace:
1365 case Sema::PCC_Class:
1366 case Sema::PCC_ObjCInstanceVariableList:
1367 case Sema::PCC_Template:
1368 case Sema::PCC_MemberTemplate:
1369 case Sema::PCC_Statement:
1370 case Sema::PCC_RecoveryInFunction:
1371 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001372 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001373 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001374 return true;
1375
John McCallf312b1e2010-08-26 23:41:50 +00001376 case Sema::PCC_Expression:
1377 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001378 return LangOpts.CPlusPlus;
1379
1380 case Sema::PCC_ObjCInterface:
1381 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001382 return false;
1383
John McCallf312b1e2010-08-26 23:41:50 +00001384 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001385 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001386 }
David Blaikie7530c032012-01-17 06:56:22 +00001387
1388 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001389}
1390
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001391static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1392 const Preprocessor &PP) {
1393 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001394 Policy.AnonymousTagLocations = false;
1395 Policy.SuppressStrongLifetime = true;
Douglas Gregor25270b62011-11-03 00:16:13 +00001396 Policy.SuppressUnwrittenScope = true;
Douglas Gregor8ca72082011-10-18 21:20:17 +00001397 return Policy;
1398}
1399
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001400/// \brief Retrieve a printing policy suitable for code completion.
1401static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1402 return getCompletionPrintingPolicy(S.Context, S.PP);
1403}
1404
Douglas Gregor8ca72082011-10-18 21:20:17 +00001405/// \brief Retrieve the string representation of the given type as a string
1406/// that has the appropriate lifetime for code completion.
1407///
1408/// This routine provides a fast path where we provide constant strings for
1409/// common type names.
1410static const char *GetCompletionTypeString(QualType T,
1411 ASTContext &Context,
1412 const PrintingPolicy &Policy,
1413 CodeCompletionAllocator &Allocator) {
1414 if (!T.getLocalQualifiers()) {
1415 // Built-in type names are constant strings.
1416 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidis27a00972012-05-05 04:20:28 +00001417 return BT->getNameAsCString(Policy);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001418
1419 // Anonymous tag types are constant strings.
1420 if (const TagType *TagT = dyn_cast<TagType>(T))
1421 if (TagDecl *Tag = TagT->getDecl())
1422 if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
1423 switch (Tag->getTagKind()) {
1424 case TTK_Struct: return "struct <anonymous>";
1425 case TTK_Class: return "class <anonymous>";
1426 case TTK_Union: return "union <anonymous>";
1427 case TTK_Enum: return "enum <anonymous>";
1428 }
1429 }
1430 }
1431
1432 // Slow path: format the type as a string.
1433 std::string Result;
1434 T.getAsStringInternal(Result, Policy);
1435 return Allocator.CopyString(Result);
1436}
1437
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001438/// \brief Add a completion for "this", if we're in a member function.
1439static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1440 QualType ThisTy = S.getCurrentThisType();
1441 if (ThisTy.isNull())
1442 return;
1443
1444 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001445 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001446 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1447 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1448 S.Context,
1449 Policy,
1450 Allocator));
1451 Builder.AddTypedTextChunk("this");
1452 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1453}
1454
Douglas Gregor01dfea02010-01-10 23:08:15 +00001455/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001456static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001457 Scope *S,
1458 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001459 ResultBuilder &Results) {
Douglas Gregor8ca72082011-10-18 21:20:17 +00001460 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001461 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor8ca72082011-10-18 21:20:17 +00001462 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregor218937c2011-02-01 19:23:04 +00001463
John McCall0a2c5e22010-08-25 06:19:51 +00001464 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001465 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001466 case Sema::PCC_Namespace:
David Blaikie4e4d0842012-03-11 07:00:24 +00001467 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001468 if (Results.includeCodePatterns()) {
1469 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001470 Builder.AddTypedTextChunk("namespace");
1471 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1472 Builder.AddPlaceholderChunk("identifier");
1473 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1474 Builder.AddPlaceholderChunk("declarations");
1475 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1476 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1477 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001478 }
1479
Douglas Gregor01dfea02010-01-10 23:08:15 +00001480 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001481 Builder.AddTypedTextChunk("namespace");
1482 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1483 Builder.AddPlaceholderChunk("name");
1484 Builder.AddChunk(CodeCompletionString::CK_Equal);
1485 Builder.AddPlaceholderChunk("namespace");
1486 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001487
1488 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001489 Builder.AddTypedTextChunk("using");
1490 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1491 Builder.AddTextChunk("namespace");
1492 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1493 Builder.AddPlaceholderChunk("identifier");
1494 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001495
1496 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001497 Builder.AddTypedTextChunk("asm");
1498 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1499 Builder.AddPlaceholderChunk("string-literal");
1500 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1501 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001502
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001503 if (Results.includeCodePatterns()) {
1504 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001505 Builder.AddTypedTextChunk("template");
1506 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1507 Builder.AddPlaceholderChunk("declaration");
1508 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001509 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001510 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001511
David Blaikie4e4d0842012-03-11 07:00:24 +00001512 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001513 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001514
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001515 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001516 // Fall through
1517
John McCallf312b1e2010-08-26 23:41:50 +00001518 case Sema::PCC_Class:
David Blaikie4e4d0842012-03-11 07:00:24 +00001519 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001520 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001521 Builder.AddTypedTextChunk("using");
1522 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1523 Builder.AddPlaceholderChunk("qualifier");
1524 Builder.AddTextChunk("::");
1525 Builder.AddPlaceholderChunk("name");
1526 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001527
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001528 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001529 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001530 Builder.AddTypedTextChunk("using");
1531 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1532 Builder.AddTextChunk("typename");
1533 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1534 Builder.AddPlaceholderChunk("qualifier");
1535 Builder.AddTextChunk("::");
1536 Builder.AddPlaceholderChunk("name");
1537 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001538 }
1539
John McCallf312b1e2010-08-26 23:41:50 +00001540 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001541 AddTypedefResult(Results);
1542
Douglas Gregor01dfea02010-01-10 23:08:15 +00001543 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001544 Builder.AddTypedTextChunk("public");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001545 if (Results.includeCodePatterns())
1546 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001547 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001548
1549 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001550 Builder.AddTypedTextChunk("protected");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001551 if (Results.includeCodePatterns())
1552 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001553 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001554
1555 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001556 Builder.AddTypedTextChunk("private");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001557 if (Results.includeCodePatterns())
1558 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001559 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001560 }
1561 }
1562 // Fall through
1563
John McCallf312b1e2010-08-26 23:41:50 +00001564 case Sema::PCC_Template:
1565 case Sema::PCC_MemberTemplate:
David Blaikie4e4d0842012-03-11 07:00:24 +00001566 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001567 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001568 Builder.AddTypedTextChunk("template");
1569 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1570 Builder.AddPlaceholderChunk("parameters");
1571 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1572 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001573 }
1574
David Blaikie4e4d0842012-03-11 07:00:24 +00001575 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1576 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001577 break;
1578
John McCallf312b1e2010-08-26 23:41:50 +00001579 case Sema::PCC_ObjCInterface:
David Blaikie4e4d0842012-03-11 07:00:24 +00001580 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1581 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1582 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001583 break;
1584
John McCallf312b1e2010-08-26 23:41:50 +00001585 case Sema::PCC_ObjCImplementation:
David Blaikie4e4d0842012-03-11 07:00:24 +00001586 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1587 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1588 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001589 break;
1590
John McCallf312b1e2010-08-26 23:41:50 +00001591 case Sema::PCC_ObjCInstanceVariableList:
David Blaikie4e4d0842012-03-11 07:00:24 +00001592 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001593 break;
1594
John McCallf312b1e2010-08-26 23:41:50 +00001595 case Sema::PCC_RecoveryInFunction:
1596 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001597 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001598
David Blaikie4e4d0842012-03-11 07:00:24 +00001599 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1600 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001601 Builder.AddTypedTextChunk("try");
1602 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1603 Builder.AddPlaceholderChunk("statements");
1604 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1605 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1606 Builder.AddTextChunk("catch");
1607 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1608 Builder.AddPlaceholderChunk("declaration");
1609 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1610 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1611 Builder.AddPlaceholderChunk("statements");
1612 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1613 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1614 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001615 }
David Blaikie4e4d0842012-03-11 07:00:24 +00001616 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001617 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001618
Douglas Gregord8e8a582010-05-25 21:41:55 +00001619 if (Results.includeCodePatterns()) {
1620 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001621 Builder.AddTypedTextChunk("if");
1622 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001623 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001624 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001625 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001626 Builder.AddPlaceholderChunk("expression");
1627 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1628 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1629 Builder.AddPlaceholderChunk("statements");
1630 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1631 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1632 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001633
Douglas Gregord8e8a582010-05-25 21:41:55 +00001634 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001635 Builder.AddTypedTextChunk("switch");
1636 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001637 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001638 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001639 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001640 Builder.AddPlaceholderChunk("expression");
1641 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1642 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1643 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1644 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1645 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001646 }
1647
Douglas Gregor01dfea02010-01-10 23:08:15 +00001648 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001649 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001650 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001651 Builder.AddTypedTextChunk("case");
1652 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1653 Builder.AddPlaceholderChunk("expression");
1654 Builder.AddChunk(CodeCompletionString::CK_Colon);
1655 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001656
1657 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001658 Builder.AddTypedTextChunk("default");
1659 Builder.AddChunk(CodeCompletionString::CK_Colon);
1660 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001661 }
1662
Douglas Gregord8e8a582010-05-25 21:41:55 +00001663 if (Results.includeCodePatterns()) {
1664 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001665 Builder.AddTypedTextChunk("while");
1666 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001667 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001668 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001669 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001670 Builder.AddPlaceholderChunk("expression");
1671 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1672 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1673 Builder.AddPlaceholderChunk("statements");
1674 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1675 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1676 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001677
1678 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001679 Builder.AddTypedTextChunk("do");
1680 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1681 Builder.AddPlaceholderChunk("statements");
1682 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1683 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1684 Builder.AddTextChunk("while");
1685 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1686 Builder.AddPlaceholderChunk("expression");
1687 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1688 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001689
Douglas Gregord8e8a582010-05-25 21:41:55 +00001690 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001691 Builder.AddTypedTextChunk("for");
1692 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001693 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001694 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001695 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001696 Builder.AddPlaceholderChunk("init-expression");
1697 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1698 Builder.AddPlaceholderChunk("condition");
1699 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1700 Builder.AddPlaceholderChunk("inc-expression");
1701 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1702 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1703 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1704 Builder.AddPlaceholderChunk("statements");
1705 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1706 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1707 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001708 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001709
1710 if (S->getContinueParent()) {
1711 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001712 Builder.AddTypedTextChunk("continue");
1713 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001714 }
1715
1716 if (S->getBreakParent()) {
1717 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001718 Builder.AddTypedTextChunk("break");
1719 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001720 }
1721
1722 // "return expression ;" or "return ;", depending on whether we
1723 // know the function is void or not.
1724 bool isVoid = false;
1725 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1726 isVoid = Function->getResultType()->isVoidType();
1727 else if (ObjCMethodDecl *Method
1728 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1729 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001730 else if (SemaRef.getCurBlock() &&
1731 !SemaRef.getCurBlock()->ReturnType.isNull())
1732 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001733 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001734 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001735 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1736 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001737 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001738 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001739
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001740 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001741 Builder.AddTypedTextChunk("goto");
1742 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1743 Builder.AddPlaceholderChunk("label");
1744 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001745
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001746 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001747 Builder.AddTypedTextChunk("using");
1748 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1749 Builder.AddTextChunk("namespace");
1750 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1751 Builder.AddPlaceholderChunk("identifier");
1752 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001753 }
1754
1755 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001756 case Sema::PCC_ForInit:
1757 case Sema::PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00001758 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001759 // Fall through: conditions and statements can have expressions.
1760
Douglas Gregor02688102010-09-14 23:59:36 +00001761 case Sema::PCC_ParenthesizedExpression:
David Blaikie4e4d0842012-03-11 07:00:24 +00001762 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCallf85e1932011-06-15 23:02:42 +00001763 CCC == Sema::PCC_ParenthesizedExpression) {
1764 // (__bridge <type>)<expression>
1765 Builder.AddTypedTextChunk("__bridge");
1766 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1767 Builder.AddPlaceholderChunk("type");
1768 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1769 Builder.AddPlaceholderChunk("expression");
1770 Results.AddResult(Result(Builder.TakeString()));
1771
1772 // (__bridge_transfer <Objective-C type>)<expression>
1773 Builder.AddTypedTextChunk("__bridge_transfer");
1774 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1775 Builder.AddPlaceholderChunk("Objective-C type");
1776 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1777 Builder.AddPlaceholderChunk("expression");
1778 Results.AddResult(Result(Builder.TakeString()));
1779
1780 // (__bridge_retained <CF type>)<expression>
1781 Builder.AddTypedTextChunk("__bridge_retained");
1782 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1783 Builder.AddPlaceholderChunk("CF type");
1784 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1785 Builder.AddPlaceholderChunk("expression");
1786 Results.AddResult(Result(Builder.TakeString()));
1787 }
1788 // Fall through
1789
John McCallf312b1e2010-08-26 23:41:50 +00001790 case Sema::PCC_Expression: {
David Blaikie4e4d0842012-03-11 07:00:24 +00001791 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001792 // 'this', if we're in a non-static member function.
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001793 addThisCompletion(SemaRef, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001794
Douglas Gregor8ca72082011-10-18 21:20:17 +00001795 // true
1796 Builder.AddResultTypeChunk("bool");
1797 Builder.AddTypedTextChunk("true");
1798 Results.AddResult(Result(Builder.TakeString()));
1799
1800 // false
1801 Builder.AddResultTypeChunk("bool");
1802 Builder.AddTypedTextChunk("false");
1803 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001804
David Blaikie4e4d0842012-03-11 07:00:24 +00001805 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001806 // dynamic_cast < type-id > ( expression )
1807 Builder.AddTypedTextChunk("dynamic_cast");
1808 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1809 Builder.AddPlaceholderChunk("type");
1810 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1811 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1812 Builder.AddPlaceholderChunk("expression");
1813 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1814 Results.AddResult(Result(Builder.TakeString()));
1815 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001816
1817 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001818 Builder.AddTypedTextChunk("static_cast");
1819 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1820 Builder.AddPlaceholderChunk("type");
1821 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1822 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1823 Builder.AddPlaceholderChunk("expression");
1824 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1825 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001826
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001827 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001828 Builder.AddTypedTextChunk("reinterpret_cast");
1829 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1830 Builder.AddPlaceholderChunk("type");
1831 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1832 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1833 Builder.AddPlaceholderChunk("expression");
1834 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1835 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001836
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001837 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001838 Builder.AddTypedTextChunk("const_cast");
1839 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1840 Builder.AddPlaceholderChunk("type");
1841 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1842 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1843 Builder.AddPlaceholderChunk("expression");
1844 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1845 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001846
David Blaikie4e4d0842012-03-11 07:00:24 +00001847 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001848 // typeid ( expression-or-type )
Douglas Gregor8ca72082011-10-18 21:20:17 +00001849 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001850 Builder.AddTypedTextChunk("typeid");
1851 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1852 Builder.AddPlaceholderChunk("expression-or-type");
1853 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1854 Results.AddResult(Result(Builder.TakeString()));
1855 }
1856
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001857 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001858 Builder.AddTypedTextChunk("new");
1859 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1860 Builder.AddPlaceholderChunk("type");
1861 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1862 Builder.AddPlaceholderChunk("expressions");
1863 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1864 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001865
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001866 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001867 Builder.AddTypedTextChunk("new");
1868 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1869 Builder.AddPlaceholderChunk("type");
1870 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1871 Builder.AddPlaceholderChunk("size");
1872 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1873 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1874 Builder.AddPlaceholderChunk("expressions");
1875 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1876 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001877
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001878 // delete expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001879 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001880 Builder.AddTypedTextChunk("delete");
1881 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1882 Builder.AddPlaceholderChunk("expression");
1883 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001884
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001885 // delete [] expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001886 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001887 Builder.AddTypedTextChunk("delete");
1888 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1889 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1890 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1891 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1892 Builder.AddPlaceholderChunk("expression");
1893 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001894
David Blaikie4e4d0842012-03-11 07:00:24 +00001895 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001896 // throw expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001897 Builder.AddResultTypeChunk("void");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001898 Builder.AddTypedTextChunk("throw");
1899 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1900 Builder.AddPlaceholderChunk("expression");
1901 Results.AddResult(Result(Builder.TakeString()));
1902 }
Douglas Gregora50216c2011-10-18 16:29:03 +00001903
Douglas Gregor12e13132010-05-26 22:00:08 +00001904 // FIXME: Rethrow?
Douglas Gregora50216c2011-10-18 16:29:03 +00001905
David Blaikie4e4d0842012-03-11 07:00:24 +00001906 if (SemaRef.getLangOpts().CPlusPlus0x) {
Douglas Gregora50216c2011-10-18 16:29:03 +00001907 // nullptr
Douglas Gregor8ca72082011-10-18 21:20:17 +00001908 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001909 Builder.AddTypedTextChunk("nullptr");
1910 Results.AddResult(Result(Builder.TakeString()));
1911
1912 // alignof
Douglas Gregor8ca72082011-10-18 21:20:17 +00001913 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001914 Builder.AddTypedTextChunk("alignof");
1915 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1916 Builder.AddPlaceholderChunk("type");
1917 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1918 Results.AddResult(Result(Builder.TakeString()));
1919
1920 // noexcept
Douglas Gregor8ca72082011-10-18 21:20:17 +00001921 Builder.AddResultTypeChunk("bool");
Douglas Gregora50216c2011-10-18 16:29:03 +00001922 Builder.AddTypedTextChunk("noexcept");
1923 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1924 Builder.AddPlaceholderChunk("expression");
1925 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1926 Results.AddResult(Result(Builder.TakeString()));
1927
1928 // sizeof... expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001929 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001930 Builder.AddTypedTextChunk("sizeof...");
1931 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1932 Builder.AddPlaceholderChunk("parameter-pack");
1933 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1934 Results.AddResult(Result(Builder.TakeString()));
1935 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001936 }
1937
David Blaikie4e4d0842012-03-11 07:00:24 +00001938 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001939 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001940 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1941 // The interface can be NULL.
1942 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregor8ca72082011-10-18 21:20:17 +00001943 if (ID->getSuperClass()) {
1944 std::string SuperType;
1945 SuperType = ID->getSuperClass()->getNameAsString();
1946 if (Method->isInstanceMethod())
1947 SuperType += " *";
1948
1949 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1950 Builder.AddTypedTextChunk("super");
1951 Results.AddResult(Result(Builder.TakeString()));
1952 }
Ted Kremenek681e2562010-05-31 21:43:10 +00001953 }
1954
Douglas Gregorbca403c2010-01-13 23:51:12 +00001955 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001956 }
1957
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001958 // sizeof expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001959 Builder.AddResultTypeChunk("size_t");
Douglas Gregor218937c2011-02-01 19:23:04 +00001960 Builder.AddTypedTextChunk("sizeof");
1961 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1962 Builder.AddPlaceholderChunk("expression-or-type");
1963 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1964 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001965 break;
1966 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001967
John McCallf312b1e2010-08-26 23:41:50 +00001968 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001969 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00001970 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001971 }
1972
David Blaikie4e4d0842012-03-11 07:00:24 +00001973 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
1974 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001975
David Blaikie4e4d0842012-03-11 07:00:24 +00001976 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00001977 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001978}
1979
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001980/// \brief If the given declaration has an associated type, add it as a result
1981/// type chunk.
1982static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00001983 const PrintingPolicy &Policy,
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001984 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00001985 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001986 if (!ND)
1987 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00001988
1989 // Skip constructors and conversion functions, which have their return types
1990 // built into their names.
1991 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
1992 return;
1993
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001994 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00001995 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001996 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
1997 T = Function->getResultType();
1998 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
1999 T = Method->getResultType();
2000 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
2001 T = FunTmpl->getTemplatedDecl()->getResultType();
2002 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
2003 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
2004 else if (isa<UnresolvedUsingValueDecl>(ND)) {
2005 /* Do nothing: ignore unresolved using declarations*/
John McCallf85e1932011-06-15 23:02:42 +00002006 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002007 T = Value->getType();
John McCallf85e1932011-06-15 23:02:42 +00002008 } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002009 T = Property->getType();
2010
2011 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2012 return;
2013
Douglas Gregor8987b232011-09-27 23:30:47 +00002014 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002015 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002016}
2017
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002018static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00002019 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002020 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2021 if (Sentinel->getSentinel() == 0) {
David Blaikie4e4d0842012-03-11 07:00:24 +00002022 if (Context.getLangOpts().ObjC1 &&
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002023 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002024 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002025 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002026 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002027 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002028 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002029 }
2030}
2031
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002032static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2033 std::string Result;
2034 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002035 Result += "in ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002036 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002037 Result += "inout ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002038 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002039 Result += "out ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002040 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002041 Result += "bycopy ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002042 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002043 Result += "byref ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002044 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002045 Result += "oneway ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002046 return Result;
2047}
2048
Douglas Gregor83482d12010-08-24 16:15:59 +00002049static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002050 const PrintingPolicy &Policy,
Douglas Gregoraba48082010-08-29 19:47:46 +00002051 ParmVarDecl *Param,
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002052 bool SuppressName = false,
2053 bool SuppressBlock = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00002054 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2055 if (Param->getType()->isDependentType() ||
2056 !Param->getType()->isBlockPointerType()) {
2057 // The argument for a dependent or non-block parameter is a placeholder
2058 // containing that parameter's type.
2059 std::string Result;
2060
Douglas Gregoraba48082010-08-29 19:47:46 +00002061 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002062 Result = Param->getIdentifier()->getName();
2063
John McCallf85e1932011-06-15 23:02:42 +00002064 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002065
2066 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002067 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2068 + Result + ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00002069 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002070 Result += Param->getIdentifier()->getName();
2071 }
2072 return Result;
2073 }
2074
2075 // The argument for a block pointer parameter is a block literal with
2076 // the appropriate type.
Douglas Gregor830072c2011-02-15 22:37:09 +00002077 FunctionTypeLoc *Block = 0;
2078 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregor83482d12010-08-24 16:15:59 +00002079 TypeLoc TL;
2080 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2081 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2082 while (true) {
2083 // Look through typedefs.
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002084 if (!SuppressBlock) {
2085 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2086 if (TypeSourceInfo *InnerTSInfo
2087 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2088 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2089 continue;
2090 }
2091 }
2092
2093 // Look through qualified types
2094 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2095 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregor83482d12010-08-24 16:15:59 +00002096 continue;
2097 }
2098 }
2099
Douglas Gregor83482d12010-08-24 16:15:59 +00002100 // Try to get the function prototype behind the block pointer type,
2101 // then we're done.
2102 if (BlockPointerTypeLoc *BlockPtr
2103 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00002104 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor830072c2011-02-15 22:37:09 +00002105 Block = dyn_cast<FunctionTypeLoc>(&TL);
2106 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregor83482d12010-08-24 16:15:59 +00002107 }
2108 break;
2109 }
2110 }
2111
2112 if (!Block) {
2113 // We were unable to find a FunctionProtoTypeLoc with parameter names
2114 // for the block; just use the parameter type as a placeholder.
2115 std::string Result;
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002116 if (!ObjCMethodParam && Param->getIdentifier())
2117 Result = Param->getIdentifier()->getName();
2118
John McCallf85e1932011-06-15 23:02:42 +00002119 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002120
2121 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002122 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2123 + Result + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002124 if (Param->getIdentifier())
2125 Result += Param->getIdentifier()->getName();
2126 }
2127
2128 return Result;
2129 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002130
Douglas Gregor83482d12010-08-24 16:15:59 +00002131 // We have the function prototype behind the block pointer type, as it was
2132 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00002133 std::string Result;
2134 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002135 if (!ResultType->isVoidType() || SuppressBlock)
John McCallf85e1932011-06-15 23:02:42 +00002136 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002137
2138 // Format the parameter list.
2139 std::string Params;
Douglas Gregor830072c2011-02-15 22:37:09 +00002140 if (!BlockProto || Block->getNumArgs() == 0) {
2141 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002142 Params = "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00002143 else
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002144 Params = "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00002145 } else {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002146 Params += "(";
Douglas Gregor38276252010-09-08 22:47:51 +00002147 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2148 if (I)
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002149 Params += ", ";
2150 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2151 /*SuppressName=*/false,
2152 /*SuppressBlock=*/true);
Douglas Gregor38276252010-09-08 22:47:51 +00002153
Douglas Gregor830072c2011-02-15 22:37:09 +00002154 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002155 Params += ", ...";
Douglas Gregor38276252010-09-08 22:47:51 +00002156 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002157 Params += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00002158 }
Douglas Gregor38276252010-09-08 22:47:51 +00002159
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002160 if (SuppressBlock) {
2161 // Format as a parameter.
2162 Result = Result + " (^";
2163 if (Param->getIdentifier())
2164 Result += Param->getIdentifier()->getName();
2165 Result += ")";
2166 Result += Params;
2167 } else {
2168 // Format as a block literal argument.
2169 Result = '^' + Result;
2170 Result += Params;
2171
2172 if (Param->getIdentifier())
2173 Result += Param->getIdentifier()->getName();
2174 }
2175
Douglas Gregor83482d12010-08-24 16:15:59 +00002176 return Result;
2177}
2178
Douglas Gregor86d9a522009-09-21 16:56:56 +00002179/// \brief Add function parameter chunks to the given code completion string.
2180static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002181 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002182 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00002183 CodeCompletionBuilder &Result,
2184 unsigned Start = 0,
2185 bool InOptional = false) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002186 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002187
Douglas Gregor218937c2011-02-01 19:23:04 +00002188 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002189 ParmVarDecl *Param = Function->getParamDecl(P);
2190
Douglas Gregor218937c2011-02-01 19:23:04 +00002191 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002192 // When we see an optional default argument, put that argument and
2193 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002194 CodeCompletionBuilder Opt(Result.getAllocator(),
2195 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002196 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002197 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002198 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregor218937c2011-02-01 19:23:04 +00002199 Result.AddOptionalChunk(Opt.TakeString());
2200 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002201 }
2202
Douglas Gregor218937c2011-02-01 19:23:04 +00002203 if (FirstParameter)
2204 FirstParameter = false;
2205 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002206 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor218937c2011-02-01 19:23:04 +00002207
2208 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002209
2210 // Format the placeholder string.
Douglas Gregor8987b232011-09-27 23:30:47 +00002211 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2212 Param);
Douglas Gregor83482d12010-08-24 16:15:59 +00002213
Douglas Gregore17794f2010-08-31 05:13:43 +00002214 if (Function->isVariadic() && P == N - 1)
2215 PlaceholderStr += ", ...";
2216
Douglas Gregor86d9a522009-09-21 16:56:56 +00002217 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002218 Result.AddPlaceholderChunk(
2219 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002220 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002221
2222 if (const FunctionProtoType *Proto
2223 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002224 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002225 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002226 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002227
Douglas Gregor218937c2011-02-01 19:23:04 +00002228 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002229 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002230}
2231
2232/// \brief Add template parameter chunks to the given code completion string.
2233static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002234 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002235 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002236 CodeCompletionBuilder &Result,
2237 unsigned MaxParameters = 0,
2238 unsigned Start = 0,
2239 bool InDefaultArg = false) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002240 bool FirstParameter = true;
2241
2242 TemplateParameterList *Params = Template->getTemplateParameters();
2243 TemplateParameterList::iterator PEnd = Params->end();
2244 if (MaxParameters)
2245 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002246 for (TemplateParameterList::iterator P = Params->begin() + Start;
2247 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002248 bool HasDefaultArg = false;
2249 std::string PlaceholderStr;
2250 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2251 if (TTP->wasDeclaredWithTypename())
2252 PlaceholderStr = "typename";
2253 else
2254 PlaceholderStr = "class";
2255
2256 if (TTP->getIdentifier()) {
2257 PlaceholderStr += ' ';
2258 PlaceholderStr += TTP->getIdentifier()->getName();
2259 }
2260
2261 HasDefaultArg = TTP->hasDefaultArgument();
2262 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002263 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002264 if (NTTP->getIdentifier())
2265 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCallf85e1932011-06-15 23:02:42 +00002266 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002267 HasDefaultArg = NTTP->hasDefaultArgument();
2268 } else {
2269 assert(isa<TemplateTemplateParmDecl>(*P));
2270 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2271
2272 // Since putting the template argument list into the placeholder would
2273 // be very, very long, we just use an abbreviation.
2274 PlaceholderStr = "template<...> class";
2275 if (TTP->getIdentifier()) {
2276 PlaceholderStr += ' ';
2277 PlaceholderStr += TTP->getIdentifier()->getName();
2278 }
2279
2280 HasDefaultArg = TTP->hasDefaultArgument();
2281 }
2282
Douglas Gregor218937c2011-02-01 19:23:04 +00002283 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002284 // When we see an optional default argument, put that argument and
2285 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002286 CodeCompletionBuilder Opt(Result.getAllocator(),
2287 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002288 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002289 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002290 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregor218937c2011-02-01 19:23:04 +00002291 P - Params->begin(), true);
2292 Result.AddOptionalChunk(Opt.TakeString());
2293 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002294 }
2295
Douglas Gregor218937c2011-02-01 19:23:04 +00002296 InDefaultArg = false;
2297
Douglas Gregor86d9a522009-09-21 16:56:56 +00002298 if (FirstParameter)
2299 FirstParameter = false;
2300 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002301 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002302
2303 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002304 Result.AddPlaceholderChunk(
2305 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002306 }
2307}
2308
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002309/// \brief Add a qualifier to the given code-completion string, if the
2310/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002311static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002312AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002313 NestedNameSpecifier *Qualifier,
2314 bool QualifierIsInformative,
Douglas Gregor8987b232011-09-27 23:30:47 +00002315 ASTContext &Context,
2316 const PrintingPolicy &Policy) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002317 if (!Qualifier)
2318 return;
2319
2320 std::string PrintedNNS;
2321 {
2322 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor8987b232011-09-27 23:30:47 +00002323 Qualifier->print(OS, Policy);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002324 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002325 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002326 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002327 else
Douglas Gregordae68752011-02-01 22:57:45 +00002328 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002329}
2330
Douglas Gregor218937c2011-02-01 19:23:04 +00002331static void
2332AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2333 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002334 const FunctionProtoType *Proto
2335 = Function->getType()->getAs<FunctionProtoType>();
2336 if (!Proto || !Proto->getTypeQuals())
2337 return;
2338
Douglas Gregora63f6de2011-02-01 21:15:40 +00002339 // FIXME: Add ref-qualifier!
2340
2341 // Handle single qualifiers without copying
2342 if (Proto->getTypeQuals() == Qualifiers::Const) {
2343 Result.AddInformativeChunk(" const");
2344 return;
2345 }
2346
2347 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2348 Result.AddInformativeChunk(" volatile");
2349 return;
2350 }
2351
2352 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2353 Result.AddInformativeChunk(" restrict");
2354 return;
2355 }
2356
2357 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002358 std::string QualsStr;
2359 if (Proto->getTypeQuals() & Qualifiers::Const)
2360 QualsStr += " const";
2361 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2362 QualsStr += " volatile";
2363 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2364 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002365 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002366}
2367
Douglas Gregor6f942b22010-09-21 16:06:22 +00002368/// \brief Add the name of the given declaration
Douglas Gregor8987b232011-09-27 23:30:47 +00002369static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
2370 NamedDecl *ND, CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002371 DeclarationName Name = ND->getDeclName();
2372 if (!Name)
2373 return;
2374
2375 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002376 case DeclarationName::CXXOperatorName: {
2377 const char *OperatorName = 0;
2378 switch (Name.getCXXOverloadedOperator()) {
2379 case OO_None:
2380 case OO_Conditional:
2381 case NUM_OVERLOADED_OPERATORS:
2382 OperatorName = "operator";
2383 break;
2384
2385#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2386 case OO_##Name: OperatorName = "operator" Spelling; break;
2387#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2388#include "clang/Basic/OperatorKinds.def"
2389
2390 case OO_New: OperatorName = "operator new"; break;
2391 case OO_Delete: OperatorName = "operator delete"; break;
2392 case OO_Array_New: OperatorName = "operator new[]"; break;
2393 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2394 case OO_Call: OperatorName = "operator()"; break;
2395 case OO_Subscript: OperatorName = "operator[]"; break;
2396 }
2397 Result.AddTypedTextChunk(OperatorName);
2398 break;
2399 }
2400
Douglas Gregor6f942b22010-09-21 16:06:22 +00002401 case DeclarationName::Identifier:
2402 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002403 case DeclarationName::CXXDestructorName:
2404 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002405 Result.AddTypedTextChunk(
2406 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002407 break;
2408
2409 case DeclarationName::CXXUsingDirective:
2410 case DeclarationName::ObjCZeroArgSelector:
2411 case DeclarationName::ObjCOneArgSelector:
2412 case DeclarationName::ObjCMultiArgSelector:
2413 break;
2414
2415 case DeclarationName::CXXConstructorName: {
2416 CXXRecordDecl *Record = 0;
2417 QualType Ty = Name.getCXXNameType();
2418 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2419 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2420 else if (const InjectedClassNameType *InjectedTy
2421 = Ty->getAs<InjectedClassNameType>())
2422 Record = InjectedTy->getDecl();
2423 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002424 Result.AddTypedTextChunk(
2425 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002426 break;
2427 }
2428
Douglas Gregordae68752011-02-01 22:57:45 +00002429 Result.AddTypedTextChunk(
2430 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002431 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002432 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor8987b232011-09-27 23:30:47 +00002433 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002434 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002435 }
2436 break;
2437 }
2438 }
2439}
2440
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002441CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002442 CodeCompletionAllocator &Allocator,
2443 CodeCompletionTUInfo &CCTUInfo) {
2444 return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002445}
2446
Douglas Gregor86d9a522009-09-21 16:56:56 +00002447/// \brief If possible, create a new code completion string for the given
2448/// result.
2449///
2450/// \returns Either a new, heap-allocated code completion string describing
2451/// how to use this result, or NULL to indicate that the string or name of the
2452/// result is all that is needed.
2453CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002454CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2455 Preprocessor &PP,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002456 CodeCompletionAllocator &Allocator,
2457 CodeCompletionTUInfo &CCTUInfo) {
2458 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002459
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002460 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002461 if (Kind == RK_Pattern) {
2462 Pattern->Priority = Priority;
2463 Pattern->Availability = Availability;
Douglas Gregorba103062012-03-27 23:34:16 +00002464
2465 if (Declaration) {
2466 Result.addParentContext(Declaration->getDeclContext());
2467 Pattern->ParentKind = Result.getParentKind();
2468 Pattern->ParentName = Result.getParentName();
2469 }
2470
Douglas Gregor218937c2011-02-01 19:23:04 +00002471 return Pattern;
2472 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002473
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002474 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002475 Result.AddTypedTextChunk(Keyword);
2476 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002477 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002478
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002479 if (Kind == RK_Macro) {
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002480 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002481 assert(MI && "Not a macro?");
2482
Douglas Gregordae68752011-02-01 22:57:45 +00002483 Result.AddTypedTextChunk(
2484 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002485
2486 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002487 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002488
2489 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002490 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregore4244702011-07-30 08:17:44 +00002491 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002492
2493 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2494 if (MI->isC99Varargs()) {
2495 --AEnd;
2496
2497 if (A == AEnd) {
2498 Result.AddPlaceholderChunk("...");
2499 }
Douglas Gregore4244702011-07-30 08:17:44 +00002500 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002501
Douglas Gregore4244702011-07-30 08:17:44 +00002502 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002503 if (A != MI->arg_begin())
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002504 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002505
2506 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002507 SmallString<32> Arg = (*A)->getName();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002508 if (MI->isC99Varargs())
2509 Arg += ", ...";
2510 else
2511 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002512 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002513 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002514 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002515
2516 // Non-variadic macros are simple.
2517 Result.AddPlaceholderChunk(
2518 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002519 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002520 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002521 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002522 }
2523
Douglas Gregord8e8a582010-05-25 21:41:55 +00002524 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002525 NamedDecl *ND = Declaration;
Douglas Gregorba103062012-03-27 23:34:16 +00002526 Result.addParentContext(ND->getDeclContext());
2527
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002528 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002529 Result.AddTypedTextChunk(
2530 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002531 Result.AddTextChunk("::");
2532 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002533 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002534
2535 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2536 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2537 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2538 }
2539 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002540
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002541 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002542
Douglas Gregor86d9a522009-09-21 16:56:56 +00002543 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002544 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002545 Ctx, Policy);
2546 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002547 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002548 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002549 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002550 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002551 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002552 }
2553
2554 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002555 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002556 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002557 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002558 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002559
Douglas Gregor86d9a522009-09-21 16:56:56 +00002560 // Figure out which template parameters are deduced (or have default
2561 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002562 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002563 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002564 unsigned LastDeducibleArgument;
2565 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2566 --LastDeducibleArgument) {
2567 if (!Deduced[LastDeducibleArgument - 1]) {
2568 // C++0x: Figure out if the template argument has a default. If so,
2569 // the user doesn't need to type this argument.
2570 // FIXME: We need to abstract template parameters better!
2571 bool HasDefaultArg = false;
2572 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002573 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002574 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2575 HasDefaultArg = TTP->hasDefaultArgument();
2576 else if (NonTypeTemplateParmDecl *NTTP
2577 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2578 HasDefaultArg = NTTP->hasDefaultArgument();
2579 else {
2580 assert(isa<TemplateTemplateParmDecl>(Param));
2581 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002582 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002583 }
2584
2585 if (!HasDefaultArg)
2586 break;
2587 }
2588 }
2589
2590 if (LastDeducibleArgument) {
2591 // Some of the function template arguments cannot be deduced from a
2592 // function call, so we introduce an explicit template argument list
2593 // containing all of the arguments up to the first deducible argument.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002594 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002595 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002596 LastDeducibleArgument);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002597 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002598 }
2599
2600 // Add the function parameters
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002601 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002602 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002603 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002604 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002605 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002606 }
2607
2608 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002609 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002610 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002611 Result.AddTypedTextChunk(
2612 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002613 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002614 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002615 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor218937c2011-02-01 19:23:04 +00002616 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002617 }
2618
Douglas Gregor9630eb62009-11-17 16:44:22 +00002619 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002620 Selector Sel = Method->getSelector();
2621 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002622 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002623 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002624 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002625 }
2626
Douglas Gregor813d8342011-02-18 22:29:55 +00002627 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002628 SelName += ':';
2629 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002630 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002631 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002632 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002633
2634 // If there is only one parameter, and we're past it, add an empty
2635 // typed-text chunk since there is nothing to type.
2636 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002637 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002638 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002639 unsigned Idx = 0;
2640 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2641 PEnd = Method->param_end();
2642 P != PEnd; (void)++P, ++Idx) {
2643 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002644 std::string Keyword;
2645 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002646 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002647 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002648 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002649 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002650 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002651 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002652 else
Douglas Gregordae68752011-02-01 22:57:45 +00002653 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002654 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002655
2656 // If we're before the starting parameter, skip the placeholder.
2657 if (Idx < StartParameter)
2658 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002659
2660 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002661
2662 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002663 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002664 else {
John McCallf85e1932011-06-15 23:02:42 +00002665 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002666 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2667 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002668 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002669 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002670 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002671 }
2672
Douglas Gregore17794f2010-08-31 05:13:43 +00002673 if (Method->isVariadic() && (P + 1) == PEnd)
2674 Arg += ", ...";
2675
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002676 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002677 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002678 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002679 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002680 else
Douglas Gregordae68752011-02-01 22:57:45 +00002681 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002682 }
2683
Douglas Gregor2a17af02009-12-23 00:21:46 +00002684 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002685 if (Method->param_size() == 0) {
2686 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002687 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002688 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002689 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002690 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002691 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002692 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002693
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002694 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002695 }
2696
Douglas Gregor218937c2011-02-01 19:23:04 +00002697 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002698 }
2699
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002700 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002701 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002702 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002703
Douglas Gregordae68752011-02-01 22:57:45 +00002704 Result.AddTypedTextChunk(
2705 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002706 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002707}
2708
Douglas Gregor86d802e2009-09-23 00:34:09 +00002709CodeCompletionString *
2710CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2711 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002712 Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002713 CodeCompletionAllocator &Allocator,
2714 CodeCompletionTUInfo &CCTUInfo) const {
Douglas Gregor8987b232011-09-27 23:30:47 +00002715 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002716
Douglas Gregor218937c2011-02-01 19:23:04 +00002717 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002718 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002719 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002720 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002721 const FunctionProtoType *Proto
2722 = dyn_cast<FunctionProtoType>(getFunctionType());
2723 if (!FDecl && !Proto) {
2724 // Function without a prototype. Just give the return type and a
2725 // highlighted ellipsis.
2726 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002727 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002728 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002729 Result.getAllocator()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002730 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2731 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2732 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002733 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002734 }
2735
2736 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002737 Result.AddTextChunk(
2738 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002739 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002740 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002741 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002742 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002743
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002744 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002745 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2746 for (unsigned I = 0; I != NumParams; ++I) {
2747 if (I)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002748 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002749
2750 std::string ArgString;
2751 QualType ArgType;
2752
2753 if (FDecl) {
2754 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2755 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2756 } else {
2757 ArgType = Proto->getArgType(I);
2758 }
2759
John McCallf85e1932011-06-15 23:02:42 +00002760 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002761
2762 if (I == CurrentArg)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002763 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2764 Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002765 else
Douglas Gregordae68752011-02-01 22:57:45 +00002766 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002767 }
2768
2769 if (Proto && Proto->isVariadic()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002770 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002771 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002772 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002773 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002774 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002775 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002776 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002777
Douglas Gregor218937c2011-02-01 19:23:04 +00002778 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002779}
2780
Chris Lattner5f9e2722011-07-23 10:55:15 +00002781unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002782 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002783 bool PreferredTypeIsPointer) {
2784 unsigned Priority = CCP_Macro;
2785
Douglas Gregorb05496d2010-09-20 21:11:48 +00002786 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2787 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2788 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002789 Priority = CCP_Constant;
2790 if (PreferredTypeIsPointer)
2791 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002792 }
2793 // Treat "YES", "NO", "true", and "false" as constants.
2794 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2795 MacroName.equals("true") || MacroName.equals("false"))
2796 Priority = CCP_Constant;
2797 // Treat "bool" as a type.
2798 else if (MacroName.equals("bool"))
2799 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2800
Douglas Gregor1827e102010-08-16 16:18:59 +00002801
2802 return Priority;
2803}
2804
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002805CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2806 if (!D)
2807 return CXCursor_UnexposedDecl;
2808
2809 switch (D->getKind()) {
2810 case Decl::Enum: return CXCursor_EnumDecl;
2811 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2812 case Decl::Field: return CXCursor_FieldDecl;
2813 case Decl::Function:
2814 return CXCursor_FunctionDecl;
2815 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2816 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002817 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002818
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002819 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002820 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2821 case Decl::ObjCMethod:
2822 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2823 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2824 case Decl::CXXMethod: return CXCursor_CXXMethod;
2825 case Decl::CXXConstructor: return CXCursor_Constructor;
2826 case Decl::CXXDestructor: return CXCursor_Destructor;
2827 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2828 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002829 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002830 case Decl::ParmVar: return CXCursor_ParmDecl;
2831 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002832 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002833 case Decl::Var: return CXCursor_VarDecl;
2834 case Decl::Namespace: return CXCursor_Namespace;
2835 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2836 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2837 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2838 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2839 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2840 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002841 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002842 case Decl::ClassTemplatePartialSpecialization:
2843 return CXCursor_ClassTemplatePartialSpecialization;
2844 case Decl::UsingDirective: return CXCursor_UsingDirective;
Douglas Gregor8e5900c2012-04-30 23:41:16 +00002845 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002846
2847 case Decl::Using:
2848 case Decl::UnresolvedUsingValue:
2849 case Decl::UnresolvedUsingTypename:
2850 return CXCursor_UsingDeclaration;
2851
Douglas Gregor352697a2011-06-03 23:08:58 +00002852 case Decl::ObjCPropertyImpl:
2853 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2854 case ObjCPropertyImplDecl::Dynamic:
2855 return CXCursor_ObjCDynamicDecl;
2856
2857 case ObjCPropertyImplDecl::Synthesize:
2858 return CXCursor_ObjCSynthesizeDecl;
2859 }
Douglas Gregor352697a2011-06-03 23:08:58 +00002860
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002861 default:
2862 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2863 switch (TD->getTagKind()) {
2864 case TTK_Struct: return CXCursor_StructDecl;
2865 case TTK_Class: return CXCursor_ClassDecl;
2866 case TTK_Union: return CXCursor_UnionDecl;
2867 case TTK_Enum: return CXCursor_EnumDecl;
2868 }
2869 }
2870 }
2871
2872 return CXCursor_UnexposedDecl;
2873}
2874
Douglas Gregor590c7d52010-07-08 20:55:51 +00002875static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2876 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002877 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002878
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002879 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002880
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002881 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2882 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002883 M != MEnd; ++M) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002884 Results.AddResult(Result(M->first,
2885 getMacroUsagePriority(M->first->getName(),
David Blaikie4e4d0842012-03-11 07:00:24 +00002886 PP.getLangOpts(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002887 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002888 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002889
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002890 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002891
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002892}
2893
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002894static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2895 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002896 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002897
2898 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002899
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002900 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2901 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2902 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2903 Results.AddResult(Result("__func__", CCP_Constant));
2904 Results.ExitScope();
2905}
2906
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002907static void HandleCodeCompleteResults(Sema *S,
2908 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002909 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002910 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002911 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002912 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002913 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002914}
2915
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002916static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2917 Sema::ParserCompletionContext PCC) {
2918 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002919 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002920 return CodeCompletionContext::CCC_TopLevel;
2921
John McCallf312b1e2010-08-26 23:41:50 +00002922 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002923 return CodeCompletionContext::CCC_ClassStructUnion;
2924
John McCallf312b1e2010-08-26 23:41:50 +00002925 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002926 return CodeCompletionContext::CCC_ObjCInterface;
2927
John McCallf312b1e2010-08-26 23:41:50 +00002928 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002929 return CodeCompletionContext::CCC_ObjCImplementation;
2930
John McCallf312b1e2010-08-26 23:41:50 +00002931 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002932 return CodeCompletionContext::CCC_ObjCIvarList;
2933
John McCallf312b1e2010-08-26 23:41:50 +00002934 case Sema::PCC_Template:
2935 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002936 if (S.CurContext->isFileContext())
2937 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002938 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002939 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002940 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002941
John McCallf312b1e2010-08-26 23:41:50 +00002942 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002943 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002944
John McCallf312b1e2010-08-26 23:41:50 +00002945 case Sema::PCC_ForInit:
David Blaikie4e4d0842012-03-11 07:00:24 +00002946 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2947 S.getLangOpts().ObjC1)
Douglas Gregora5450a02010-10-18 22:01:46 +00002948 return CodeCompletionContext::CCC_ParenthesizedExpression;
2949 else
2950 return CodeCompletionContext::CCC_Expression;
2951
2952 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002953 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002954 return CodeCompletionContext::CCC_Expression;
2955
John McCallf312b1e2010-08-26 23:41:50 +00002956 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002957 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002958
John McCallf312b1e2010-08-26 23:41:50 +00002959 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002960 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002961
2962 case Sema::PCC_ParenthesizedExpression:
2963 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002964
2965 case Sema::PCC_LocalDeclarationSpecifiers:
2966 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002967 }
David Blaikie7530c032012-01-17 06:56:22 +00002968
2969 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002970}
2971
Douglas Gregorf6961522010-08-27 21:18:54 +00002972/// \brief If we're in a C++ virtual member function, add completion results
2973/// that invoke the functions we override, since it's common to invoke the
2974/// overridden function as well as adding new functionality.
2975///
2976/// \param S The semantic analysis object for which we are generating results.
2977///
2978/// \param InContext This context in which the nested-name-specifier preceding
2979/// the code-completion point
2980static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2981 ResultBuilder &Results) {
2982 // Look through blocks.
2983 DeclContext *CurContext = S.CurContext;
2984 while (isa<BlockDecl>(CurContext))
2985 CurContext = CurContext->getParent();
2986
2987
2988 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2989 if (!Method || !Method->isVirtual())
2990 return;
2991
2992 // We need to have names for all of the parameters, if we're going to
2993 // generate a forwarding call.
2994 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2995 PEnd = Method->param_end();
2996 P != PEnd;
2997 ++P) {
2998 if (!(*P)->getDeclName())
2999 return;
3000 }
3001
Douglas Gregor8987b232011-09-27 23:30:47 +00003002 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00003003 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
3004 MEnd = Method->end_overridden_methods();
3005 M != MEnd; ++M) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003006 CodeCompletionBuilder Builder(Results.getAllocator(),
3007 Results.getCodeCompletionTUInfo());
Douglas Gregorf6961522010-08-27 21:18:54 +00003008 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
3009 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3010 continue;
3011
3012 // If we need a nested-name-specifier, add one now.
3013 if (!InContext) {
3014 NestedNameSpecifier *NNS
3015 = getRequiredQualification(S.Context, CurContext,
3016 Overridden->getDeclContext());
3017 if (NNS) {
3018 std::string Str;
3019 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00003020 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00003021 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003022 }
3023 } else if (!InContext->Equals(Overridden->getDeclContext()))
3024 continue;
3025
Douglas Gregordae68752011-02-01 22:57:45 +00003026 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003027 Overridden->getNameAsString()));
3028 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00003029 bool FirstParam = true;
3030 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3031 PEnd = Method->param_end();
3032 P != PEnd; ++P) {
3033 if (FirstParam)
3034 FirstParam = false;
3035 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003036 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003037
Douglas Gregordae68752011-02-01 22:57:45 +00003038 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003039 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003040 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003041 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3042 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003043 CCP_SuperCompletion,
Douglas Gregorba103062012-03-27 23:34:16 +00003044 CXCursor_CXXMethod,
3045 CXAvailability_Available,
3046 Overridden));
Douglas Gregorf6961522010-08-27 21:18:54 +00003047 Results.Ignore(Overridden);
3048 }
3049}
3050
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003051void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3052 ModuleIdPath Path) {
3053 typedef CodeCompletionResult Result;
3054 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003055 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003056 CodeCompletionContext::CCC_Other);
3057 Results.EnterNewScope();
3058
3059 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003060 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003061 typedef CodeCompletionResult Result;
3062 if (Path.empty()) {
3063 // Enumerate all top-level modules.
3064 llvm::SmallVector<Module *, 8> Modules;
3065 PP.getHeaderSearchInfo().collectAllModules(Modules);
3066 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3067 Builder.AddTypedTextChunk(
3068 Builder.getAllocator().CopyString(Modules[I]->Name));
3069 Results.AddResult(Result(Builder.TakeString(),
3070 CCP_Declaration,
3071 CXCursor_NotImplemented,
3072 Modules[I]->isAvailable()
3073 ? CXAvailability_Available
3074 : CXAvailability_NotAvailable));
3075 }
3076 } else {
3077 // Load the named module.
3078 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3079 Module::AllVisible,
3080 /*IsInclusionDirective=*/false);
3081 // Enumerate submodules.
3082 if (Mod) {
3083 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3084 SubEnd = Mod->submodule_end();
3085 Sub != SubEnd; ++Sub) {
3086
3087 Builder.AddTypedTextChunk(
3088 Builder.getAllocator().CopyString((*Sub)->Name));
3089 Results.AddResult(Result(Builder.TakeString(),
3090 CCP_Declaration,
3091 CXCursor_NotImplemented,
3092 (*Sub)->isAvailable()
3093 ? CXAvailability_Available
3094 : CXAvailability_NotAvailable));
3095 }
3096 }
3097 }
3098 Results.ExitScope();
3099 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3100 Results.data(),Results.size());
3101}
3102
Douglas Gregor01dfea02010-01-10 23:08:15 +00003103void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003104 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00003105 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003106 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003107 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003108 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003109 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003110
Douglas Gregor01dfea02010-01-10 23:08:15 +00003111 // Determine how to filter results, e.g., so that the names of
3112 // values (functions, enumerators, function templates, etc.) are
3113 // only allowed where we can have an expression.
3114 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003115 case PCC_Namespace:
3116 case PCC_Class:
3117 case PCC_ObjCInterface:
3118 case PCC_ObjCImplementation:
3119 case PCC_ObjCInstanceVariableList:
3120 case PCC_Template:
3121 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003122 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003123 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003124 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3125 break;
3126
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003127 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003128 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003129 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003130 case PCC_ForInit:
3131 case PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00003132 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003133 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3134 else
3135 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003136
David Blaikie4e4d0842012-03-11 07:00:24 +00003137 if (getLangOpts().CPlusPlus)
Douglas Gregorf6961522010-08-27 21:18:54 +00003138 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003139 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003140
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003141 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003142 // Unfiltered
3143 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003144 }
3145
Douglas Gregor3cdee122010-08-26 16:36:48 +00003146 // If we are in a C++ non-static member function, check the qualifiers on
3147 // the member function to filter/prioritize the results list.
3148 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3149 if (CurMethod->isInstance())
3150 Results.setObjectTypeQualifiers(
3151 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3152
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003153 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003154 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3155 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003156
Douglas Gregorbca403c2010-01-13 23:51:12 +00003157 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003158 Results.ExitScope();
3159
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003160 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003161 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003162 case PCC_Expression:
3163 case PCC_Statement:
3164 case PCC_RecoveryInFunction:
3165 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003166 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor72db1082010-08-24 01:11:00 +00003167 break;
3168
3169 case PCC_Namespace:
3170 case PCC_Class:
3171 case PCC_ObjCInterface:
3172 case PCC_ObjCImplementation:
3173 case PCC_ObjCInstanceVariableList:
3174 case PCC_Template:
3175 case PCC_MemberTemplate:
3176 case PCC_ForInit:
3177 case PCC_Condition:
3178 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003179 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003180 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003181 }
3182
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003183 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003184 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003185
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003186 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003187 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003188}
3189
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003190static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3191 ParsedType Receiver,
3192 IdentifierInfo **SelIdents,
3193 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003194 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003195 bool IsSuper,
3196 ResultBuilder &Results);
3197
3198void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3199 bool AllowNonIdentifiers,
3200 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003201 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003202 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003203 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003204 AllowNestedNameSpecifiers
3205 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3206 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003207 Results.EnterNewScope();
3208
3209 // Type qualifiers can come after names.
3210 Results.AddResult(Result("const"));
3211 Results.AddResult(Result("volatile"));
David Blaikie4e4d0842012-03-11 07:00:24 +00003212 if (getLangOpts().C99)
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003213 Results.AddResult(Result("restrict"));
3214
David Blaikie4e4d0842012-03-11 07:00:24 +00003215 if (getLangOpts().CPlusPlus) {
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003216 if (AllowNonIdentifiers) {
3217 Results.AddResult(Result("operator"));
3218 }
3219
3220 // Add nested-name-specifiers.
3221 if (AllowNestedNameSpecifiers) {
3222 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003223 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003224 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3225 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3226 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003227 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003228 }
3229 }
3230 Results.ExitScope();
3231
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003232 // If we're in a context where we might have an expression (rather than a
3233 // declaration), and what we've seen so far is an Objective-C type that could
3234 // be a receiver of a class message, this may be a class message send with
3235 // the initial opening bracket '[' missing. Add appropriate completions.
3236 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3237 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3238 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3239 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3240 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3241 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3242 DS.getTypeQualifiers() == 0 &&
3243 S &&
3244 (S->getFlags() & Scope::DeclScope) != 0 &&
3245 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3246 Scope::FunctionPrototypeScope |
3247 Scope::AtCatchScope)) == 0) {
3248 ParsedType T = DS.getRepAsType();
3249 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003250 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003251 }
3252
Douglas Gregor4497dd42010-08-24 04:59:56 +00003253 // Note that we intentionally suppress macro results here, since we do not
3254 // encourage using macros to produce the names of entities.
3255
Douglas Gregor52779fb2010-09-23 23:01:17 +00003256 HandleCodeCompleteResults(this, CodeCompleter,
3257 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003258 Results.data(), Results.size());
3259}
3260
Douglas Gregorfb629412010-08-23 21:17:50 +00003261struct Sema::CodeCompleteExpressionData {
3262 CodeCompleteExpressionData(QualType PreferredType = QualType())
3263 : PreferredType(PreferredType), IntegralConstantExpression(false),
3264 ObjCCollection(false) { }
3265
3266 QualType PreferredType;
3267 bool IntegralConstantExpression;
3268 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003269 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003270};
3271
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003272/// \brief Perform code-completion in an expression context when we know what
3273/// type we're looking for.
Douglas Gregorfb629412010-08-23 21:17:50 +00003274void Sema::CodeCompleteExpression(Scope *S,
3275 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00003276 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003277 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003278 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003279 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003280 if (Data.ObjCCollection)
3281 Results.setFilter(&ResultBuilder::IsObjCCollection);
3282 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003283 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikie4e4d0842012-03-11 07:00:24 +00003284 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003285 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3286 else
3287 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003288
3289 if (!Data.PreferredType.isNull())
3290 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3291
3292 // Ignore any declarations that we were told that we don't care about.
3293 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3294 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003295
3296 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003297 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3298 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003299
3300 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003301 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003302 Results.ExitScope();
3303
Douglas Gregor590c7d52010-07-08 20:55:51 +00003304 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003305 if (!Data.PreferredType.isNull())
3306 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3307 || Data.PreferredType->isMemberPointerType()
3308 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003309
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003310 if (S->getFnParent() &&
3311 !Data.ObjCCollection &&
3312 !Data.IntegralConstantExpression)
David Blaikie4e4d0842012-03-11 07:00:24 +00003313 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003314
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003315 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003316 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003317 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003318 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3319 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003320 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003321}
3322
Douglas Gregorac5fd842010-09-18 01:28:11 +00003323void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3324 if (E.isInvalid())
3325 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikie4e4d0842012-03-11 07:00:24 +00003326 else if (getLangOpts().ObjC1)
Douglas Gregorac5fd842010-09-18 01:28:11 +00003327 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003328}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003329
Douglas Gregor73449212010-12-09 23:01:55 +00003330/// \brief The set of properties that have already been added, referenced by
3331/// property name.
3332typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3333
Douglas Gregorb92a4082012-06-12 13:44:08 +00003334/// \brief Retrieve the container definition, if any?
3335static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3336 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3337 if (Interface->hasDefinition())
3338 return Interface->getDefinition();
3339
3340 return Interface;
3341 }
3342
3343 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3344 if (Protocol->hasDefinition())
3345 return Protocol->getDefinition();
3346
3347 return Protocol;
3348 }
3349 return Container;
3350}
3351
3352static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003353 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003354 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003355 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003356 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003357 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003358 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003359
Douglas Gregorb92a4082012-06-12 13:44:08 +00003360 // Retrieve the definition.
3361 Container = getContainerDef(Container);
3362
Douglas Gregor95ac6552009-11-18 01:29:26 +00003363 // Add properties in this container.
3364 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3365 PEnd = Container->prop_end();
3366 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003367 ++P) {
3368 if (AddedProperties.insert(P->getIdentifier()))
David Blaikie581deb32012-06-06 20:45:41 +00003369 Results.MaybeAddResult(Result(*P, 0), CurContext);
Douglas Gregor73449212010-12-09 23:01:55 +00003370 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003371
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003372 // Add nullary methods
3373 if (AllowNullaryMethods) {
3374 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003375 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003376 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3377 MEnd = Container->meth_end();
3378 M != MEnd; ++M) {
3379 if (M->getSelector().isUnarySelector())
3380 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3381 if (AddedProperties.insert(Name)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003382 CodeCompletionBuilder Builder(Results.getAllocator(),
3383 Results.getCodeCompletionTUInfo());
David Blaikie581deb32012-06-06 20:45:41 +00003384 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003385 Builder.AddTypedTextChunk(
3386 Results.getAllocator().CopyString(Name->getName()));
3387
David Blaikie581deb32012-06-06 20:45:41 +00003388 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
Douglas Gregorba103062012-03-27 23:34:16 +00003389 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003390 CurContext);
3391 }
3392 }
3393 }
3394
3395
Douglas Gregor95ac6552009-11-18 01:29:26 +00003396 // Add properties in referenced protocols.
3397 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3398 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3399 PEnd = Protocol->protocol_end();
3400 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003401 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3402 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003403 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003404 if (AllowCategories) {
3405 // Look through categories.
3406 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3407 Category; Category = Category->getNextClassCategory())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003408 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3409 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003410 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003411
3412 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003413 for (ObjCInterfaceDecl::all_protocol_iterator
3414 I = IFace->all_referenced_protocol_begin(),
3415 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003416 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3417 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003418
3419 // Look in the superclass.
3420 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003421 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3422 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003423 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003424 } else if (const ObjCCategoryDecl *Category
3425 = dyn_cast<ObjCCategoryDecl>(Container)) {
3426 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003427 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3428 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003429 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003430 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3431 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003432 }
3433}
3434
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003435void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003436 SourceLocation OpLoc,
3437 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003438 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003439 return;
3440
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003441 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3442 if (ConvertedBase.isInvalid())
3443 return;
3444 Base = ConvertedBase.get();
3445
John McCall0a2c5e22010-08-25 06:19:51 +00003446 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003447
Douglas Gregor81b747b2009-09-17 21:32:03 +00003448 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003449
3450 if (IsArrow) {
3451 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3452 BaseType = Ptr->getPointeeType();
3453 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003454 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003455 else
3456 return;
3457 }
3458
Douglas Gregor3da626b2011-07-07 16:03:39 +00003459 enum CodeCompletionContext::Kind contextKind;
3460
3461 if (IsArrow) {
3462 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3463 }
3464 else {
3465 if (BaseType->isObjCObjectPointerType() ||
3466 BaseType->isObjCObjectOrInterfaceType()) {
3467 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3468 }
3469 else {
3470 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3471 }
3472 }
3473
Douglas Gregor218937c2011-02-01 19:23:04 +00003474 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003475 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003476 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003477 BaseType),
3478 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003479 Results.EnterNewScope();
3480 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003481 // Indicate that we are performing a member access, and the cv-qualifiers
3482 // for the base object type.
3483 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3484
Douglas Gregor95ac6552009-11-18 01:29:26 +00003485 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003486 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003487 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003488 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3489 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003490
David Blaikie4e4d0842012-03-11 07:00:24 +00003491 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003492 if (!Results.empty()) {
3493 // The "template" keyword can follow "->" or "." in the grammar.
3494 // However, we only want to suggest the template keyword if something
3495 // is dependent.
3496 bool IsDependent = BaseType->isDependentType();
3497 if (!IsDependent) {
3498 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3499 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3500 IsDependent = Ctx->isDependentContext();
3501 break;
3502 }
3503 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003504
Douglas Gregor95ac6552009-11-18 01:29:26 +00003505 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003506 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003507 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003508 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003509 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3510 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003511 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003512
3513 // Add property results based on our interface.
3514 const ObjCObjectPointerType *ObjCPtr
3515 = BaseType->getAsObjCInterfacePointerType();
3516 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003517 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3518 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003519 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003520
3521 // Add properties from the protocols in a qualified interface.
3522 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3523 E = ObjCPtr->qual_end();
3524 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003525 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3526 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003527 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003528 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003529 // Objective-C instance variable access.
3530 ObjCInterfaceDecl *Class = 0;
3531 if (const ObjCObjectPointerType *ObjCPtr
3532 = BaseType->getAs<ObjCObjectPointerType>())
3533 Class = ObjCPtr->getInterfaceDecl();
3534 else
John McCallc12c5bb2010-05-15 11:32:37 +00003535 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003536
3537 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003538 if (Class) {
3539 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3540 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003541 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3542 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003543 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003544 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003545
3546 // FIXME: How do we cope with isa?
3547
3548 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003549
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003550 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003551 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003552 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003553 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003554}
3555
Douglas Gregor374929f2009-09-18 15:37:17 +00003556void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3557 if (!CodeCompleter)
3558 return;
3559
John McCall0a2c5e22010-08-25 06:19:51 +00003560 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003561 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003562 enum CodeCompletionContext::Kind ContextKind
3563 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003564 switch ((DeclSpec::TST)TagSpec) {
3565 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003566 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003567 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003568 break;
3569
3570 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003571 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003572 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003573 break;
3574
3575 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003576 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003577 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003578 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003579 break;
3580
3581 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003582 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003583 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003584
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003585 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3586 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003587 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003588
3589 // First pass: look for tags.
3590 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003591 LookupVisibleDecls(S, LookupTagName, Consumer,
3592 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003593
Douglas Gregor8071e422010-08-15 06:18:01 +00003594 if (CodeCompleter->includeGlobals()) {
3595 // Second pass: look for nested name specifiers.
3596 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3597 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3598 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003599
Douglas Gregor52779fb2010-09-23 23:01:17 +00003600 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003601 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003602}
3603
Douglas Gregor1a480c42010-08-27 17:35:51 +00003604void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003605 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003606 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003607 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003608 Results.EnterNewScope();
3609 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3610 Results.AddResult("const");
3611 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3612 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003613 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003614 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3615 Results.AddResult("restrict");
3616 Results.ExitScope();
3617 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003618 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003619 Results.data(), Results.size());
3620}
3621
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003622void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003623 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003624 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003625
John McCall781472f2010-08-25 08:40:02 +00003626 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003627 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3628 if (!type->isEnumeralType()) {
3629 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003630 Data.IntegralConstantExpression = true;
3631 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003632 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003633 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003634
3635 // Code-complete the cases of a switch statement over an enumeration type
3636 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003637 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregorb92a4082012-06-12 13:44:08 +00003638 if (EnumDecl *Def = Enum->getDefinition())
3639 Enum = Def;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003640
3641 // Determine which enumerators we have already seen in the switch statement.
3642 // FIXME: Ideally, we would also be able to look *past* the code-completion
3643 // token, in case we are code-completing in the middle of the switch and not
3644 // at the end. However, we aren't able to do so at the moment.
3645 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003646 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003647 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3648 SC = SC->getNextSwitchCase()) {
3649 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3650 if (!Case)
3651 continue;
3652
3653 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3654 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3655 if (EnumConstantDecl *Enumerator
3656 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3657 // We look into the AST of the case statement to determine which
3658 // enumerator was named. Alternatively, we could compute the value of
3659 // the integral constant expression, then compare it against the
3660 // values of each enumerator. However, value-based approach would not
3661 // work as well with C++ templates where enumerators declared within a
3662 // template are type- and value-dependent.
3663 EnumeratorsSeen.insert(Enumerator);
3664
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003665 // If this is a qualified-id, keep track of the nested-name-specifier
3666 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003667 //
3668 // switch (TagD.getKind()) {
3669 // case TagDecl::TK_enum:
3670 // break;
3671 // case XXX
3672 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003673 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003674 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3675 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003676 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003677 }
3678 }
3679
David Blaikie4e4d0842012-03-11 07:00:24 +00003680 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003681 // If there are no prior enumerators in C++, check whether we have to
3682 // qualify the names of the enumerators that we suggest, because they
3683 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003684 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003685 }
3686
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003687 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003688 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003689 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003690 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003691 Results.EnterNewScope();
3692 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3693 EEnd = Enum->enumerator_end();
3694 E != EEnd; ++E) {
David Blaikie581deb32012-06-06 20:45:41 +00003695 if (EnumeratorsSeen.count(*E))
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003696 continue;
3697
David Blaikie581deb32012-06-06 20:45:41 +00003698 CodeCompletionResult R(*E, Qualifier);
Douglas Gregor5c722c702011-02-18 23:30:37 +00003699 R.Priority = CCP_EnumInCase;
3700 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003701 }
3702 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003703
Douglas Gregor3da626b2011-07-07 16:03:39 +00003704 //We need to make sure we're setting the right context,
3705 //so only say we include macros if the code completer says we do
3706 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3707 if (CodeCompleter->includeMacros()) {
Douglas Gregorbca403c2010-01-13 23:51:12 +00003708 AddMacroResults(PP, Results);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003709 kind = CodeCompletionContext::CCC_OtherWithMacros;
3710 }
3711
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003712 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003713 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003714 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003715}
3716
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003717namespace {
3718 struct IsBetterOverloadCandidate {
3719 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003720 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003721
3722 public:
John McCall5769d612010-02-08 23:07:23 +00003723 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3724 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003725
3726 bool
3727 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003728 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003729 }
3730 };
3731}
3732
Ahmed Charles13a140c2012-02-25 11:00:22 +00003733static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3734 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003735 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003736
3737 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003738 if (!Args[I])
3739 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003740
Douglas Gregord28dcd72010-05-30 06:10:08 +00003741 return false;
3742}
3743
Richard Trieuf81e5a92011-09-09 02:00:50 +00003744void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charles13a140c2012-02-25 11:00:22 +00003745 llvm::ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003746 if (!CodeCompleter)
3747 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003748
3749 // When we're code-completing for a call, we fall back to ordinary
3750 // name code-completion whenever we can't produce specific
3751 // results. We may want to revisit this strategy in the future,
3752 // e.g., by merging the two kinds of results.
3753
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003754 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003755
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003756 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003757 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3758 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003759 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003760 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003761 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003762
John McCall3b4294e2009-12-16 12:17:52 +00003763 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003764 SourceLocation Loc = Fn->getExprLoc();
3765 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003766
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003767 // FIXME: What if we're calling something that isn't a function declaration?
3768 // FIXME: What if we're calling a pseudo-destructor?
3769 // FIXME: What if we're calling a member function?
3770
Douglas Gregorc0265402010-01-21 15:46:19 +00003771 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003772 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003773
John McCall3b4294e2009-12-16 12:17:52 +00003774 Expr *NakedFn = Fn->IgnoreParenCasts();
3775 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003776 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003777 /*PartialOverloading=*/ true);
3778 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3779 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003780 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003781 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003782 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003783 Results.push_back(ResultCandidate(FDecl));
3784 else
John McCall86820f52010-01-26 01:37:31 +00003785 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003786 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3787 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003788 }
John McCall3b4294e2009-12-16 12:17:52 +00003789 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003790
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003791 QualType ParamType;
3792
Douglas Gregorc0265402010-01-21 15:46:19 +00003793 if (!CandidateSet.empty()) {
3794 // Sort the overload candidate set by placing the best overloads first.
3795 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003796 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003797
Douglas Gregorc0265402010-01-21 15:46:19 +00003798 // Add the remaining viable overload candidates as code-completion reslults.
3799 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3800 CandEnd = CandidateSet.end();
3801 Cand != CandEnd; ++Cand) {
3802 if (Cand->Viable)
3803 Results.push_back(ResultCandidate(Cand->Function));
3804 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003805
3806 // From the viable candidates, try to determine the type of this parameter.
3807 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3808 if (const FunctionType *FType = Results[I].getFunctionType())
3809 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003810 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003811 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003812 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003813 else if (!Context.hasSameUnqualifiedType(
3814 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003815 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003816 ParamType = QualType();
3817 break;
3818 }
3819 }
3820 }
3821 } else {
3822 // Try to determine the parameter type from the type of the expression
3823 // being called.
3824 QualType FunctionType = Fn->getType();
3825 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3826 FunctionType = Ptr->getPointeeType();
3827 else if (const BlockPointerType *BlockPtr
3828 = FunctionType->getAs<BlockPointerType>())
3829 FunctionType = BlockPtr->getPointeeType();
3830 else if (const MemberPointerType *MemPtr
3831 = FunctionType->getAs<MemberPointerType>())
3832 FunctionType = MemPtr->getPointeeType();
3833
3834 if (const FunctionProtoType *Proto
3835 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003836 if (Args.size() < Proto->getNumArgs())
3837 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003838 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003839 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003840
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003841 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003842 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003843 else
3844 CodeCompleteExpression(S, ParamType);
3845
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003846 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003847 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003848 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003849}
3850
John McCalld226f652010-08-21 09:40:31 +00003851void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3852 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003853 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003854 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003855 return;
3856 }
3857
3858 CodeCompleteExpression(S, VD->getType());
3859}
3860
3861void Sema::CodeCompleteReturn(Scope *S) {
3862 QualType ResultType;
3863 if (isa<BlockDecl>(CurContext)) {
3864 if (BlockScopeInfo *BSI = getCurBlock())
3865 ResultType = BSI->ReturnType;
3866 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3867 ResultType = Function->getResultType();
3868 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3869 ResultType = Method->getResultType();
3870
3871 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003872 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003873 else
3874 CodeCompleteExpression(S, ResultType);
3875}
3876
Douglas Gregord2d8be62011-07-30 08:36:53 +00003877void Sema::CodeCompleteAfterIf(Scope *S) {
3878 typedef CodeCompletionResult Result;
3879 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003880 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord2d8be62011-07-30 08:36:53 +00003881 mapCodeCompletionContext(*this, PCC_Statement));
3882 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3883 Results.EnterNewScope();
3884
3885 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3886 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3887 CodeCompleter->includeGlobals());
3888
3889 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3890
3891 // "else" block
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003892 CodeCompletionBuilder Builder(Results.getAllocator(),
3893 Results.getCodeCompletionTUInfo());
Douglas Gregord2d8be62011-07-30 08:36:53 +00003894 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00003895 if (Results.includeCodePatterns()) {
3896 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3897 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3898 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3899 Builder.AddPlaceholderChunk("statements");
3900 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3901 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3902 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003903 Results.AddResult(Builder.TakeString());
3904
3905 // "else if" block
3906 Builder.AddTypedTextChunk("else");
3907 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3908 Builder.AddTextChunk("if");
3909 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3910 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00003911 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00003912 Builder.AddPlaceholderChunk("condition");
3913 else
3914 Builder.AddPlaceholderChunk("expression");
3915 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00003916 if (Results.includeCodePatterns()) {
3917 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3918 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3919 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3920 Builder.AddPlaceholderChunk("statements");
3921 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3922 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3923 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003924 Results.AddResult(Builder.TakeString());
3925
3926 Results.ExitScope();
3927
3928 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003929 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003930
3931 if (CodeCompleter->includeMacros())
3932 AddMacroResults(PP, Results);
3933
3934 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3935 Results.data(),Results.size());
3936}
3937
Richard Trieuf81e5a92011-09-09 02:00:50 +00003938void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003939 if (LHS)
3940 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3941 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003942 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003943}
3944
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003945void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003946 bool EnteringContext) {
3947 if (!SS.getScopeRep() || !CodeCompleter)
3948 return;
3949
Douglas Gregor86d9a522009-09-21 16:56:56 +00003950 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3951 if (!Ctx)
3952 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003953
3954 // Try to instantiate any non-dependent declaration contexts before
3955 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003956 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003957 return;
3958
Douglas Gregor218937c2011-02-01 19:23:04 +00003959 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003960 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003961 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003962 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003963
Douglas Gregor86d9a522009-09-21 16:56:56 +00003964 // The "template" keyword can follow "::" in the grammar, but only
3965 // put it into the grammar if the nested-name-specifier is dependent.
3966 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3967 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003968 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003969
3970 // Add calls to overridden virtual functions, if there are any.
3971 //
3972 // FIXME: This isn't wonderful, because we don't know whether we're actually
3973 // in a context that permits expressions. This is a general issue with
3974 // qualified-id completions.
3975 if (!EnteringContext)
3976 MaybeAddOverrideCalls(*this, Ctx, Results);
3977 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003978
Douglas Gregorf6961522010-08-27 21:18:54 +00003979 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3980 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3981
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003982 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00003983 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003984 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003985}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003986
3987void Sema::CodeCompleteUsing(Scope *S) {
3988 if (!CodeCompleter)
3989 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 Gregor52779fb2010-09-23 23:01:17 +00003993 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3994 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003995 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003996
3997 // If we aren't in class scope, we could see the "namespace" keyword.
3998 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00003999 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004000
4001 // After "using", we can see anything that would start a
4002 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004003 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004004 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4005 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004006 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004007
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004008 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004009 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004010 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004011}
4012
4013void Sema::CodeCompleteUsingDirective(Scope *S) {
4014 if (!CodeCompleter)
4015 return;
4016
Douglas Gregor86d9a522009-09-21 16:56:56 +00004017 // After "using namespace", we expect to see a namespace name or namespace
4018 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004019 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004020 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004021 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004022 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004023 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004024 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004025 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4026 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004027 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004028 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004029 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004030 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004031}
4032
4033void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4034 if (!CodeCompleter)
4035 return;
4036
Douglas Gregor86d9a522009-09-21 16:56:56 +00004037 DeclContext *Ctx = (DeclContext *)S->getEntity();
4038 if (!S->getParent())
4039 Ctx = Context.getTranslationUnitDecl();
4040
Douglas Gregor52779fb2010-09-23 23:01:17 +00004041 bool SuppressedGlobalResults
4042 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4043
Douglas Gregor218937c2011-02-01 19:23:04 +00004044 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004045 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004046 SuppressedGlobalResults
4047 ? CodeCompletionContext::CCC_Namespace
4048 : CodeCompletionContext::CCC_Other,
4049 &ResultBuilder::IsNamespace);
4050
4051 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004052 // We only want to see those namespaces that have already been defined
4053 // within this scope, because its likely that the user is creating an
4054 // extended namespace declaration. Keep track of the most recent
4055 // definition of each namespace.
4056 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4057 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4058 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4059 NS != NSEnd; ++NS)
David Blaikie581deb32012-06-06 20:45:41 +00004060 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004061
4062 // Add the most recent definition (or extended definition) of each
4063 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004064 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004065 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregorba103062012-03-27 23:34:16 +00004066 NS = OrigToLatest.begin(),
4067 NSEnd = OrigToLatest.end();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004068 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004069 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004070 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004071 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004072 }
4073
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004074 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004075 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004076 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004077}
4078
4079void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4080 if (!CodeCompleter)
4081 return;
4082
Douglas Gregor86d9a522009-09-21 16:56:56 +00004083 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004084 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004085 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004086 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004087 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004088 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004089 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4090 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004091 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004092 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004093 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004094}
4095
Douglas Gregored8d3222009-09-18 20:05:18 +00004096void Sema::CodeCompleteOperatorName(Scope *S) {
4097 if (!CodeCompleter)
4098 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004099
John McCall0a2c5e22010-08-25 06:19:51 +00004100 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004101 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004102 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004103 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004104 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004105 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004106
Douglas Gregor86d9a522009-09-21 16:56:56 +00004107 // Add the names of overloadable operators.
4108#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4109 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004110 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004111#include "clang/Basic/OperatorKinds.def"
4112
4113 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004114 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004115 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004116 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4117 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004118
4119 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004120 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004121 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004122
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004123 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004124 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004125 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004126}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004127
Douglas Gregor0133f522010-08-28 00:00:50 +00004128void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004129 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004130 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004131 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004132 CXXConstructorDecl *Constructor
4133 = static_cast<CXXConstructorDecl *>(ConstructorD);
4134 if (!Constructor)
4135 return;
4136
Douglas Gregor218937c2011-02-01 19:23:04 +00004137 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004138 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004139 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004140 Results.EnterNewScope();
4141
4142 // Fill in any already-initialized fields or base classes.
4143 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4144 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4145 for (unsigned I = 0; I != NumInitializers; ++I) {
4146 if (Initializers[I]->isBaseInitializer())
4147 InitializedBases.insert(
4148 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4149 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004150 InitializedFields.insert(cast<FieldDecl>(
4151 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004152 }
4153
4154 // Add completions for base classes.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004155 CodeCompletionBuilder Builder(Results.getAllocator(),
4156 Results.getCodeCompletionTUInfo());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004157 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004158 CXXRecordDecl *ClassDecl = Constructor->getParent();
4159 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4160 BaseEnd = ClassDecl->bases_end();
4161 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004162 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4163 SawLastInitializer
4164 = NumInitializers > 0 &&
4165 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4166 Context.hasSameUnqualifiedType(Base->getType(),
4167 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004168 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004169 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004170
Douglas Gregor218937c2011-02-01 19:23:04 +00004171 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004172 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004173 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004174 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4175 Builder.AddPlaceholderChunk("args");
4176 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4177 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004178 SawLastInitializer? CCP_NextInitializer
4179 : CCP_MemberDeclaration));
4180 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004181 }
4182
4183 // Add completions for virtual base classes.
4184 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4185 BaseEnd = ClassDecl->vbases_end();
4186 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004187 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4188 SawLastInitializer
4189 = NumInitializers > 0 &&
4190 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4191 Context.hasSameUnqualifiedType(Base->getType(),
4192 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004193 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004194 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004195
Douglas Gregor218937c2011-02-01 19:23:04 +00004196 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004197 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004198 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004199 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4200 Builder.AddPlaceholderChunk("args");
4201 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4202 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004203 SawLastInitializer? CCP_NextInitializer
4204 : CCP_MemberDeclaration));
4205 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004206 }
4207
4208 // Add completions for members.
4209 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4210 FieldEnd = ClassDecl->field_end();
4211 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004212 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4213 SawLastInitializer
4214 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004215 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
David Blaikie581deb32012-06-06 20:45:41 +00004216 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004217 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004218 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004219
4220 if (!Field->getDeclName())
4221 continue;
4222
Douglas Gregordae68752011-02-01 22:57:45 +00004223 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004224 Field->getIdentifier()->getName()));
4225 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4226 Builder.AddPlaceholderChunk("args");
4227 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4228 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004229 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004230 : CCP_MemberDeclaration,
Douglas Gregorba103062012-03-27 23:34:16 +00004231 CXCursor_MemberRef,
4232 CXAvailability_Available,
David Blaikie581deb32012-06-06 20:45:41 +00004233 *Field));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004234 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004235 }
4236 Results.ExitScope();
4237
Douglas Gregor52779fb2010-09-23 23:01:17 +00004238 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004239 Results.data(), Results.size());
4240}
4241
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004242/// \brief Determine whether this scope denotes a namespace.
4243static bool isNamespaceScope(Scope *S) {
4244 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4245 if (!DC)
4246 return false;
4247
4248 return DC->isFileContext();
4249}
4250
4251void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4252 bool AfterAmpersand) {
4253 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004254 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004255 CodeCompletionContext::CCC_Other);
4256 Results.EnterNewScope();
4257
4258 // Note what has already been captured.
4259 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4260 bool IncludedThis = false;
4261 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4262 CEnd = Intro.Captures.end();
4263 C != CEnd; ++C) {
4264 if (C->Kind == LCK_This) {
4265 IncludedThis = true;
4266 continue;
4267 }
4268
4269 Known.insert(C->Id);
4270 }
4271
4272 // Look for other capturable variables.
4273 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4274 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4275 D != DEnd; ++D) {
4276 VarDecl *Var = dyn_cast<VarDecl>(*D);
4277 if (!Var ||
4278 !Var->hasLocalStorage() ||
4279 Var->hasAttr<BlocksAttr>())
4280 continue;
4281
4282 if (Known.insert(Var->getIdentifier()))
4283 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4284 }
4285 }
4286
4287 // Add 'this', if it would be valid.
4288 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4289 addThisCompletion(*this, Results);
4290
4291 Results.ExitScope();
4292
4293 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4294 Results.data(), Results.size());
4295}
4296
James Dennetta40f7922012-06-14 03:11:41 +00004297/// Macro that optionally prepends an "@" to the string literal passed in via
4298/// Keyword, depending on whether NeedAt is true or false.
4299#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4300
Douglas Gregorbca403c2010-01-13 23:51:12 +00004301static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004302 ResultBuilder &Results,
4303 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004304 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004305 // Since we have an implementation, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004306 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004307
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004308 CodeCompletionBuilder Builder(Results.getAllocator(),
4309 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004310 if (LangOpts.ObjC2) {
4311 // @dynamic
James Dennetta40f7922012-06-14 03:11:41 +00004312 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004313 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4314 Builder.AddPlaceholderChunk("property");
4315 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004316
4317 // @synthesize
James Dennetta40f7922012-06-14 03:11:41 +00004318 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004319 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4320 Builder.AddPlaceholderChunk("property");
4321 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004322 }
4323}
4324
Douglas Gregorbca403c2010-01-13 23:51:12 +00004325static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004326 ResultBuilder &Results,
4327 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004328 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004329
4330 // Since we have an interface or protocol, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004331 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004332
4333 if (LangOpts.ObjC2) {
4334 // @property
James Dennetta40f7922012-06-14 03:11:41 +00004335 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004336
4337 // @required
James Dennetta40f7922012-06-14 03:11:41 +00004338 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004339
4340 // @optional
James Dennetta40f7922012-06-14 03:11:41 +00004341 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004342 }
4343}
4344
Douglas Gregorbca403c2010-01-13 23:51:12 +00004345static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004346 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004347 CodeCompletionBuilder Builder(Results.getAllocator(),
4348 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004349
4350 // @class name ;
James Dennetta40f7922012-06-14 03:11:41 +00004351 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004352 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4353 Builder.AddPlaceholderChunk("name");
4354 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004355
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004356 if (Results.includeCodePatterns()) {
4357 // @interface name
4358 // FIXME: Could introduce the whole pattern, including superclasses and
4359 // such.
James Dennetta40f7922012-06-14 03:11:41 +00004360 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004361 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4362 Builder.AddPlaceholderChunk("class");
4363 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004364
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004365 // @protocol name
James Dennetta40f7922012-06-14 03:11:41 +00004366 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004367 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4368 Builder.AddPlaceholderChunk("protocol");
4369 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004370
4371 // @implementation name
James Dennetta40f7922012-06-14 03:11:41 +00004372 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004373 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4374 Builder.AddPlaceholderChunk("class");
4375 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004376 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004377
4378 // @compatibility_alias name
James Dennetta40f7922012-06-14 03:11:41 +00004379 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004380 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4381 Builder.AddPlaceholderChunk("alias");
4382 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4383 Builder.AddPlaceholderChunk("class");
4384 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004385}
4386
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004387void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004388 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004389 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004390 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004391 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004392 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004393 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004394 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004395 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004396 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004397 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004398 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004399 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004400 HandleCodeCompleteResults(this, CodeCompleter,
4401 CodeCompletionContext::CCC_Other,
4402 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004403}
4404
Douglas Gregorbca403c2010-01-13 23:51:12 +00004405static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004406 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004407 CodeCompletionBuilder Builder(Results.getAllocator(),
4408 Results.getCodeCompletionTUInfo());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004409
4410 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004411 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004412 if (Results.getSema().getLangOpts().CPlusPlus ||
4413 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004414 EncodeType = "const char[]";
Douglas Gregor8ca72082011-10-18 21:20:17 +00004415 Builder.AddResultTypeChunk(EncodeType);
James Dennetta40f7922012-06-14 03:11:41 +00004416 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004417 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4418 Builder.AddPlaceholderChunk("type-name");
4419 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4420 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004421
4422 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004423 Builder.AddResultTypeChunk("Protocol *");
James Dennetta40f7922012-06-14 03:11:41 +00004424 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004425 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4426 Builder.AddPlaceholderChunk("protocol-name");
4427 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4428 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004429
4430 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004431 Builder.AddResultTypeChunk("SEL");
James Dennetta40f7922012-06-14 03:11:41 +00004432 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004433 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4434 Builder.AddPlaceholderChunk("selector");
4435 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4436 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004437
4438 // @"string"
4439 Builder.AddResultTypeChunk("NSString *");
4440 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
4441 Builder.AddPlaceholderChunk("string");
4442 Builder.AddTextChunk("\"");
4443 Results.AddResult(Result(Builder.TakeString()));
4444
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004445 // @[ objects, ... ]
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004446 Builder.AddResultTypeChunk("NSArray *");
James Dennetta40f7922012-06-14 03:11:41 +00004447 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004448 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4449 Builder.AddPlaceholderChunk("objects, ...");
4450 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4451 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4452 Results.AddResult(Result(Builder.TakeString()));
4453
4454 // @{ key : object, ... }
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004455 Builder.AddResultTypeChunk("NSDictionary *");
James Dennetta40f7922012-06-14 03:11:41 +00004456 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004457 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4458 Builder.AddPlaceholderChunk("key");
4459 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4460 Builder.AddChunk(CodeCompletionString::CK_Colon);
4461 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4462 Builder.AddPlaceholderChunk("object, ...");
4463 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4464 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4465 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004466
4467 // @( expression )
4468 Builder.AddResultTypeChunk("id");
4469 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
4470 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4471 Builder.AddPlaceholderChunk("expression");
4472 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4473 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4474 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004475}
4476
Douglas Gregorbca403c2010-01-13 23:51:12 +00004477static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004478 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004479 CodeCompletionBuilder Builder(Results.getAllocator(),
4480 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004481
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004482 if (Results.includeCodePatterns()) {
4483 // @try { statements } @catch ( declaration ) { statements } @finally
4484 // { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004485 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004486 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4487 Builder.AddPlaceholderChunk("statements");
4488 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4489 Builder.AddTextChunk("@catch");
4490 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4491 Builder.AddPlaceholderChunk("parameter");
4492 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4493 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4494 Builder.AddPlaceholderChunk("statements");
4495 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4496 Builder.AddTextChunk("@finally");
4497 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4498 Builder.AddPlaceholderChunk("statements");
4499 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4500 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004501 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004502
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004503 // @throw
James Dennetta40f7922012-06-14 03:11:41 +00004504 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004505 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4506 Builder.AddPlaceholderChunk("expression");
4507 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004508
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004509 if (Results.includeCodePatterns()) {
4510 // @synchronized ( expression ) { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004511 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004512 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4513 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4514 Builder.AddPlaceholderChunk("expression");
4515 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4516 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4517 Builder.AddPlaceholderChunk("statements");
4518 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4519 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004520 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004521}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004522
Douglas Gregorbca403c2010-01-13 23:51:12 +00004523static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004524 ResultBuilder &Results,
4525 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004526 typedef CodeCompletionResult Result;
James Dennetta40f7922012-06-14 03:11:41 +00004527 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
4528 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
4529 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004530 if (LangOpts.ObjC2)
James Dennetta40f7922012-06-14 03:11:41 +00004531 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004532}
4533
4534void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004535 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004536 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004537 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004538 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004539 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004540 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004541 HandleCodeCompleteResults(this, CodeCompleter,
4542 CodeCompletionContext::CCC_Other,
4543 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004544}
4545
4546void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004547 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004548 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004549 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004550 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004551 AddObjCStatementResults(Results, false);
4552 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004553 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004554 HandleCodeCompleteResults(this, CodeCompleter,
4555 CodeCompletionContext::CCC_Other,
4556 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004557}
4558
4559void Sema::CodeCompleteObjCAtExpression(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 Gregor9a0c85e2009-12-07 09:51:25 +00004563 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004564 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004565 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004566 HandleCodeCompleteResults(this, CodeCompleter,
4567 CodeCompletionContext::CCC_Other,
4568 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004569}
4570
Douglas Gregor988358f2009-11-19 00:14:45 +00004571/// \brief Determine whether the addition of the given flag to an Objective-C
4572/// property's attributes will cause a conflict.
4573static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4574 // Check if we've already added this flag.
4575 if (Attributes & NewFlag)
4576 return true;
4577
4578 Attributes |= NewFlag;
4579
4580 // Check for collisions with "readonly".
4581 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4582 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4583 ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004584 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004585 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004586 ObjCDeclSpec::DQ_PR_retain |
4587 ObjCDeclSpec::DQ_PR_strong)))
Douglas Gregor988358f2009-11-19 00:14:45 +00004588 return true;
4589
John McCallf85e1932011-06-15 23:02:42 +00004590 // Check for more than one of { assign, copy, retain, strong }.
Douglas Gregor988358f2009-11-19 00:14:45 +00004591 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004592 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004593 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004594 ObjCDeclSpec::DQ_PR_retain|
4595 ObjCDeclSpec::DQ_PR_strong);
Douglas Gregor988358f2009-11-19 00:14:45 +00004596 if (AssignCopyRetMask &&
4597 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004598 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004599 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004600 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
4601 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
Douglas Gregor988358f2009-11-19 00:14:45 +00004602 return true;
4603
4604 return false;
4605}
4606
Douglas Gregora93b1082009-11-18 23:08:07 +00004607void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004608 if (!CodeCompleter)
4609 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004610
Steve Naroffece8e712009-10-08 21:55:05 +00004611 unsigned Attributes = ODS.getPropertyAttributes();
4612
John McCall0a2c5e22010-08-25 06:19:51 +00004613 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004614 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004615 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004616 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004617 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004618 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004619 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004620 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004621 Results.AddResult(CodeCompletionResult("assign"));
John McCallf85e1932011-06-15 23:02:42 +00004622 if (!ObjCPropertyFlagConflicts(Attributes,
4623 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4624 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004625 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004626 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004627 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004628 Results.AddResult(CodeCompletionResult("retain"));
John McCallf85e1932011-06-15 23:02:42 +00004629 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4630 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004631 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004632 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004633 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004634 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004635 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4636 Results.AddResult(CodeCompletionResult("atomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004637 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004638 CodeCompletionBuilder Setter(Results.getAllocator(),
4639 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004640 Setter.AddTypedTextChunk("setter");
4641 Setter.AddTextChunk(" = ");
4642 Setter.AddPlaceholderChunk("method");
4643 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004644 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004645 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004646 CodeCompletionBuilder Getter(Results.getAllocator(),
4647 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004648 Getter.AddTypedTextChunk("getter");
4649 Getter.AddTextChunk(" = ");
4650 Getter.AddPlaceholderChunk("method");
4651 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004652 }
Steve Naroffece8e712009-10-08 21:55:05 +00004653 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004654 HandleCodeCompleteResults(this, CodeCompleter,
4655 CodeCompletionContext::CCC_Other,
4656 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004657}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004658
Douglas Gregor4ad96852009-11-19 07:41:15 +00004659/// \brief Descripts the kind of Objective-C method that we want to find
4660/// via code completion.
4661enum ObjCMethodKind {
Dmitri Gribenko49fdccb2012-06-08 23:13:42 +00004662 MK_Any, ///< Any kind of method, provided it means other specified criteria.
4663 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
4664 MK_OneArgSelector ///< One-argument selector.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004665};
4666
Douglas Gregor458433d2010-08-26 15:07:07 +00004667static bool isAcceptableObjCSelector(Selector Sel,
4668 ObjCMethodKind WantKind,
4669 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004670 unsigned NumSelIdents,
4671 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004672 if (NumSelIdents > Sel.getNumArgs())
4673 return false;
4674
4675 switch (WantKind) {
4676 case MK_Any: break;
4677 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4678 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4679 }
4680
Douglas Gregorcf544262010-11-17 21:36:08 +00004681 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4682 return false;
4683
Douglas Gregor458433d2010-08-26 15:07:07 +00004684 for (unsigned I = 0; I != NumSelIdents; ++I)
4685 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4686 return false;
4687
4688 return true;
4689}
4690
Douglas Gregor4ad96852009-11-19 07:41:15 +00004691static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4692 ObjCMethodKind WantKind,
4693 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004694 unsigned NumSelIdents,
4695 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004696 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004697 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004698}
Douglas Gregord36adf52010-09-16 16:06:31 +00004699
4700namespace {
4701 /// \brief A set of selectors, which is used to avoid introducing multiple
4702 /// completions with the same selector into the result set.
4703 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4704}
4705
Douglas Gregor36ecb042009-11-17 23:22:23 +00004706/// \brief Add all of the Objective-C methods in the given Objective-C
4707/// container to the set of results.
4708///
4709/// The container will be a class, protocol, category, or implementation of
4710/// any of the above. This mether will recurse to include methods from
4711/// the superclasses of classes along with their categories, protocols, and
4712/// implementations.
4713///
4714/// \param Container the container in which we'll look to find methods.
4715///
James Dennetta40f7922012-06-14 03:11:41 +00004716/// \param WantInstanceMethods Whether to add instance methods (only); if
4717/// false, this routine will add factory methods (only).
Douglas Gregor36ecb042009-11-17 23:22:23 +00004718///
4719/// \param CurContext the context in which we're performing the lookup that
4720/// finds methods.
4721///
Douglas Gregorcf544262010-11-17 21:36:08 +00004722/// \param AllowSameLength Whether we allow a method to be added to the list
4723/// when it has the same number of parameters as we have selector identifiers.
4724///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004725/// \param Results the structure into which we'll add results.
4726static void AddObjCMethods(ObjCContainerDecl *Container,
4727 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004728 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004729 IdentifierInfo **SelIdents,
4730 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004731 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004732 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004733 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004734 ResultBuilder &Results,
4735 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004736 typedef CodeCompletionResult Result;
Douglas Gregorb92a4082012-06-12 13:44:08 +00004737 Container = getContainerDef(Container);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004738 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4739 MEnd = Container->meth_end();
4740 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00004741 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004742 // Check whether the selector identifiers we've been given are a
4743 // subset of the identifiers for this particular method.
David Blaikie581deb32012-06-06 20:45:41 +00004744 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004745 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004746 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004747
David Blaikie262bc182012-04-30 02:36:29 +00004748 if (!Selectors.insert(M->getSelector()))
Douglas Gregord36adf52010-09-16 16:06:31 +00004749 continue;
4750
David Blaikie581deb32012-06-06 20:45:41 +00004751 Result R = Result(*M, 0);
Douglas Gregord3c68542009-11-19 01:08:35 +00004752 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004753 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004754 if (!InOriginalClass)
4755 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004756 Results.MaybeAddResult(R, CurContext);
4757 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004758 }
4759
Douglas Gregore396c7b2010-09-16 15:34:59 +00004760 // Visit the protocols of protocols.
4761 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004762 if (Protocol->hasDefinition()) {
4763 const ObjCList<ObjCProtocolDecl> &Protocols
4764 = Protocol->getReferencedProtocols();
4765 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4766 E = Protocols.end();
4767 I != E; ++I)
4768 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4769 NumSelIdents, CurContext, Selectors, AllowSameLength,
4770 Results, false);
4771 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004772 }
4773
Douglas Gregor36ecb042009-11-17 23:22:23 +00004774 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004775 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004776 return;
4777
4778 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004779 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4780 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004781 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004782 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004783 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004784
4785 // Add methods in categories.
4786 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4787 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004788 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004789 NumSelIdents, CurContext, Selectors, AllowSameLength,
4790 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004791
4792 // Add a categories protocol methods.
4793 const ObjCList<ObjCProtocolDecl> &Protocols
4794 = CatDecl->getReferencedProtocols();
4795 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4796 E = Protocols.end();
4797 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004798 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004799 NumSelIdents, CurContext, Selectors, AllowSameLength,
4800 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004801
4802 // Add methods in category implementations.
4803 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004804 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004805 NumSelIdents, CurContext, Selectors, AllowSameLength,
4806 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004807 }
4808
4809 // Add methods in superclass.
4810 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004811 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004812 SelIdents, NumSelIdents, CurContext, Selectors,
4813 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004814
4815 // Add methods in our implementation, if any.
4816 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004817 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004818 NumSelIdents, CurContext, Selectors, AllowSameLength,
4819 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004820}
4821
4822
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004823void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004824 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004825
4826 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004827 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004828 if (!Class) {
4829 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004830 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004831 Class = Category->getClassInterface();
4832
4833 if (!Class)
4834 return;
4835 }
4836
4837 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004838 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004839 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004840 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004841 Results.EnterNewScope();
4842
Douglas Gregord36adf52010-09-16 16:06:31 +00004843 VisitedSelectorSet Selectors;
4844 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004845 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004846 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004847 HandleCodeCompleteResults(this, CodeCompleter,
4848 CodeCompletionContext::CCC_Other,
4849 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004850}
4851
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004852void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004853 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004854
4855 // Try to find the interface where setters might live.
4856 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004857 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004858 if (!Class) {
4859 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004860 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004861 Class = Category->getClassInterface();
4862
4863 if (!Class)
4864 return;
4865 }
4866
4867 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004868 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004869 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004870 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004871 Results.EnterNewScope();
4872
Douglas Gregord36adf52010-09-16 16:06:31 +00004873 VisitedSelectorSet Selectors;
4874 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004875 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004876
4877 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004878 HandleCodeCompleteResults(this, CodeCompleter,
4879 CodeCompletionContext::CCC_Other,
4880 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004881}
4882
Douglas Gregorafc45782011-02-15 22:19:42 +00004883void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4884 bool IsParameter) {
John McCall0a2c5e22010-08-25 06:19:51 +00004885 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004886 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004887 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004888 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004889 Results.EnterNewScope();
4890
4891 // Add context-sensitive, Objective-C parameter-passing keywords.
4892 bool AddedInOut = false;
4893 if ((DS.getObjCDeclQualifier() &
4894 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4895 Results.AddResult("in");
4896 Results.AddResult("inout");
4897 AddedInOut = true;
4898 }
4899 if ((DS.getObjCDeclQualifier() &
4900 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4901 Results.AddResult("out");
4902 if (!AddedInOut)
4903 Results.AddResult("inout");
4904 }
4905 if ((DS.getObjCDeclQualifier() &
4906 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4907 ObjCDeclSpec::DQ_Oneway)) == 0) {
4908 Results.AddResult("bycopy");
4909 Results.AddResult("byref");
4910 Results.AddResult("oneway");
4911 }
4912
Douglas Gregorafc45782011-02-15 22:19:42 +00004913 // If we're completing the return type of an Objective-C method and the
4914 // identifier IBAction refers to a macro, provide a completion item for
4915 // an action, e.g.,
4916 // IBAction)<#selector#>:(id)sender
4917 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4918 Context.Idents.get("IBAction").hasMacroDefinition()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004919 CodeCompletionBuilder Builder(Results.getAllocator(),
4920 Results.getCodeCompletionTUInfo(),
4921 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorafc45782011-02-15 22:19:42 +00004922 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004923 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004924 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004925 Builder.AddChunk(CodeCompletionString::CK_Colon);
4926 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004927 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004928 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004929 Builder.AddTextChunk("sender");
4930 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4931 }
4932
Douglas Gregord32b0222010-08-24 01:06:58 +00004933 // Add various builtin type names and specifiers.
4934 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4935 Results.ExitScope();
4936
4937 // Add the various type names
4938 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4939 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4940 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4941 CodeCompleter->includeGlobals());
4942
4943 if (CodeCompleter->includeMacros())
4944 AddMacroResults(PP, Results);
4945
4946 HandleCodeCompleteResults(this, CodeCompleter,
4947 CodeCompletionContext::CCC_Type,
4948 Results.data(), Results.size());
4949}
4950
Douglas Gregor22f56992010-04-06 19:22:33 +00004951/// \brief When we have an expression with type "id", we may assume
4952/// that it has some more-specific class type based on knowledge of
4953/// common uses of Objective-C. This routine returns that class type,
4954/// or NULL if no better result could be determined.
4955static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004956 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004957 if (!Msg)
4958 return 0;
4959
4960 Selector Sel = Msg->getSelector();
4961 if (Sel.isNull())
4962 return 0;
4963
4964 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4965 if (!Id)
4966 return 0;
4967
4968 ObjCMethodDecl *Method = Msg->getMethodDecl();
4969 if (!Method)
4970 return 0;
4971
4972 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004973 ObjCInterfaceDecl *IFace = 0;
4974 switch (Msg->getReceiverKind()) {
4975 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004976 if (const ObjCObjectType *ObjType
4977 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4978 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004979 break;
4980
4981 case ObjCMessageExpr::Instance: {
4982 QualType T = Msg->getInstanceReceiver()->getType();
4983 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4984 IFace = Ptr->getInterfaceDecl();
4985 break;
4986 }
4987
4988 case ObjCMessageExpr::SuperInstance:
4989 case ObjCMessageExpr::SuperClass:
4990 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00004991 }
4992
4993 if (!IFace)
4994 return 0;
4995
4996 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4997 if (Method->isInstanceMethod())
4998 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4999 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00005000 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00005001 .Case("autorelease", IFace)
5002 .Case("copy", IFace)
5003 .Case("copyWithZone", IFace)
5004 .Case("mutableCopy", IFace)
5005 .Case("mutableCopyWithZone", IFace)
5006 .Case("awakeFromCoder", IFace)
5007 .Case("replacementObjectFromCoder", IFace)
5008 .Case("class", IFace)
5009 .Case("classForCoder", IFace)
5010 .Case("superclass", Super)
5011 .Default(0);
5012
5013 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5014 .Case("new", IFace)
5015 .Case("alloc", IFace)
5016 .Case("allocWithZone", IFace)
5017 .Case("class", IFace)
5018 .Case("superclass", Super)
5019 .Default(0);
5020}
5021
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005022// Add a special completion for a message send to "super", which fills in the
5023// most likely case of forwarding all of our arguments to the superclass
5024// function.
5025///
5026/// \param S The semantic analysis object.
5027///
5028/// \param S NeedSuperKeyword Whether we need to prefix this completion with
5029/// the "super" keyword. Otherwise, we just need to provide the arguments.
5030///
5031/// \param SelIdents The identifiers in the selector that have already been
5032/// provided as arguments for a send to "super".
5033///
5034/// \param NumSelIdents The number of identifiers in \p SelIdents.
5035///
5036/// \param Results The set of results to augment.
5037///
5038/// \returns the Objective-C method declaration that would be invoked by
5039/// this "super" completion. If NULL, no completion was added.
5040static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
5041 IdentifierInfo **SelIdents,
5042 unsigned NumSelIdents,
5043 ResultBuilder &Results) {
5044 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5045 if (!CurMethod)
5046 return 0;
5047
5048 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5049 if (!Class)
5050 return 0;
5051
5052 // Try to find a superclass method with the same selector.
5053 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00005054 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5055 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005056 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5057 CurMethod->isInstanceMethod());
5058
Douglas Gregor78bcd912011-02-16 00:51:18 +00005059 // Check in categories or class extensions.
5060 if (!SuperMethod) {
5061 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5062 Category = Category->getNextClassCategory())
5063 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
5064 CurMethod->isInstanceMethod())))
5065 break;
5066 }
5067 }
5068
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005069 if (!SuperMethod)
5070 return 0;
5071
5072 // Check whether the superclass method has the same signature.
5073 if (CurMethod->param_size() != SuperMethod->param_size() ||
5074 CurMethod->isVariadic() != SuperMethod->isVariadic())
5075 return 0;
5076
5077 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5078 CurPEnd = CurMethod->param_end(),
5079 SuperP = SuperMethod->param_begin();
5080 CurP != CurPEnd; ++CurP, ++SuperP) {
5081 // Make sure the parameter types are compatible.
5082 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5083 (*SuperP)->getType()))
5084 return 0;
5085
5086 // Make sure we have a parameter name to forward!
5087 if (!(*CurP)->getIdentifier())
5088 return 0;
5089 }
5090
5091 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005092 CodeCompletionBuilder Builder(Results.getAllocator(),
5093 Results.getCodeCompletionTUInfo());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005094
5095 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005096 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5097 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005098
5099 // If we need the "super" keyword, add it (plus some spacing).
5100 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005101 Builder.AddTypedTextChunk("super");
5102 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005103 }
5104
5105 Selector Sel = CurMethod->getSelector();
5106 if (Sel.isUnarySelector()) {
5107 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005108 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005109 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005110 else
Douglas Gregordae68752011-02-01 22:57:45 +00005111 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005112 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005113 } else {
5114 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5115 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5116 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005117 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005118
5119 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005120 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005121 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005122 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005123 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005124 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005125 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005126 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005127 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005128 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005129 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005130 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005131 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005132 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005133 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005134 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005135 }
5136 }
5137 }
5138
Douglas Gregorba103062012-03-27 23:34:16 +00005139 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5140 CCP_SuperCompletion));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005141 return SuperMethod;
5142}
5143
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005144void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005145 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005146 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005147 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005148 CodeCompletionContext::CCC_ObjCMessageReceiver,
David Blaikie4e4d0842012-03-11 07:00:24 +00005149 getLangOpts().CPlusPlus0x
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005150 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5151 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005152
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005153 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5154 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005155 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5156 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005157
5158 // If we are in an Objective-C method inside a class that has a superclass,
5159 // add "super" as an option.
5160 if (ObjCMethodDecl *Method = getCurMethodDecl())
5161 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005162 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005163 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005164
5165 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5166 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005167
David Blaikie4e4d0842012-03-11 07:00:24 +00005168 if (getLangOpts().CPlusPlus0x)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005169 addThisCompletion(*this, Results);
5170
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005171 Results.ExitScope();
5172
5173 if (CodeCompleter->includeMacros())
5174 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005175 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005176 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005177
5178}
5179
Douglas Gregor2725ca82010-04-21 19:57:20 +00005180void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5181 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005182 unsigned NumSelIdents,
5183 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005184 ObjCInterfaceDecl *CDecl = 0;
5185 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5186 // Figure out which interface we're in.
5187 CDecl = CurMethod->getClassInterface();
5188 if (!CDecl)
5189 return;
5190
5191 // Find the superclass of this class.
5192 CDecl = CDecl->getSuperClass();
5193 if (!CDecl)
5194 return;
5195
5196 if (CurMethod->isInstanceMethod()) {
5197 // We are inside an instance method, which means that the message
5198 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005199 // current object.
5200 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005201 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005202 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005203 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005204 }
5205
5206 // Fall through to send to the superclass in CDecl.
5207 } else {
5208 // "super" may be the name of a type or variable. Figure out which
5209 // it is.
5210 IdentifierInfo *Super = &Context.Idents.get("super");
5211 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5212 LookupOrdinaryName);
5213 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5214 // "super" names an interface. Use it.
5215 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005216 if (const ObjCObjectType *Iface
5217 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5218 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005219 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5220 // "super" names an unresolved type; we can't be more specific.
5221 } else {
5222 // Assume that "super" names some kind of value and parse that way.
5223 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005224 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005225 UnqualifiedId id;
5226 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005227 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5228 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005229 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005230 SelIdents, NumSelIdents,
5231 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005232 }
5233
5234 // Fall through
5235 }
5236
John McCallb3d87482010-08-24 05:47:05 +00005237 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005238 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005239 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005240 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005241 NumSelIdents, AtArgumentExpression,
5242 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005243}
5244
Douglas Gregorb9d77572010-09-21 00:03:25 +00005245/// \brief Given a set of code-completion results for the argument of a message
5246/// send, determine the preferred type (if any) for that argument expression.
5247static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5248 unsigned NumSelIdents) {
5249 typedef CodeCompletionResult Result;
5250 ASTContext &Context = Results.getSema().Context;
5251
5252 QualType PreferredType;
5253 unsigned BestPriority = CCP_Unlikely * 2;
5254 Result *ResultsData = Results.data();
5255 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5256 Result &R = ResultsData[I];
5257 if (R.Kind == Result::RK_Declaration &&
5258 isa<ObjCMethodDecl>(R.Declaration)) {
5259 if (R.Priority <= BestPriority) {
5260 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5261 if (NumSelIdents <= Method->param_size()) {
5262 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5263 ->getType();
5264 if (R.Priority < BestPriority || PreferredType.isNull()) {
5265 BestPriority = R.Priority;
5266 PreferredType = MyPreferredType;
5267 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5268 MyPreferredType)) {
5269 PreferredType = QualType();
5270 }
5271 }
5272 }
5273 }
5274 }
5275
5276 return PreferredType;
5277}
5278
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005279static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5280 ParsedType Receiver,
5281 IdentifierInfo **SelIdents,
5282 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005283 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005284 bool IsSuper,
5285 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005286 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005287 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005288
Douglas Gregor24a069f2009-11-17 17:59:40 +00005289 // If the given name refers to an interface type, retrieve the
5290 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005291 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005292 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005293 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005294 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5295 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005296 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005297
Douglas Gregor36ecb042009-11-17 23:22:23 +00005298 // Add all of the factory methods in this Objective-C class, its protocols,
5299 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005300 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005301
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005302 // If this is a send-to-super, try to add the special "super" send
5303 // completion.
5304 if (IsSuper) {
5305 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005306 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5307 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005308 Results.Ignore(SuperMethod);
5309 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005310
Douglas Gregor265f7492010-08-27 15:29:55 +00005311 // If we're inside an Objective-C method definition, prefer its selector to
5312 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005313 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005314 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005315
Douglas Gregord36adf52010-09-16 16:06:31 +00005316 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005317 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005318 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005319 SemaRef.CurContext, Selectors, AtArgumentExpression,
5320 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005321 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005322 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005323
Douglas Gregor719770d2010-04-06 17:30:22 +00005324 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005325 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005326 if (SemaRef.ExternalSource) {
5327 for (uint32_t I = 0,
5328 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005329 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005330 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5331 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005332 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005333
5334 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005335 }
5336 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005337
5338 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5339 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005340 M != MEnd; ++M) {
5341 for (ObjCMethodList *MethList = &M->second.second;
5342 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005343 MethList = MethList->Next) {
5344 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5345 NumSelIdents))
5346 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005347
Douglas Gregor13438f92010-04-06 16:40:00 +00005348 Result R(MethList->Method, 0);
5349 R.StartParameter = NumSelIdents;
5350 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005351 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005352 }
5353 }
5354 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005355
5356 Results.ExitScope();
5357}
Douglas Gregor13438f92010-04-06 16:40:00 +00005358
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005359void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5360 IdentifierInfo **SelIdents,
5361 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005362 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005363 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005364
5365 QualType T = this->GetTypeFromParser(Receiver);
5366
Douglas Gregor218937c2011-02-01 19:23:04 +00005367 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005368 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005369 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005370 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005371
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005372 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5373 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005374
5375 // If we're actually at the argument expression (rather than prior to the
5376 // selector), we're actually performing code completion for an expression.
5377 // Determine whether we have a single, best method. If so, we can
5378 // code-complete the expression using the corresponding parameter type as
5379 // our preferred type, improving completion results.
5380 if (AtArgumentExpression) {
5381 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005382 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005383 if (PreferredType.isNull())
5384 CodeCompleteOrdinaryName(S, PCC_Expression);
5385 else
5386 CodeCompleteExpression(S, PreferredType);
5387 return;
5388 }
5389
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005390 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005391 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005392 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005393}
5394
Richard Trieuf81e5a92011-09-09 02:00:50 +00005395void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005396 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005397 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005398 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005399 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005400 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005401
5402 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005403
Douglas Gregor36ecb042009-11-17 23:22:23 +00005404 // If necessary, apply function/array conversion to the receiver.
5405 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005406 if (RecExpr) {
5407 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5408 if (Conv.isInvalid()) // conversion failed. bail.
5409 return;
5410 RecExpr = Conv.take();
5411 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005412 QualType ReceiverType = RecExpr? RecExpr->getType()
5413 : Super? Context.getObjCObjectPointerType(
5414 Context.getObjCInterfaceType(Super))
5415 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005416
Douglas Gregorda892642010-11-08 21:12:30 +00005417 // If we're messaging an expression with type "id" or "Class", check
5418 // whether we know something special about the receiver that allows
5419 // us to assume a more-specific receiver type.
5420 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5421 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5422 if (ReceiverType->isObjCClassType())
5423 return CodeCompleteObjCClassMessage(S,
5424 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5425 SelIdents, NumSelIdents,
5426 AtArgumentExpression, Super);
5427
5428 ReceiverType = Context.getObjCObjectPointerType(
5429 Context.getObjCInterfaceType(IFace));
5430 }
5431
Douglas Gregor36ecb042009-11-17 23:22:23 +00005432 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005433 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005434 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005435 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005436 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005437
Douglas Gregor36ecb042009-11-17 23:22:23 +00005438 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005439
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005440 // If this is a send-to-super, try to add the special "super" send
5441 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005442 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005443 if (ObjCMethodDecl *SuperMethod
5444 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5445 Results))
5446 Results.Ignore(SuperMethod);
5447 }
5448
Douglas Gregor265f7492010-08-27 15:29:55 +00005449 // If we're inside an Objective-C method definition, prefer its selector to
5450 // others.
5451 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5452 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005453
Douglas Gregord36adf52010-09-16 16:06:31 +00005454 // Keep track of the selectors we've already added.
5455 VisitedSelectorSet Selectors;
5456
Douglas Gregorf74a4192009-11-18 00:06:18 +00005457 // Handle messages to Class. This really isn't a message to an instance
5458 // method, so we treat it the same way we would treat a message send to a
5459 // class method.
5460 if (ReceiverType->isObjCClassType() ||
5461 ReceiverType->isObjCQualifiedClassType()) {
5462 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5463 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005464 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005465 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005466 }
5467 }
5468 // Handle messages to a qualified ID ("id<foo>").
5469 else if (const ObjCObjectPointerType *QualID
5470 = ReceiverType->getAsObjCQualifiedIdType()) {
5471 // Search protocols for instance methods.
5472 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5473 E = QualID->qual_end();
5474 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005475 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005476 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005477 }
5478 // Handle messages to a pointer to interface type.
5479 else if (const ObjCObjectPointerType *IFacePtr
5480 = ReceiverType->getAsObjCInterfacePointerType()) {
5481 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005482 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005483 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5484 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005485
5486 // Search protocols for instance methods.
5487 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5488 E = IFacePtr->qual_end();
5489 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005490 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005491 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005492 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005493 // Handle messages to "id".
5494 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005495 // We're messaging "id", so provide all instance methods we know
5496 // about as code-completion results.
5497
5498 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005499 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005500 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005501 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5502 I != N; ++I) {
5503 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005504 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005505 continue;
5506
Sebastian Redldb9d2142010-08-02 23:18:59 +00005507 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005508 }
5509 }
5510
Sebastian Redldb9d2142010-08-02 23:18:59 +00005511 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5512 MEnd = MethodPool.end();
5513 M != MEnd; ++M) {
5514 for (ObjCMethodList *MethList = &M->second.first;
5515 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005516 MethList = MethList->Next) {
5517 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5518 NumSelIdents))
5519 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005520
5521 if (!Selectors.insert(MethList->Method->getSelector()))
5522 continue;
5523
Douglas Gregor13438f92010-04-06 16:40:00 +00005524 Result R(MethList->Method, 0);
5525 R.StartParameter = NumSelIdents;
5526 R.AllParametersAreInformative = false;
5527 Results.MaybeAddResult(R, CurContext);
5528 }
5529 }
5530 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005531 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005532
5533
5534 // If we're actually at the argument expression (rather than prior to the
5535 // selector), we're actually performing code completion for an expression.
5536 // Determine whether we have a single, best method. If so, we can
5537 // code-complete the expression using the corresponding parameter type as
5538 // our preferred type, improving completion results.
5539 if (AtArgumentExpression) {
5540 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5541 NumSelIdents);
5542 if (PreferredType.isNull())
5543 CodeCompleteOrdinaryName(S, PCC_Expression);
5544 else
5545 CodeCompleteExpression(S, PreferredType);
5546 return;
5547 }
5548
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005549 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005550 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005551 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005552}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005553
Douglas Gregorfb629412010-08-23 21:17:50 +00005554void Sema::CodeCompleteObjCForCollection(Scope *S,
5555 DeclGroupPtrTy IterationVar) {
5556 CodeCompleteExpressionData Data;
5557 Data.ObjCCollection = true;
5558
5559 if (IterationVar.getAsOpaquePtr()) {
5560 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5561 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5562 if (*I)
5563 Data.IgnoreDecls.push_back(*I);
5564 }
5565 }
5566
5567 CodeCompleteExpression(S, Data);
5568}
5569
Douglas Gregor458433d2010-08-26 15:07:07 +00005570void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5571 unsigned NumSelIdents) {
5572 // If we have an external source, load the entire class method
5573 // pool from the AST file.
5574 if (ExternalSource) {
5575 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5576 I != N; ++I) {
5577 Selector Sel = ExternalSource->GetExternalSelector(I);
5578 if (Sel.isNull() || MethodPool.count(Sel))
5579 continue;
5580
5581 ReadMethodPool(Sel);
5582 }
5583 }
5584
Douglas Gregor218937c2011-02-01 19:23:04 +00005585 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005586 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005587 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005588 Results.EnterNewScope();
5589 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5590 MEnd = MethodPool.end();
5591 M != MEnd; ++M) {
5592
5593 Selector Sel = M->first;
5594 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5595 continue;
5596
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005597 CodeCompletionBuilder Builder(Results.getAllocator(),
5598 Results.getCodeCompletionTUInfo());
Douglas Gregor458433d2010-08-26 15:07:07 +00005599 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005600 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005601 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005602 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005603 continue;
5604 }
5605
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005606 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005607 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005608 if (I == NumSelIdents) {
5609 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005610 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005611 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005612 Accumulator.clear();
5613 }
5614 }
5615
Benjamin Kramera0651c52011-07-26 16:59:25 +00005616 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005617 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005618 }
Douglas Gregordae68752011-02-01 22:57:45 +00005619 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005620 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005621 }
5622 Results.ExitScope();
5623
5624 HandleCodeCompleteResults(this, CodeCompleter,
5625 CodeCompletionContext::CCC_SelectorName,
5626 Results.data(), Results.size());
5627}
5628
Douglas Gregor55385fe2009-11-18 04:19:12 +00005629/// \brief Add all of the protocol declarations that we find in the given
5630/// (translation unit) context.
5631static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005632 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005633 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005634 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005635
5636 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5637 DEnd = Ctx->decls_end();
5638 D != DEnd; ++D) {
5639 // Record any protocols we find.
5640 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005641 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005642 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005643 }
5644}
5645
5646void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5647 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005648 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005649 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005650 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005651
Douglas Gregor70c23352010-12-09 21:44:02 +00005652 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5653 Results.EnterNewScope();
5654
5655 // Tell the result set to ignore all of the protocols we have
5656 // already seen.
5657 // FIXME: This doesn't work when caching code-completion results.
5658 for (unsigned I = 0; I != NumProtocols; ++I)
5659 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5660 Protocols[I].second))
5661 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005662
Douglas Gregor70c23352010-12-09 21:44:02 +00005663 // Add all protocols.
5664 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5665 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005666
Douglas Gregor70c23352010-12-09 21:44:02 +00005667 Results.ExitScope();
5668 }
5669
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005670 HandleCodeCompleteResults(this, CodeCompleter,
5671 CodeCompletionContext::CCC_ObjCProtocolName,
5672 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005673}
5674
5675void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
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 Gregor083128f2009-11-18 04:49:41 +00005679
Douglas Gregor70c23352010-12-09 21:44:02 +00005680 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5681 Results.EnterNewScope();
5682
5683 // Add all protocols.
5684 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5685 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005686
Douglas Gregor70c23352010-12-09 21:44:02 +00005687 Results.ExitScope();
5688 }
5689
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005690 HandleCodeCompleteResults(this, CodeCompleter,
5691 CodeCompletionContext::CCC_ObjCProtocolName,
5692 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005693}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005694
5695/// \brief Add all of the Objective-C interface declarations that we find in
5696/// the given (translation unit) context.
5697static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5698 bool OnlyForwardDeclarations,
5699 bool OnlyUnimplemented,
5700 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005701 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005702
5703 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5704 DEnd = Ctx->decls_end();
5705 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005706 // Record any interfaces we find.
5707 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005708 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005709 (!OnlyUnimplemented || !Class->getImplementation()))
5710 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005711 }
5712}
5713
5714void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005715 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005716 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005717 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005718 Results.EnterNewScope();
5719
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005720 if (CodeCompleter->includeGlobals()) {
5721 // Add all classes.
5722 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5723 false, Results);
5724 }
5725
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005726 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005727
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005728 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005729 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005730 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005731}
5732
Douglas Gregorc83c6872010-04-15 22:33:43 +00005733void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5734 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005735 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005736 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005737 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005738 Results.EnterNewScope();
5739
5740 // Make sure that we ignore the class we're currently defining.
5741 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005742 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005743 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005744 Results.Ignore(CurClass);
5745
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005746 if (CodeCompleter->includeGlobals()) {
5747 // Add all classes.
5748 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5749 false, Results);
5750 }
5751
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005752 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005753
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005754 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005755 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005756 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005757}
5758
5759void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005760 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005761 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005762 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005763 Results.EnterNewScope();
5764
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005765 if (CodeCompleter->includeGlobals()) {
5766 // Add all unimplemented classes.
5767 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5768 true, Results);
5769 }
5770
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005771 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005772
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005773 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005774 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005775 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005776}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005777
5778void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005779 IdentifierInfo *ClassName,
5780 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005781 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005782
Douglas Gregor218937c2011-02-01 19:23:04 +00005783 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005784 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005785 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005786
5787 // Ignore any categories we find that have already been implemented by this
5788 // interface.
5789 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5790 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005791 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005792 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5793 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5794 Category = Category->getNextClassCategory())
5795 CategoryNames.insert(Category->getIdentifier());
5796
5797 // Add all of the categories we know about.
5798 Results.EnterNewScope();
5799 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5800 for (DeclContext::decl_iterator D = TU->decls_begin(),
5801 DEnd = TU->decls_end();
5802 D != DEnd; ++D)
5803 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5804 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005805 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005806 Results.ExitScope();
5807
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005808 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005809 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005810 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005811}
5812
5813void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005814 IdentifierInfo *ClassName,
5815 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005816 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005817
5818 // Find the corresponding interface. If we couldn't find the interface, the
5819 // program itself is ill-formed. However, we'll try to be helpful still by
5820 // providing the list of all of the categories we know about.
5821 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005822 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005823 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5824 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005825 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005826
Douglas Gregor218937c2011-02-01 19:23:04 +00005827 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005828 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005829 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005830
5831 // Add all of the categories that have have corresponding interface
5832 // declarations in this class and any of its superclasses, except for
5833 // already-implemented categories in the class itself.
5834 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5835 Results.EnterNewScope();
5836 bool IgnoreImplemented = true;
5837 while (Class) {
5838 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5839 Category = Category->getNextClassCategory())
5840 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5841 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005842 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005843
5844 Class = Class->getSuperClass();
5845 IgnoreImplemented = false;
5846 }
5847 Results.ExitScope();
5848
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005849 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005850 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005851 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005852}
Douglas Gregor322328b2009-11-18 22:32:06 +00005853
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005854void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005855 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005856 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005857 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005858 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005859
5860 // Figure out where this @synthesize lives.
5861 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005862 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005863 if (!Container ||
5864 (!isa<ObjCImplementationDecl>(Container) &&
5865 !isa<ObjCCategoryImplDecl>(Container)))
5866 return;
5867
5868 // Ignore any properties that have already been implemented.
Douglas Gregorb92a4082012-06-12 13:44:08 +00005869 Container = getContainerDef(Container);
5870 for (DeclContext::decl_iterator D = Container->decls_begin(),
Douglas Gregor322328b2009-11-18 22:32:06 +00005871 DEnd = Container->decls_end();
5872 D != DEnd; ++D)
5873 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5874 Results.Ignore(PropertyImpl->getPropertyDecl());
5875
5876 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005877 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005878 Results.EnterNewScope();
5879 if (ObjCImplementationDecl *ClassImpl
5880 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005881 AddObjCProperties(ClassImpl->getClassInterface(), false,
5882 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005883 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005884 else
5885 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005886 false, /*AllowNullaryMethods=*/false, CurContext,
5887 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005888 Results.ExitScope();
5889
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005890 HandleCodeCompleteResults(this, CodeCompleter,
5891 CodeCompletionContext::CCC_Other,
5892 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005893}
5894
5895void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005896 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005897 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005898 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005899 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005900 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005901
5902 // Figure out where this @synthesize lives.
5903 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005904 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005905 if (!Container ||
5906 (!isa<ObjCImplementationDecl>(Container) &&
5907 !isa<ObjCCategoryImplDecl>(Container)))
5908 return;
5909
5910 // Figure out which interface we're looking into.
5911 ObjCInterfaceDecl *Class = 0;
5912 if (ObjCImplementationDecl *ClassImpl
5913 = dyn_cast<ObjCImplementationDecl>(Container))
5914 Class = ClassImpl->getClassInterface();
5915 else
5916 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5917 ->getClassInterface();
5918
Douglas Gregore8426052011-04-18 14:40:46 +00005919 // Determine the type of the property we're synthesizing.
5920 QualType PropertyType = Context.getObjCIdType();
5921 if (Class) {
5922 if (ObjCPropertyDecl *Property
5923 = Class->FindPropertyDeclaration(PropertyName)) {
5924 PropertyType
5925 = Property->getType().getNonReferenceType().getUnqualifiedType();
5926
5927 // Give preference to ivars
5928 Results.setPreferredType(PropertyType);
5929 }
5930 }
5931
Douglas Gregor322328b2009-11-18 22:32:06 +00005932 // Add all of the instance variables in this class and its superclasses.
5933 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005934 bool SawSimilarlyNamedIvar = false;
5935 std::string NameWithPrefix;
5936 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005937 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005938 std::string NameWithSuffix = PropertyName->getName().str();
5939 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005940 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005941 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5942 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005943 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5944
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005945 // Determine whether we've seen an ivar with a name similar to the
5946 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005947 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005948 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005949 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005950 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005951
5952 // Reduce the priority of this result by one, to give it a slight
5953 // advantage over other results whose names don't match so closely.
5954 if (Results.size() &&
5955 Results.data()[Results.size() - 1].Kind
5956 == CodeCompletionResult::RK_Declaration &&
5957 Results.data()[Results.size() - 1].Declaration == Ivar)
5958 Results.data()[Results.size() - 1].Priority--;
5959 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005960 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005961 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005962
5963 if (!SawSimilarlyNamedIvar) {
5964 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005965 // an ivar of the appropriate type.
5966 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005967 typedef CodeCompletionResult Result;
5968 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005969 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
5970 Priority,CXAvailability_Available);
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005971
Douglas Gregor8987b232011-09-27 23:30:47 +00005972 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00005973 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005974 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005975 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5976 Results.AddResult(Result(Builder.TakeString(), Priority,
5977 CXCursor_ObjCIvarDecl));
5978 }
5979
Douglas Gregor322328b2009-11-18 22:32:06 +00005980 Results.ExitScope();
5981
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005982 HandleCodeCompleteResults(this, CodeCompleter,
5983 CodeCompletionContext::CCC_Other,
5984 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005985}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005986
Douglas Gregor408be5a2010-08-25 01:08:01 +00005987// Mapping from selectors to the methods that implement that selector, along
5988// with the "in original class" flag.
5989typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5990 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005991
5992/// \brief Find all of the methods that reside in the given container
5993/// (and its superclasses, protocols, etc.) that meet the given
5994/// criteria. Insert those methods into the map of known methods,
5995/// indexed by selector so they can be easily found.
5996static void FindImplementableMethods(ASTContext &Context,
5997 ObjCContainerDecl *Container,
5998 bool WantInstanceMethods,
5999 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00006000 KnownMethodsMap &KnownMethods,
6001 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006002 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006003 // Make sure we have a definition; that's what we'll walk.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006004 if (!IFace->hasDefinition())
6005 return;
Douglas Gregorb92a4082012-06-12 13:44:08 +00006006
6007 IFace = IFace->getDefinition();
6008 Container = IFace;
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006009
Douglas Gregore8f5a172010-04-07 00:21:17 +00006010 const ObjCList<ObjCProtocolDecl> &Protocols
6011 = IFace->getReferencedProtocols();
6012 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006013 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006014 I != E; ++I)
6015 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006016 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006017
Douglas Gregorea766182010-10-18 18:21:28 +00006018 // Add methods from any class extensions and categories.
6019 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
6020 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00006021 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
6022 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006023 KnownMethods, false);
6024
6025 // Visit the superclass.
6026 if (IFace->getSuperClass())
6027 FindImplementableMethods(Context, IFace->getSuperClass(),
6028 WantInstanceMethods, ReturnType,
6029 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006030 }
6031
6032 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6033 // Recurse into protocols.
6034 const ObjCList<ObjCProtocolDecl> &Protocols
6035 = Category->getReferencedProtocols();
6036 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006037 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006038 I != E; ++I)
6039 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006040 KnownMethods, InOriginalClass);
6041
6042 // If this category is the original class, jump to the interface.
6043 if (InOriginalClass && Category->getClassInterface())
6044 FindImplementableMethods(Context, Category->getClassInterface(),
6045 WantInstanceMethods, ReturnType, KnownMethods,
6046 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006047 }
6048
6049 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006050 // Make sure we have a definition; that's what we'll walk.
6051 if (!Protocol->hasDefinition())
6052 return;
6053 Protocol = Protocol->getDefinition();
6054 Container = Protocol;
6055
6056 // Recurse into protocols.
6057 const ObjCList<ObjCProtocolDecl> &Protocols
6058 = Protocol->getReferencedProtocols();
6059 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6060 E = Protocols.end();
6061 I != E; ++I)
6062 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6063 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006064 }
6065
6066 // Add methods in this container. This operation occurs last because
6067 // we want the methods from this container to override any methods
6068 // we've previously seen with the same selector.
6069 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
6070 MEnd = Container->meth_end();
6071 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00006072 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006073 if (!ReturnType.isNull() &&
David Blaikie262bc182012-04-30 02:36:29 +00006074 !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006075 continue;
6076
David Blaikie581deb32012-06-06 20:45:41 +00006077 KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006078 }
6079 }
6080}
6081
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006082/// \brief Add the parenthesized return or parameter type chunk to a code
6083/// completion string.
6084static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor90f5f472012-04-10 18:35:07 +00006085 unsigned ObjCDeclQuals,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006086 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006087 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006088 CodeCompletionBuilder &Builder) {
6089 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor90f5f472012-04-10 18:35:07 +00006090 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
6091 if (!Quals.empty())
6092 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor8987b232011-09-27 23:30:47 +00006093 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006094 Builder.getAllocator()));
6095 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6096}
6097
6098/// \brief Determine whether the given class is or inherits from a class by
6099/// the given name.
6100static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00006101 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006102 if (!Class)
6103 return false;
6104
6105 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6106 return true;
6107
6108 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6109}
6110
6111/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6112/// Key-Value Observing (KVO).
6113static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6114 bool IsInstanceMethod,
6115 QualType ReturnType,
6116 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006117 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006118 ResultBuilder &Results) {
6119 IdentifierInfo *PropName = Property->getIdentifier();
6120 if (!PropName || PropName->getLength() == 0)
6121 return;
6122
Douglas Gregor8987b232011-09-27 23:30:47 +00006123 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6124
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006125 // Builder that will create each code completion.
6126 typedef CodeCompletionResult Result;
6127 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006128 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006129
6130 // The selector table.
6131 SelectorTable &Selectors = Context.Selectors;
6132
6133 // The property name, copied into the code completion allocation region
6134 // on demand.
6135 struct KeyHolder {
6136 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006137 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006138 const char *CopiedKey;
6139
Chris Lattner5f9e2722011-07-23 10:55:15 +00006140 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006141 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6142
6143 operator const char *() {
6144 if (CopiedKey)
6145 return CopiedKey;
6146
6147 return CopiedKey = Allocator.CopyString(Key);
6148 }
6149 } Key(Allocator, PropName->getName());
6150
6151 // The uppercased name of the property name.
6152 std::string UpperKey = PropName->getName();
6153 if (!UpperKey.empty())
6154 UpperKey[0] = toupper(UpperKey[0]);
6155
6156 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6157 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6158 Property->getType());
6159 bool ReturnTypeMatchesVoid
6160 = ReturnType.isNull() || ReturnType->isVoidType();
6161
6162 // Add the normal accessor -(type)key.
6163 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006164 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006165 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6166 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006167 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6168 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006169
6170 Builder.AddTypedTextChunk(Key);
6171 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6172 CXCursor_ObjCInstanceMethodDecl));
6173 }
6174
6175 // If we have an integral or boolean property (or the user has provided
6176 // an integral or boolean return type), add the accessor -(type)isKey.
6177 if (IsInstanceMethod &&
6178 ((!ReturnType.isNull() &&
6179 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6180 (ReturnType.isNull() &&
6181 (Property->getType()->isIntegerType() ||
6182 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006183 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006184 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006185 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006186 if (ReturnType.isNull()) {
6187 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6188 Builder.AddTextChunk("BOOL");
6189 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6190 }
6191
6192 Builder.AddTypedTextChunk(
6193 Allocator.CopyString(SelectorId->getName()));
6194 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6195 CXCursor_ObjCInstanceMethodDecl));
6196 }
6197 }
6198
6199 // Add the normal mutator.
6200 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6201 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006202 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006203 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006204 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006205 if (ReturnType.isNull()) {
6206 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6207 Builder.AddTextChunk("void");
6208 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6209 }
6210
6211 Builder.AddTypedTextChunk(
6212 Allocator.CopyString(SelectorId->getName()));
6213 Builder.AddTypedTextChunk(":");
Douglas Gregor90f5f472012-04-10 18:35:07 +00006214 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6215 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006216 Builder.AddTextChunk(Key);
6217 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6218 CXCursor_ObjCInstanceMethodDecl));
6219 }
6220 }
6221
6222 // Indexed and unordered accessors
6223 unsigned IndexedGetterPriority = CCP_CodePattern;
6224 unsigned IndexedSetterPriority = CCP_CodePattern;
6225 unsigned UnorderedGetterPriority = CCP_CodePattern;
6226 unsigned UnorderedSetterPriority = CCP_CodePattern;
6227 if (const ObjCObjectPointerType *ObjCPointer
6228 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6229 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6230 // If this interface type is not provably derived from a known
6231 // collection, penalize the corresponding completions.
6232 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6233 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6234 if (!InheritsFromClassNamed(IFace, "NSArray"))
6235 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6236 }
6237
6238 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6239 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6240 if (!InheritsFromClassNamed(IFace, "NSSet"))
6241 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6242 }
6243 }
6244 } else {
6245 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6246 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6247 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6248 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6249 }
6250
6251 // Add -(NSUInteger)countOf<key>
6252 if (IsInstanceMethod &&
6253 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006254 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006255 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006256 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006257 if (ReturnType.isNull()) {
6258 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6259 Builder.AddTextChunk("NSUInteger");
6260 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6261 }
6262
6263 Builder.AddTypedTextChunk(
6264 Allocator.CopyString(SelectorId->getName()));
6265 Results.AddResult(Result(Builder.TakeString(),
6266 std::min(IndexedGetterPriority,
6267 UnorderedGetterPriority),
6268 CXCursor_ObjCInstanceMethodDecl));
6269 }
6270 }
6271
6272 // Indexed getters
6273 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6274 if (IsInstanceMethod &&
6275 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006276 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006277 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006278 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006279 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006280 if (ReturnType.isNull()) {
6281 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6282 Builder.AddTextChunk("id");
6283 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6284 }
6285
6286 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6287 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6288 Builder.AddTextChunk("NSUInteger");
6289 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6290 Builder.AddTextChunk("index");
6291 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6292 CXCursor_ObjCInstanceMethodDecl));
6293 }
6294 }
6295
6296 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6297 if (IsInstanceMethod &&
6298 (ReturnType.isNull() ||
6299 (ReturnType->isObjCObjectPointerType() &&
6300 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6301 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6302 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006303 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006304 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006305 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006306 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006307 if (ReturnType.isNull()) {
6308 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6309 Builder.AddTextChunk("NSArray *");
6310 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6311 }
6312
6313 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6314 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6315 Builder.AddTextChunk("NSIndexSet *");
6316 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6317 Builder.AddTextChunk("indexes");
6318 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6319 CXCursor_ObjCInstanceMethodDecl));
6320 }
6321 }
6322
6323 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6324 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006325 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006326 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006327 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006328 &Context.Idents.get("range")
6329 };
6330
Douglas Gregore74c25c2011-05-04 23:50:46 +00006331 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006332 if (ReturnType.isNull()) {
6333 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6334 Builder.AddTextChunk("void");
6335 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6336 }
6337
6338 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6339 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6340 Builder.AddPlaceholderChunk("object-type");
6341 Builder.AddTextChunk(" **");
6342 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6343 Builder.AddTextChunk("buffer");
6344 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6345 Builder.AddTypedTextChunk("range:");
6346 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6347 Builder.AddTextChunk("NSRange");
6348 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6349 Builder.AddTextChunk("inRange");
6350 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6351 CXCursor_ObjCInstanceMethodDecl));
6352 }
6353 }
6354
6355 // Mutable indexed accessors
6356
6357 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6358 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006359 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006360 IdentifierInfo *SelectorIds[2] = {
6361 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006362 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006363 };
6364
Douglas Gregore74c25c2011-05-04 23:50:46 +00006365 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006366 if (ReturnType.isNull()) {
6367 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6368 Builder.AddTextChunk("void");
6369 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6370 }
6371
6372 Builder.AddTypedTextChunk("insertObject:");
6373 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6374 Builder.AddPlaceholderChunk("object-type");
6375 Builder.AddTextChunk(" *");
6376 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6377 Builder.AddTextChunk("object");
6378 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6379 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6380 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6381 Builder.AddPlaceholderChunk("NSUInteger");
6382 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6383 Builder.AddTextChunk("index");
6384 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6385 CXCursor_ObjCInstanceMethodDecl));
6386 }
6387 }
6388
6389 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6390 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006391 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006392 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006393 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006394 &Context.Idents.get("atIndexes")
6395 };
6396
Douglas Gregore74c25c2011-05-04 23:50:46 +00006397 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006398 if (ReturnType.isNull()) {
6399 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6400 Builder.AddTextChunk("void");
6401 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6402 }
6403
6404 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6405 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6406 Builder.AddTextChunk("NSArray *");
6407 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6408 Builder.AddTextChunk("array");
6409 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6410 Builder.AddTypedTextChunk("atIndexes:");
6411 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6412 Builder.AddPlaceholderChunk("NSIndexSet *");
6413 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6414 Builder.AddTextChunk("indexes");
6415 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6416 CXCursor_ObjCInstanceMethodDecl));
6417 }
6418 }
6419
6420 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6421 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006422 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006423 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006424 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006425 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
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("NSUInteger");
6435 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6436 Builder.AddTextChunk("index");
6437 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6438 CXCursor_ObjCInstanceMethodDecl));
6439 }
6440 }
6441
6442 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6443 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006444 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006445 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006446 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006447 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006448 if (ReturnType.isNull()) {
6449 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6450 Builder.AddTextChunk("void");
6451 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6452 }
6453
6454 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6455 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6456 Builder.AddTextChunk("NSIndexSet *");
6457 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6458 Builder.AddTextChunk("indexes");
6459 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6460 CXCursor_ObjCInstanceMethodDecl));
6461 }
6462 }
6463
6464 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6465 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006466 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006467 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006468 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006469 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006470 &Context.Idents.get("withObject")
6471 };
6472
Douglas Gregore74c25c2011-05-04 23:50:46 +00006473 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006474 if (ReturnType.isNull()) {
6475 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6476 Builder.AddTextChunk("void");
6477 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6478 }
6479
6480 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6481 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6482 Builder.AddPlaceholderChunk("NSUInteger");
6483 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6484 Builder.AddTextChunk("index");
6485 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6486 Builder.AddTypedTextChunk("withObject:");
6487 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6488 Builder.AddTextChunk("id");
6489 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6490 Builder.AddTextChunk("object");
6491 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6492 CXCursor_ObjCInstanceMethodDecl));
6493 }
6494 }
6495
6496 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6497 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006498 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006499 = (Twine("replace") + UpperKey + "AtIndexes").str();
6500 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006501 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006502 &Context.Idents.get(SelectorName1),
6503 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006504 };
6505
Douglas Gregore74c25c2011-05-04 23:50:46 +00006506 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006507 if (ReturnType.isNull()) {
6508 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6509 Builder.AddTextChunk("void");
6510 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6511 }
6512
6513 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6514 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6515 Builder.AddPlaceholderChunk("NSIndexSet *");
6516 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6517 Builder.AddTextChunk("indexes");
6518 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6519 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6520 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6521 Builder.AddTextChunk("NSArray *");
6522 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6523 Builder.AddTextChunk("array");
6524 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6525 CXCursor_ObjCInstanceMethodDecl));
6526 }
6527 }
6528
6529 // Unordered getters
6530 // - (NSEnumerator *)enumeratorOfKey
6531 if (IsInstanceMethod &&
6532 (ReturnType.isNull() ||
6533 (ReturnType->isObjCObjectPointerType() &&
6534 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6535 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6536 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006537 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006538 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006539 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006540 if (ReturnType.isNull()) {
6541 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6542 Builder.AddTextChunk("NSEnumerator *");
6543 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6544 }
6545
6546 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6547 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6548 CXCursor_ObjCInstanceMethodDecl));
6549 }
6550 }
6551
6552 // - (type *)memberOfKey:(type *)object
6553 if (IsInstanceMethod &&
6554 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006555 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006556 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006557 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006558 if (ReturnType.isNull()) {
6559 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6560 Builder.AddPlaceholderChunk("object-type");
6561 Builder.AddTextChunk(" *");
6562 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6563 }
6564
6565 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6566 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6567 if (ReturnType.isNull()) {
6568 Builder.AddPlaceholderChunk("object-type");
6569 Builder.AddTextChunk(" *");
6570 } else {
6571 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006572 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006573 Builder.getAllocator()));
6574 }
6575 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6576 Builder.AddTextChunk("object");
6577 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6578 CXCursor_ObjCInstanceMethodDecl));
6579 }
6580 }
6581
6582 // Mutable unordered accessors
6583 // - (void)addKeyObject:(type *)object
6584 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006585 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006586 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006587 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006588 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006589 if (ReturnType.isNull()) {
6590 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6591 Builder.AddTextChunk("void");
6592 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6593 }
6594
6595 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6596 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6597 Builder.AddPlaceholderChunk("object-type");
6598 Builder.AddTextChunk(" *");
6599 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6600 Builder.AddTextChunk("object");
6601 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6602 CXCursor_ObjCInstanceMethodDecl));
6603 }
6604 }
6605
6606 // - (void)addKey:(NSSet *)objects
6607 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006608 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006609 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006610 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006611 if (ReturnType.isNull()) {
6612 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6613 Builder.AddTextChunk("void");
6614 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6615 }
6616
6617 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6618 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6619 Builder.AddTextChunk("NSSet *");
6620 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6621 Builder.AddTextChunk("objects");
6622 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6623 CXCursor_ObjCInstanceMethodDecl));
6624 }
6625 }
6626
6627 // - (void)removeKeyObject:(type *)object
6628 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006629 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006630 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006631 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006632 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006633 if (ReturnType.isNull()) {
6634 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6635 Builder.AddTextChunk("void");
6636 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6637 }
6638
6639 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6640 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6641 Builder.AddPlaceholderChunk("object-type");
6642 Builder.AddTextChunk(" *");
6643 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6644 Builder.AddTextChunk("object");
6645 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6646 CXCursor_ObjCInstanceMethodDecl));
6647 }
6648 }
6649
6650 // - (void)removeKey:(NSSet *)objects
6651 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006652 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006653 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006654 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006655 if (ReturnType.isNull()) {
6656 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6657 Builder.AddTextChunk("void");
6658 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6659 }
6660
6661 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6662 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6663 Builder.AddTextChunk("NSSet *");
6664 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6665 Builder.AddTextChunk("objects");
6666 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6667 CXCursor_ObjCInstanceMethodDecl));
6668 }
6669 }
6670
6671 // - (void)intersectKey:(NSSet *)objects
6672 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006673 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006674 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006675 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006676 if (ReturnType.isNull()) {
6677 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6678 Builder.AddTextChunk("void");
6679 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6680 }
6681
6682 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6683 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6684 Builder.AddTextChunk("NSSet *");
6685 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6686 Builder.AddTextChunk("objects");
6687 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6688 CXCursor_ObjCInstanceMethodDecl));
6689 }
6690 }
6691
6692 // Key-Value Observing
6693 // + (NSSet *)keyPathsForValuesAffectingKey
6694 if (!IsInstanceMethod &&
6695 (ReturnType.isNull() ||
6696 (ReturnType->isObjCObjectPointerType() &&
6697 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6698 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6699 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006700 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006701 = (Twine("keyPathsForValuesAffecting") + 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.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006704 if (ReturnType.isNull()) {
6705 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6706 Builder.AddTextChunk("NSSet *");
6707 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6708 }
6709
6710 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6711 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006712 CXCursor_ObjCClassMethodDecl));
6713 }
6714 }
6715
6716 // + (BOOL)automaticallyNotifiesObserversForKey
6717 if (!IsInstanceMethod &&
6718 (ReturnType.isNull() ||
6719 ReturnType->isIntegerType() ||
6720 ReturnType->isBooleanType())) {
6721 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006722 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006723 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6724 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6725 if (ReturnType.isNull()) {
6726 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6727 Builder.AddTextChunk("BOOL");
6728 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6729 }
6730
6731 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6732 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6733 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006734 }
6735 }
6736}
6737
Douglas Gregore8f5a172010-04-07 00:21:17 +00006738void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6739 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006740 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006741 // Determine the return type of the method we're declaring, if
6742 // provided.
6743 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006744 Decl *IDecl = 0;
6745 if (CurContext->isObjCContainer()) {
6746 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6747 IDecl = cast<Decl>(OCD);
6748 }
Douglas Gregorea766182010-10-18 18:21:28 +00006749 // Determine where we should start searching for methods.
6750 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006751 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006752 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006753 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6754 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006755 IsInImplementation = true;
6756 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006757 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006758 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006759 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006760 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006761 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006762 }
6763
6764 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006765 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006766 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006767 }
6768
Douglas Gregorea766182010-10-18 18:21:28 +00006769 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006770 HandleCodeCompleteResults(this, CodeCompleter,
6771 CodeCompletionContext::CCC_Other,
6772 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006773 return;
6774 }
6775
6776 // Find all of the methods that we could declare/implement here.
6777 KnownMethodsMap KnownMethods;
6778 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006779 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006780
Douglas Gregore8f5a172010-04-07 00:21:17 +00006781 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006782 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006783 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006784 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006785 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006786 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006787 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006788 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6789 MEnd = KnownMethods.end();
6790 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006791 ObjCMethodDecl *Method = M->second.first;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006792 CodeCompletionBuilder Builder(Results.getAllocator(),
6793 Results.getCodeCompletionTUInfo());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006794
6795 // If the result type was not already provided, add it to the
6796 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006797 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006798 AddObjCPassingTypeChunk(Method->getResultType(),
6799 Method->getObjCDeclQualifier(),
6800 Context, Policy,
6801 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006802
6803 Selector Sel = Method->getSelector();
6804
6805 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006806 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006807 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006808
6809 // Add parameters to the pattern.
6810 unsigned I = 0;
6811 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6812 PEnd = Method->param_end();
6813 P != PEnd; (void)++P, ++I) {
6814 // Add the part of the selector name.
6815 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006816 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006817 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006818 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6819 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006820 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006821 } else
6822 break;
6823
6824 // Add the parameter type.
Douglas Gregor90f5f472012-04-10 18:35:07 +00006825 AddObjCPassingTypeChunk((*P)->getOriginalType(),
6826 (*P)->getObjCDeclQualifier(),
6827 Context, Policy,
Douglas Gregor8987b232011-09-27 23:30:47 +00006828 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006829
6830 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006831 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006832 }
6833
6834 if (Method->isVariadic()) {
6835 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006836 Builder.AddChunk(CodeCompletionString::CK_Comma);
6837 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006838 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006839
Douglas Gregor447107d2010-05-28 00:57:46 +00006840 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006841 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006842 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6843 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6844 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006845 if (!Method->getResultType()->isVoidType()) {
6846 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006847 Builder.AddTextChunk("return");
6848 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6849 Builder.AddPlaceholderChunk("expression");
6850 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006851 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006852 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006853
Douglas Gregor218937c2011-02-01 19:23:04 +00006854 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6855 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006856 }
6857
Douglas Gregor408be5a2010-08-25 01:08:01 +00006858 unsigned Priority = CCP_CodePattern;
6859 if (!M->second.second)
6860 Priority += CCD_InBaseClass;
6861
Douglas Gregorba103062012-03-27 23:34:16 +00006862 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006863 }
6864
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006865 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6866 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006867 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006868 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006869 Containers.push_back(SearchDecl);
6870
Douglas Gregore74c25c2011-05-04 23:50:46 +00006871 VisitedSelectorSet KnownSelectors;
6872 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6873 MEnd = KnownMethods.end();
6874 M != MEnd; ++M)
6875 KnownSelectors.insert(M->first);
6876
6877
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006878 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6879 if (!IFace)
6880 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6881 IFace = Category->getClassInterface();
6882
6883 if (IFace) {
6884 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6885 Category = Category->getNextClassCategory())
6886 Containers.push_back(Category);
6887 }
6888
6889 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6890 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6891 PEnd = Containers[I]->prop_end();
6892 P != PEnd; ++P) {
David Blaikie581deb32012-06-06 20:45:41 +00006893 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006894 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006895 }
6896 }
6897 }
6898
Douglas Gregore8f5a172010-04-07 00:21:17 +00006899 Results.ExitScope();
6900
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006901 HandleCodeCompleteResults(this, CodeCompleter,
6902 CodeCompletionContext::CCC_Other,
6903 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006904}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006905
6906void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6907 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006908 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006909 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006910 IdentifierInfo **SelIdents,
6911 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006912 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006913 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006914 if (ExternalSource) {
6915 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6916 I != N; ++I) {
6917 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006918 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006919 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006920
6921 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006922 }
6923 }
6924
6925 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006926 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006927 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006928 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006929 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006930
6931 if (ReturnTy)
6932 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006933
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006934 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006935 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6936 MEnd = MethodPool.end();
6937 M != MEnd; ++M) {
6938 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6939 &M->second.second;
6940 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006941 MethList = MethList->Next) {
6942 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6943 NumSelIdents))
6944 continue;
6945
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006946 if (AtParameterName) {
6947 // Suggest parameter names we've seen before.
6948 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6949 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6950 if (Param->getIdentifier()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006951 CodeCompletionBuilder Builder(Results.getAllocator(),
6952 Results.getCodeCompletionTUInfo());
Douglas Gregordae68752011-02-01 22:57:45 +00006953 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006954 Param->getIdentifier()->getName()));
6955 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006956 }
6957 }
6958
6959 continue;
6960 }
6961
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006962 Result R(MethList->Method, 0);
6963 R.StartParameter = NumSelIdents;
6964 R.AllParametersAreInformative = false;
6965 R.DeclaringEntity = true;
6966 Results.MaybeAddResult(R, CurContext);
6967 }
6968 }
6969
6970 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006971 HandleCodeCompleteResults(this, CodeCompleter,
6972 CodeCompletionContext::CCC_Other,
6973 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006974}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006975
Douglas Gregorf29c5232010-08-24 22:20:20 +00006976void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006977 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006978 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006979 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006980 Results.EnterNewScope();
6981
6982 // #if <condition>
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006983 CodeCompletionBuilder Builder(Results.getAllocator(),
6984 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00006985 Builder.AddTypedTextChunk("if");
6986 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6987 Builder.AddPlaceholderChunk("condition");
6988 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006989
6990 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006991 Builder.AddTypedTextChunk("ifdef");
6992 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6993 Builder.AddPlaceholderChunk("macro");
6994 Results.AddResult(Builder.TakeString());
6995
Douglas Gregorf44e8542010-08-24 19:08:16 +00006996 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006997 Builder.AddTypedTextChunk("ifndef");
6998 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6999 Builder.AddPlaceholderChunk("macro");
7000 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007001
7002 if (InConditional) {
7003 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00007004 Builder.AddTypedTextChunk("elif");
7005 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7006 Builder.AddPlaceholderChunk("condition");
7007 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007008
7009 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00007010 Builder.AddTypedTextChunk("else");
7011 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007012
7013 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00007014 Builder.AddTypedTextChunk("endif");
7015 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007016 }
7017
7018 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007019 Builder.AddTypedTextChunk("include");
7020 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7021 Builder.AddTextChunk("\"");
7022 Builder.AddPlaceholderChunk("header");
7023 Builder.AddTextChunk("\"");
7024 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007025
7026 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007027 Builder.AddTypedTextChunk("include");
7028 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7029 Builder.AddTextChunk("<");
7030 Builder.AddPlaceholderChunk("header");
7031 Builder.AddTextChunk(">");
7032 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007033
7034 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007035 Builder.AddTypedTextChunk("define");
7036 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7037 Builder.AddPlaceholderChunk("macro");
7038 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007039
7040 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00007041 Builder.AddTypedTextChunk("define");
7042 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7043 Builder.AddPlaceholderChunk("macro");
7044 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7045 Builder.AddPlaceholderChunk("args");
7046 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7047 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007048
7049 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007050 Builder.AddTypedTextChunk("undef");
7051 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7052 Builder.AddPlaceholderChunk("macro");
7053 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007054
7055 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00007056 Builder.AddTypedTextChunk("line");
7057 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7058 Builder.AddPlaceholderChunk("number");
7059 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007060
7061 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00007062 Builder.AddTypedTextChunk("line");
7063 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7064 Builder.AddPlaceholderChunk("number");
7065 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7066 Builder.AddTextChunk("\"");
7067 Builder.AddPlaceholderChunk("filename");
7068 Builder.AddTextChunk("\"");
7069 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007070
7071 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007072 Builder.AddTypedTextChunk("error");
7073 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7074 Builder.AddPlaceholderChunk("message");
7075 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007076
7077 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00007078 Builder.AddTypedTextChunk("pragma");
7079 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7080 Builder.AddPlaceholderChunk("arguments");
7081 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007082
David Blaikie4e4d0842012-03-11 07:00:24 +00007083 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00007084 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007085 Builder.AddTypedTextChunk("import");
7086 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7087 Builder.AddTextChunk("\"");
7088 Builder.AddPlaceholderChunk("header");
7089 Builder.AddTextChunk("\"");
7090 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007091
7092 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007093 Builder.AddTypedTextChunk("import");
7094 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7095 Builder.AddTextChunk("<");
7096 Builder.AddPlaceholderChunk("header");
7097 Builder.AddTextChunk(">");
7098 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007099 }
7100
7101 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007102 Builder.AddTypedTextChunk("include_next");
7103 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7104 Builder.AddTextChunk("\"");
7105 Builder.AddPlaceholderChunk("header");
7106 Builder.AddTextChunk("\"");
7107 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007108
7109 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007110 Builder.AddTypedTextChunk("include_next");
7111 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7112 Builder.AddTextChunk("<");
7113 Builder.AddPlaceholderChunk("header");
7114 Builder.AddTextChunk(">");
7115 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007116
7117 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007118 Builder.AddTypedTextChunk("warning");
7119 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7120 Builder.AddPlaceholderChunk("message");
7121 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007122
7123 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7124 // completions for them. And __include_macros is a Clang-internal extension
7125 // that we don't want to encourage anyone to use.
7126
7127 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7128 Results.ExitScope();
7129
Douglas Gregorf44e8542010-08-24 19:08:16 +00007130 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00007131 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00007132 Results.data(), Results.size());
7133}
7134
7135void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007136 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007137 S->getFnParent()? Sema::PCC_RecoveryInFunction
7138 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007139}
7140
Douglas Gregorf29c5232010-08-24 22:20:20 +00007141void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007142 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007143 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007144 IsDefinition? CodeCompletionContext::CCC_MacroName
7145 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007146 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7147 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007148 CodeCompletionBuilder Builder(Results.getAllocator(),
7149 Results.getCodeCompletionTUInfo());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007150 Results.EnterNewScope();
7151 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7152 MEnd = PP.macro_end();
7153 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007154 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007155 M->first->getName()));
7156 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007157 }
7158 Results.ExitScope();
7159 } else if (IsDefinition) {
7160 // FIXME: Can we detect when the user just wrote an include guard above?
7161 }
7162
Douglas Gregor52779fb2010-09-23 23:01:17 +00007163 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007164 Results.data(), Results.size());
7165}
7166
Douglas Gregorf29c5232010-08-24 22:20:20 +00007167void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007168 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007169 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007170 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007171
7172 if (!CodeCompleter || CodeCompleter->includeMacros())
7173 AddMacroResults(PP, Results);
7174
7175 // defined (<macro>)
7176 Results.EnterNewScope();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007177 CodeCompletionBuilder Builder(Results.getAllocator(),
7178 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007179 Builder.AddTypedTextChunk("defined");
7180 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7181 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7182 Builder.AddPlaceholderChunk("macro");
7183 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7184 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007185 Results.ExitScope();
7186
7187 HandleCodeCompleteResults(this, CodeCompleter,
7188 CodeCompletionContext::CCC_PreprocessorExpression,
7189 Results.data(), Results.size());
7190}
7191
7192void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7193 IdentifierInfo *Macro,
7194 MacroInfo *MacroInfo,
7195 unsigned Argument) {
7196 // FIXME: In the future, we could provide "overload" results, much like we
7197 // do for function calls.
7198
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007199 // Now just ignore this. There will be another code-completion callback
7200 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007201}
7202
Douglas Gregor55817af2010-08-25 17:04:25 +00007203void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007204 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007205 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007206 0, 0);
7207}
7208
Douglas Gregordae68752011-02-01 22:57:45 +00007209void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007210 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007211 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007212 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7213 CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007214 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7215 CodeCompletionDeclConsumer Consumer(Builder,
7216 Context.getTranslationUnitDecl());
7217 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7218 Consumer);
7219 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007220
7221 if (!CodeCompleter || CodeCompleter->includeMacros())
7222 AddMacroResults(PP, Builder);
7223
7224 Results.clear();
7225 Results.insert(Results.end(),
7226 Builder.data(), Builder.data() + Builder.size());
7227}