blob: 3fd66ec04293d75545213fcdc319006db6b52a2e [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;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000126
127 /// \brief If non-NULL, a filter function used to remove any code-completion
128 /// results that are not desirable.
129 LookupFilter Filter;
Douglas Gregor45bcd432010-01-14 03:21:49 +0000130
131 /// \brief Whether we should allow declarations as
132 /// nested-name-specifiers that would otherwise be filtered out.
133 bool AllowNestedNameSpecifiers;
134
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000135 /// \brief If set, the type that we would prefer our resulting value
136 /// declarations to have.
137 ///
138 /// Closely matching the preferred type gives a boost to a result's
139 /// priority.
140 CanQualType PreferredType;
141
Douglas Gregor86d9a522009-09-21 16:56:56 +0000142 /// \brief A list of shadow maps, which is used to model name hiding at
143 /// different levels of, e.g., the inheritance hierarchy.
144 std::list<ShadowMap> ShadowMaps;
145
Douglas Gregor3cdee122010-08-26 16:36:48 +0000146 /// \brief If we're potentially referring to a C++ member function, the set
147 /// of qualifiers applied to the object type.
148 Qualifiers ObjectTypeQualifiers;
149
150 /// \brief Whether the \p ObjectTypeQualifiers field is active.
151 bool HasObjectTypeQualifiers;
152
Douglas Gregor265f7492010-08-27 15:29:55 +0000153 /// \brief The selector that we prefer.
154 Selector PreferredSelector;
155
Douglas Gregorca45da02010-11-02 20:36:02 +0000156 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000157 CodeCompletionContext CompletionContext;
158
Douglas Gregorca45da02010-11-02 20:36:02 +0000159 /// \brief If we are in an instance method definition, the @implementation
160 /// object.
161 ObjCImplementationDecl *ObjCImplementation;
162
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000163 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000164
Douglas Gregor6f942b22010-09-21 16:06:22 +0000165 void MaybeAddConstructorResults(Result R);
166
Douglas Gregor86d9a522009-09-21 16:56:56 +0000167 public:
Douglas Gregordae68752011-02-01 22:57:45 +0000168 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000169 const CodeCompletionContext &CompletionContext,
170 LookupFilter Filter = 0)
Douglas Gregor218937c2011-02-01 19:23:04 +0000171 : SemaRef(SemaRef), Allocator(Allocator), Filter(Filter),
172 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-11-02 20:36:02 +0000173 CompletionContext(CompletionContext),
174 ObjCImplementation(0)
175 {
176 // If this is an Objective-C instance method definition, dig out the
177 // corresponding implementation.
178 switch (CompletionContext.getKind()) {
179 case CodeCompletionContext::CCC_Expression:
180 case CodeCompletionContext::CCC_ObjCMessageReceiver:
181 case CodeCompletionContext::CCC_ParenthesizedExpression:
182 case CodeCompletionContext::CCC_Statement:
183 case CodeCompletionContext::CCC_Recovery:
184 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
185 if (Method->isInstanceMethod())
186 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
187 ObjCImplementation = Interface->getImplementation();
188 break;
189
190 default:
191 break;
192 }
193 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000194
Douglas Gregord8e8a582010-05-25 21:41:55 +0000195 /// \brief Whether we should include code patterns in the completion
196 /// results.
197 bool includeCodePatterns() const {
198 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000199 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000200 }
201
Douglas Gregor86d9a522009-09-21 16:56:56 +0000202 /// \brief Set the filter used for code-completion results.
203 void setFilter(LookupFilter Filter) {
204 this->Filter = Filter;
205 }
206
Douglas Gregor86d9a522009-09-21 16:56:56 +0000207 Result *data() { return Results.empty()? 0 : &Results.front(); }
208 unsigned size() const { return Results.size(); }
209 bool empty() const { return Results.empty(); }
210
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000211 /// \brief Specify the preferred type.
212 void setPreferredType(QualType T) {
213 PreferredType = SemaRef.Context.getCanonicalType(T);
214 }
215
Douglas Gregor3cdee122010-08-26 16:36:48 +0000216 /// \brief Set the cv-qualifiers on the object type, for us in filtering
217 /// calls to member functions.
218 ///
219 /// When there are qualifiers in this set, they will be used to filter
220 /// out member functions that aren't available (because there will be a
221 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
222 /// match.
223 void setObjectTypeQualifiers(Qualifiers Quals) {
224 ObjectTypeQualifiers = Quals;
225 HasObjectTypeQualifiers = true;
226 }
227
Douglas Gregor265f7492010-08-27 15:29:55 +0000228 /// \brief Set the preferred selector.
229 ///
230 /// When an Objective-C method declaration result is added, and that
231 /// method's selector matches this preferred selector, we give that method
232 /// a slight priority boost.
233 void setPreferredSelector(Selector Sel) {
234 PreferredSelector = Sel;
235 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000236
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000237 /// \brief Retrieve the code-completion context for which results are
238 /// being collected.
239 const CodeCompletionContext &getCompletionContext() const {
240 return CompletionContext;
241 }
242
Douglas Gregor45bcd432010-01-14 03:21:49 +0000243 /// \brief Specify whether nested-name-specifiers are allowed.
244 void allowNestedNameSpecifiers(bool Allow = true) {
245 AllowNestedNameSpecifiers = Allow;
246 }
247
Douglas Gregorb9d77572010-09-21 00:03:25 +0000248 /// \brief Return the semantic analysis object for which we are collecting
249 /// code completion results.
250 Sema &getSema() const { return SemaRef; }
251
Douglas Gregor218937c2011-02-01 19:23:04 +0000252 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000253 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Douglas Gregor218937c2011-02-01 19:23:04 +0000254
Douglas Gregore495b7f2010-01-14 00:20:49 +0000255 /// \brief Determine whether the given declaration is at all interesting
256 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000257 ///
258 /// \param ND the declaration that we are inspecting.
259 ///
260 /// \param AsNestedNameSpecifier will be set true if this declaration is
261 /// only interesting when it is a nested-name-specifier.
262 bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000263
264 /// \brief Check whether the result is hidden by the Hiding declaration.
265 ///
266 /// \returns true if the result is hidden and cannot be found, false if
267 /// the hidden result could still be found. When false, \p R may be
268 /// modified to describe how the result can be found (e.g., via extra
269 /// qualification).
270 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
271 NamedDecl *Hiding);
272
Douglas Gregor86d9a522009-09-21 16:56:56 +0000273 /// \brief Add a new result to this result set (if it isn't already in one
274 /// of the shadow maps), or replace an existing result (for, e.g., a
275 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000276 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000277 /// \param R the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000278 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000279 /// \param CurContext the context in which this result will be named.
Douglas Gregor456c4a12009-09-21 20:12:40 +0000280 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000281
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000282 /// \brief Add a new result to this result set, where we already know
283 /// the hiding declation (if any).
284 ///
285 /// \param R the result to add (if it is unique).
286 ///
287 /// \param CurContext the context in which this result will be named.
288 ///
289 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000290 ///
291 /// \param InBaseClass whether the result was found in a base
292 /// class of the searched context.
293 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
294 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000295
Douglas Gregora4477812010-01-14 16:01:26 +0000296 /// \brief Add a new non-declaration result to this result set.
297 void AddResult(Result R);
298
Douglas Gregor86d9a522009-09-21 16:56:56 +0000299 /// \brief Enter into a new scope.
300 void EnterNewScope();
301
302 /// \brief Exit from the current scope.
303 void ExitScope();
304
Douglas Gregor55385fe2009-11-18 04:19:12 +0000305 /// \brief Ignore this declaration, if it is seen again.
306 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
307
Douglas Gregor86d9a522009-09-21 16:56:56 +0000308 /// \name Name lookup predicates
309 ///
310 /// These predicates can be passed to the name lookup functions to filter the
311 /// results of name lookup. All of the predicates have the same type, so that
312 ///
313 //@{
Douglas Gregor791215b2009-09-21 20:51:25 +0000314 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000315 bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
Douglas Gregorf9578432010-07-28 21:50:18 +0000316 bool IsIntegralConstantValue(NamedDecl *ND) const;
Douglas Gregor01dfea02010-01-10 23:08:15 +0000317 bool IsOrdinaryNonValueName(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000318 bool IsNestedNameSpecifier(NamedDecl *ND) const;
319 bool IsEnum(NamedDecl *ND) const;
320 bool IsClassOrStruct(NamedDecl *ND) const;
321 bool IsUnion(NamedDecl *ND) const;
322 bool IsNamespace(NamedDecl *ND) const;
323 bool IsNamespaceOrAlias(NamedDecl *ND) const;
324 bool IsType(NamedDecl *ND) const;
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000325 bool IsMember(NamedDecl *ND) const;
Douglas Gregor80f4f4c2010-01-14 16:08:12 +0000326 bool IsObjCIvar(NamedDecl *ND) const;
Douglas Gregor8e254cf2010-05-27 23:06:34 +0000327 bool IsObjCMessageReceiver(NamedDecl *ND) const;
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000328 bool IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const;
Douglas Gregorfb629412010-08-23 21:17:50 +0000329 bool IsObjCCollection(NamedDecl *ND) const;
Douglas Gregor52779fb2010-09-23 23:01:17 +0000330 bool IsImpossibleToSatisfy(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000331 //@}
332 };
333}
334
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000335class ResultBuilder::ShadowMapEntry::iterator {
336 llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
337 unsigned SingleDeclIndex;
338
339public:
340 typedef DeclIndexPair value_type;
341 typedef value_type reference;
342 typedef std::ptrdiff_t difference_type;
343 typedef std::input_iterator_tag iterator_category;
344
345 class pointer {
346 DeclIndexPair Value;
347
348 public:
349 pointer(const DeclIndexPair &Value) : Value(Value) { }
350
351 const DeclIndexPair *operator->() const {
352 return &Value;
353 }
354 };
355
356 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
357
358 iterator(NamedDecl *SingleDecl, unsigned Index)
359 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
360
361 iterator(const DeclIndexPair *Iterator)
362 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
363
364 iterator &operator++() {
365 if (DeclOrIterator.is<NamedDecl *>()) {
366 DeclOrIterator = (NamedDecl *)0;
367 SingleDeclIndex = 0;
368 return *this;
369 }
370
371 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
372 ++I;
373 DeclOrIterator = I;
374 return *this;
375 }
376
Chris Lattner66392d42010-09-04 18:12:20 +0000377 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000378 iterator tmp(*this);
379 ++(*this);
380 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000381 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000382
383 reference operator*() const {
384 if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
385 return reference(ND, SingleDeclIndex);
386
Douglas Gregord490f952009-12-06 21:27:58 +0000387 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000388 }
389
390 pointer operator->() const {
391 return pointer(**this);
392 }
393
394 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000395 return X.DeclOrIterator.getOpaqueValue()
396 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000397 X.SingleDeclIndex == Y.SingleDeclIndex;
398 }
399
400 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000401 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000402 }
403};
404
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000405ResultBuilder::ShadowMapEntry::iterator
406ResultBuilder::ShadowMapEntry::begin() const {
407 if (DeclOrVector.isNull())
408 return iterator();
409
410 if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
411 return iterator(ND, SingleDeclIndex);
412
413 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
414}
415
416ResultBuilder::ShadowMapEntry::iterator
417ResultBuilder::ShadowMapEntry::end() const {
418 if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
419 return iterator();
420
421 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
422}
423
Douglas Gregor456c4a12009-09-21 20:12:40 +0000424/// \brief Compute the qualification required to get from the current context
425/// (\p CurContext) to the target context (\p TargetContext).
426///
427/// \param Context the AST context in which the qualification will be used.
428///
429/// \param CurContext the context where an entity is being named, which is
430/// typically based on the current scope.
431///
432/// \param TargetContext the context in which the named entity actually
433/// resides.
434///
435/// \returns a nested name specifier that refers into the target context, or
436/// NULL if no qualification is needed.
437static NestedNameSpecifier *
438getRequiredQualification(ASTContext &Context,
439 DeclContext *CurContext,
440 DeclContext *TargetContext) {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000441 SmallVector<DeclContext *, 4> TargetParents;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000442
443 for (DeclContext *CommonAncestor = TargetContext;
444 CommonAncestor && !CommonAncestor->Encloses(CurContext);
445 CommonAncestor = CommonAncestor->getLookupParent()) {
446 if (CommonAncestor->isTransparentContext() ||
447 CommonAncestor->isFunctionOrMethod())
448 continue;
449
450 TargetParents.push_back(CommonAncestor);
451 }
452
453 NestedNameSpecifier *Result = 0;
454 while (!TargetParents.empty()) {
455 DeclContext *Parent = TargetParents.back();
456 TargetParents.pop_back();
457
Douglas Gregorfb629412010-08-23 21:17:50 +0000458 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
459 if (!Namespace->getIdentifier())
460 continue;
461
Douglas Gregor456c4a12009-09-21 20:12:40 +0000462 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000463 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000464 else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
465 Result = NestedNameSpecifier::Create(Context, Result,
466 false,
467 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000468 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000469 return Result;
470}
471
Douglas Gregor45bcd432010-01-14 03:21:49 +0000472bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
473 bool &AsNestedNameSpecifier) const {
474 AsNestedNameSpecifier = false;
475
Douglas Gregore495b7f2010-01-14 00:20:49 +0000476 ND = ND->getUnderlyingDecl();
477 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000478
479 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000480 if (!ND->getDeclName())
481 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000482
483 // Friend declarations and declarations introduced due to friends are never
484 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000485 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000486 return false;
487
Douglas Gregor76282942009-12-11 17:31:05 +0000488 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000489 if (isa<ClassTemplateSpecializationDecl>(ND) ||
490 isa<ClassTemplatePartialSpecializationDecl>(ND))
491 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000492
Douglas Gregor76282942009-12-11 17:31:05 +0000493 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000494 if (isa<UsingDecl>(ND))
495 return false;
496
497 // Some declarations have reserved names that we don't want to ever show.
498 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000499 // __va_list_tag is a freak of nature. Find it and skip it.
500 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000501 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000502
Douglas Gregorf52cede2009-10-09 22:16:47 +0000503 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000504 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000505 //
506 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000507 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000508 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000509 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000510 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
511 (ND->getLocation().isInvalid() ||
512 SemaRef.SourceMgr.isInSystemHeader(
513 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000514 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000515 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000516 }
Douglas Gregor6f942b22010-09-21 16:06:22 +0000517
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000518 // Skip out-of-line declarations and definitions.
519 // NOTE: Unless it's an Objective-C property, method, or ivar, where
520 // the contexts can be messy.
521 if (!ND->getDeclContext()->Equals(ND->getLexicalDeclContext()) &&
522 !(isa<ObjCPropertyDecl>(ND) || isa<ObjCIvarDecl>(ND) ||
523 isa<ObjCMethodDecl>(ND)))
524 return false;
525
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000526 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
527 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
528 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000529 Filter != &ResultBuilder::IsNamespaceOrAlias &&
530 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000531 AsNestedNameSpecifier = true;
532
Douglas Gregor86d9a522009-09-21 16:56:56 +0000533 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000534 if (Filter && !(this->*Filter)(ND)) {
535 // Check whether it is interesting as a nested-name-specifier.
David Blaikie4e4d0842012-03-11 07:00:24 +0000536 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor45bcd432010-01-14 03:21:49 +0000537 IsNestedNameSpecifier(ND) &&
538 (Filter != &ResultBuilder::IsMember ||
539 (isa<CXXRecordDecl>(ND) &&
540 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
541 AsNestedNameSpecifier = true;
542 return true;
543 }
544
Douglas Gregore495b7f2010-01-14 00:20:49 +0000545 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000546 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000547 // ... then it must be interesting!
548 return true;
549}
550
Douglas Gregor6660d842010-01-14 00:41:07 +0000551bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
552 NamedDecl *Hiding) {
553 // In C, there is no way to refer to a hidden name.
554 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
555 // name if we introduce the tag type.
David Blaikie4e4d0842012-03-11 07:00:24 +0000556 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor6660d842010-01-14 00:41:07 +0000557 return true;
558
Sebastian Redl7a126a42010-08-31 00:36:30 +0000559 DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000560
561 // There is no way to qualify a name declared in a function or method.
562 if (HiddenCtx->isFunctionOrMethod())
563 return true;
564
Sebastian Redl7a126a42010-08-31 00:36:30 +0000565 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000566 return true;
567
568 // We can refer to the result with the appropriate qualification. Do it.
569 R.Hidden = true;
570 R.QualifierIsInformative = false;
571
572 if (!R.Qualifier)
573 R.Qualifier = getRequiredQualification(SemaRef.Context,
574 CurContext,
575 R.Declaration->getDeclContext());
576 return false;
577}
578
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000579/// \brief A simplified classification of types used to determine whether two
580/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000581SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000582 switch (T->getTypeClass()) {
583 case Type::Builtin:
584 switch (cast<BuiltinType>(T)->getKind()) {
585 case BuiltinType::Void:
586 return STC_Void;
587
588 case BuiltinType::NullPtr:
589 return STC_Pointer;
590
591 case BuiltinType::Overload:
592 case BuiltinType::Dependent:
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000593 return STC_Other;
594
595 case BuiltinType::ObjCId:
596 case BuiltinType::ObjCClass:
597 case BuiltinType::ObjCSel:
598 return STC_ObjectiveC;
599
600 default:
601 return STC_Arithmetic;
602 }
David Blaikie7530c032012-01-17 06:56:22 +0000603
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000604 case Type::Complex:
605 return STC_Arithmetic;
606
607 case Type::Pointer:
608 return STC_Pointer;
609
610 case Type::BlockPointer:
611 return STC_Block;
612
613 case Type::LValueReference:
614 case Type::RValueReference:
615 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
616
617 case Type::ConstantArray:
618 case Type::IncompleteArray:
619 case Type::VariableArray:
620 case Type::DependentSizedArray:
621 return STC_Array;
622
623 case Type::DependentSizedExtVector:
624 case Type::Vector:
625 case Type::ExtVector:
626 return STC_Arithmetic;
627
628 case Type::FunctionProto:
629 case Type::FunctionNoProto:
630 return STC_Function;
631
632 case Type::Record:
633 return STC_Record;
634
635 case Type::Enum:
636 return STC_Arithmetic;
637
638 case Type::ObjCObject:
639 case Type::ObjCInterface:
640 case Type::ObjCObjectPointer:
641 return STC_ObjectiveC;
642
643 default:
644 return STC_Other;
645 }
646}
647
648/// \brief Get the type that a given expression will have if this declaration
649/// is used as an expression in its "typical" code-completion form.
Douglas Gregor1827e102010-08-16 16:18:59 +0000650QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000651 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
652
653 if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
654 return C.getTypeDeclType(Type);
655 if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
656 return C.getObjCInterfaceType(Iface);
657
658 QualType T;
659 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000660 T = Function->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000661 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000662 T = Method->getSendResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000663 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000664 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000665 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
666 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
667 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
668 T = Property->getType();
669 else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
670 T = Value->getType();
671 else
672 return QualType();
Douglas Gregor3e64d562011-04-14 20:33:34 +0000673
674 // Dig through references, function pointers, and block pointers to
675 // get down to the likely type of an expression when the entity is
676 // used.
677 do {
678 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
679 T = Ref->getPointeeType();
680 continue;
681 }
682
683 if (const PointerType *Pointer = T->getAs<PointerType>()) {
684 if (Pointer->getPointeeType()->isFunctionType()) {
685 T = Pointer->getPointeeType();
686 continue;
687 }
688
689 break;
690 }
691
692 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
693 T = Block->getPointeeType();
694 continue;
695 }
696
697 if (const FunctionType *Function = T->getAs<FunctionType>()) {
698 T = Function->getResultType();
699 continue;
700 }
701
702 break;
703 } while (true);
704
705 return T;
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000706}
707
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000708void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
709 // If this is an Objective-C method declaration whose selector matches our
710 // preferred selector, give it a priority boost.
711 if (!PreferredSelector.isNull())
712 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
713 if (PreferredSelector == Method->getSelector())
714 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000715
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000716 // If we have a preferred type, adjust the priority for results with exactly-
717 // matching or nearly-matching types.
718 if (!PreferredType.isNull()) {
719 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
720 if (!T.isNull()) {
721 CanQualType TC = SemaRef.Context.getCanonicalType(T);
722 // Check for exactly-matching types (modulo qualifiers).
723 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
724 R.Priority /= CCF_ExactTypeMatch;
725 // Check for nearly-matching types, based on classification of each.
726 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000727 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000728 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
729 R.Priority /= CCF_SimilarTypeMatch;
730 }
731 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000732}
733
Douglas Gregor6f942b22010-09-21 16:06:22 +0000734void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikie4e4d0842012-03-11 07:00:24 +0000735 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor6f942b22010-09-21 16:06:22 +0000736 !CompletionContext.wantConstructorResults())
737 return;
738
739 ASTContext &Context = SemaRef.Context;
740 NamedDecl *D = R.Declaration;
741 CXXRecordDecl *Record = 0;
742 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
743 Record = ClassTemplate->getTemplatedDecl();
744 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
745 // Skip specializations and partial specializations.
746 if (isa<ClassTemplateSpecializationDecl>(Record))
747 return;
748 } else {
749 // There are no constructors here.
750 return;
751 }
752
753 Record = Record->getDefinition();
754 if (!Record)
755 return;
756
757
758 QualType RecordTy = Context.getTypeDeclType(Record);
759 DeclarationName ConstructorName
760 = Context.DeclarationNames.getCXXConstructorName(
761 Context.getCanonicalType(RecordTy));
762 for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
763 Ctors.first != Ctors.second; ++Ctors.first) {
764 R.Declaration = *Ctors.first;
765 R.CursorKind = getCursorKindForDecl(R.Declaration);
766 Results.push_back(R);
767 }
768}
769
Douglas Gregore495b7f2010-01-14 00:20:49 +0000770void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
771 assert(!ShadowMaps.empty() && "Must enter into a results scope");
772
773 if (R.Kind != Result::RK_Declaration) {
774 // For non-declaration results, just add the result.
775 Results.push_back(R);
776 return;
777 }
778
779 // Look through using declarations.
780 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
781 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
782 return;
783 }
784
785 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
786 unsigned IDNS = CanonDecl->getIdentifierNamespace();
787
Douglas Gregor45bcd432010-01-14 03:21:49 +0000788 bool AsNestedNameSpecifier = false;
789 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000790 return;
791
Douglas Gregor6f942b22010-09-21 16:06:22 +0000792 // C++ constructors are never found by name lookup.
793 if (isa<CXXConstructorDecl>(R.Declaration))
794 return;
795
Douglas Gregor86d9a522009-09-21 16:56:56 +0000796 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000797 ShadowMapEntry::iterator I, IEnd;
798 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
799 if (NamePos != SMap.end()) {
800 I = NamePos->second.begin();
801 IEnd = NamePos->second.end();
802 }
803
804 for (; I != IEnd; ++I) {
805 NamedDecl *ND = I->first;
806 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000807 if (ND->getCanonicalDecl() == CanonDecl) {
808 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000809 Results[Index].Declaration = R.Declaration;
810
Douglas Gregor86d9a522009-09-21 16:56:56 +0000811 // We're done.
812 return;
813 }
814 }
815
816 // This is a new declaration in this scope. However, check whether this
817 // declaration name is hidden by a similarly-named declaration in an outer
818 // scope.
819 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
820 --SMEnd;
821 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000822 ShadowMapEntry::iterator I, IEnd;
823 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
824 if (NamePos != SM->end()) {
825 I = NamePos->second.begin();
826 IEnd = NamePos->second.end();
827 }
828 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000829 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000830 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000831 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
832 Decl::IDNS_ObjCProtocol)))
833 continue;
834
835 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000836 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000837 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000838 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000839 continue;
840
841 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000842 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000843 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000844
845 break;
846 }
847 }
848
849 // Make sure that any given declaration only shows up in the result set once.
850 if (!AllDeclsFound.insert(CanonDecl))
851 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000852
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000853 // If the filter is for nested-name-specifiers, then this result starts a
854 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000855 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000856 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000857 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000858 } else
859 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000860
Douglas Gregor0563c262009-09-22 23:15:58 +0000861 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000862 if (R.QualifierIsInformative && !R.Qualifier &&
863 !R.StartsNestedNameSpecifier) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000864 DeclContext *Ctx = R.Declaration->getDeclContext();
865 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
866 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
867 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
868 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
869 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
870 else
871 R.QualifierIsInformative = false;
872 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000873
Douglas Gregor86d9a522009-09-21 16:56:56 +0000874 // Insert this result into the set of results and into the current shadow
875 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000876 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000877 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000878
879 if (!AsNestedNameSpecifier)
880 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000881}
882
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000883void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000884 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000885 if (R.Kind != Result::RK_Declaration) {
886 // For non-declaration results, just add the result.
887 Results.push_back(R);
888 return;
889 }
890
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000891 // Look through using declarations.
892 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
893 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
894 return;
895 }
896
Douglas Gregor45bcd432010-01-14 03:21:49 +0000897 bool AsNestedNameSpecifier = false;
898 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000899 return;
900
Douglas Gregor6f942b22010-09-21 16:06:22 +0000901 // C++ constructors are never found by name lookup.
902 if (isa<CXXConstructorDecl>(R.Declaration))
903 return;
904
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000905 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
906 return;
907
908 // Make sure that any given declaration only shows up in the result set once.
909 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
910 return;
911
912 // If the filter is for nested-name-specifiers, then this result starts a
913 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000914 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000915 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000916 R.Priority = CCP_NestedNameSpecifier;
917 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000918 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
919 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000920 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000921 R.QualifierIsInformative = true;
922
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000923 // If this result is supposed to have an informative qualifier, add one.
924 if (R.QualifierIsInformative && !R.Qualifier &&
925 !R.StartsNestedNameSpecifier) {
926 DeclContext *Ctx = R.Declaration->getDeclContext();
927 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
928 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
929 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
930 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000931 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000932 else
933 R.QualifierIsInformative = false;
934 }
935
Douglas Gregor12e13132010-05-26 22:00:08 +0000936 // Adjust the priority if this result comes from a base class.
937 if (InBaseClass)
938 R.Priority += CCD_InBaseClass;
939
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000940 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000941
Douglas Gregor3cdee122010-08-26 16:36:48 +0000942 if (HasObjectTypeQualifiers)
943 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
944 if (Method->isInstance()) {
945 Qualifiers MethodQuals
946 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
947 if (ObjectTypeQualifiers == MethodQuals)
948 R.Priority += CCD_ObjectQualifierMatch;
949 else if (ObjectTypeQualifiers - MethodQuals) {
950 // The method cannot be invoked, because doing so would drop
951 // qualifiers.
952 return;
953 }
954 }
955
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000956 // Insert this result into the set of results.
957 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000958
959 if (!AsNestedNameSpecifier)
960 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000961}
962
Douglas Gregora4477812010-01-14 16:01:26 +0000963void ResultBuilder::AddResult(Result R) {
964 assert(R.Kind != Result::RK_Declaration &&
965 "Declaration results need more context");
966 Results.push_back(R);
967}
968
Douglas Gregor86d9a522009-09-21 16:56:56 +0000969/// \brief Enter into a new scope.
970void ResultBuilder::EnterNewScope() {
971 ShadowMaps.push_back(ShadowMap());
972}
973
974/// \brief Exit from the current scope.
975void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000976 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
977 EEnd = ShadowMaps.back().end();
978 E != EEnd;
979 ++E)
980 E->second.Destroy();
981
Douglas Gregor86d9a522009-09-21 16:56:56 +0000982 ShadowMaps.pop_back();
983}
984
Douglas Gregor791215b2009-09-21 20:51:25 +0000985/// \brief Determines whether this given declaration will be found by
986/// ordinary name lookup.
987bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000988 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
989
Douglas Gregor791215b2009-09-21 20:51:25 +0000990 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +0000991 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000992 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +0000993 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +0000994 if (isa<ObjCIvarDecl>(ND))
995 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +0000996 }
997
Douglas Gregor791215b2009-09-21 20:51:25 +0000998 return ND->getIdentifierNamespace() & IDNS;
999}
1000
Douglas Gregor01dfea02010-01-10 23:08:15 +00001001/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001002/// ordinary name lookup but is not a type name.
1003bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
1004 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1005 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1006 return false;
1007
1008 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001009 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +00001010 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +00001011 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +00001012 if (isa<ObjCIvarDecl>(ND))
1013 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001014 }
1015
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001016 return ND->getIdentifierNamespace() & IDNS;
1017}
1018
Douglas Gregorf9578432010-07-28 21:50:18 +00001019bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
1020 if (!IsOrdinaryNonTypeName(ND))
1021 return 0;
1022
1023 if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
1024 if (VD->getType()->isIntegralOrEnumerationType())
1025 return true;
1026
1027 return false;
1028}
1029
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001030/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001031/// ordinary name lookup.
1032bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001033 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1034
Douglas Gregor01dfea02010-01-10 23:08:15 +00001035 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001036 if (SemaRef.getLangOpts().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001037 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001038
1039 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001040 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1041 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001042}
1043
Douglas Gregor86d9a522009-09-21 16:56:56 +00001044/// \brief Determines whether the given declaration is suitable as the
1045/// start of a C++ nested-name-specifier, e.g., a class or namespace.
1046bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
1047 // Allow us to find class templates, too.
1048 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1049 ND = ClassTemplate->getTemplatedDecl();
1050
1051 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1052}
1053
1054/// \brief Determines whether the given declaration is an enumeration.
1055bool ResultBuilder::IsEnum(NamedDecl *ND) const {
1056 return isa<EnumDecl>(ND);
1057}
1058
1059/// \brief Determines whether the given declaration is a class or struct.
1060bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
1061 // Allow us to find class templates, too.
1062 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1063 ND = ClassTemplate->getTemplatedDecl();
1064
1065 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001066 return RD->getTagKind() == TTK_Class ||
1067 RD->getTagKind() == TTK_Struct;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001068
1069 return false;
1070}
1071
1072/// \brief Determines whether the given declaration is a union.
1073bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1074 // Allow us to find class templates, too.
1075 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1076 ND = ClassTemplate->getTemplatedDecl();
1077
1078 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001079 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001080
1081 return false;
1082}
1083
1084/// \brief Determines whether the given declaration is a namespace.
1085bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1086 return isa<NamespaceDecl>(ND);
1087}
1088
1089/// \brief Determines whether the given declaration is a namespace or
1090/// namespace alias.
1091bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1092 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1093}
1094
Douglas Gregor76282942009-12-11 17:31:05 +00001095/// \brief Determines whether the given declaration is a type.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001096bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregord32b0222010-08-24 01:06:58 +00001097 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1098 ND = Using->getTargetDecl();
1099
1100 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001101}
1102
Douglas Gregor76282942009-12-11 17:31:05 +00001103/// \brief Determines which members of a class should be visible via
1104/// "." or "->". Only value declarations, nested name specifiers, and
1105/// using declarations thereof should show up.
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001106bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor76282942009-12-11 17:31:05 +00001107 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1108 ND = Using->getTargetDecl();
1109
Douglas Gregorce821962009-12-11 18:14:22 +00001110 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1111 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001112}
1113
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001114static bool isObjCReceiverType(ASTContext &C, QualType T) {
1115 T = C.getCanonicalType(T);
1116 switch (T->getTypeClass()) {
1117 case Type::ObjCObject:
1118 case Type::ObjCInterface:
1119 case Type::ObjCObjectPointer:
1120 return true;
1121
1122 case Type::Builtin:
1123 switch (cast<BuiltinType>(T)->getKind()) {
1124 case BuiltinType::ObjCId:
1125 case BuiltinType::ObjCClass:
1126 case BuiltinType::ObjCSel:
1127 return true;
1128
1129 default:
1130 break;
1131 }
1132 return false;
1133
1134 default:
1135 break;
1136 }
1137
David Blaikie4e4d0842012-03-11 07:00:24 +00001138 if (!C.getLangOpts().CPlusPlus)
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001139 return false;
1140
1141 // FIXME: We could perform more analysis here to determine whether a
1142 // particular class type has any conversions to Objective-C types. For now,
1143 // just accept all class types.
1144 return T->isDependentType() || T->isRecordType();
1145}
1146
1147bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1148 QualType T = getDeclUsageType(SemaRef.Context, ND);
1149 if (T.isNull())
1150 return false;
1151
1152 T = SemaRef.Context.getBaseElementType(T);
1153 return isObjCReceiverType(SemaRef.Context, T);
1154}
1155
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001156bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const {
1157 if (IsObjCMessageReceiver(ND))
1158 return true;
1159
1160 VarDecl *Var = dyn_cast<VarDecl>(ND);
1161 if (!Var)
1162 return false;
1163
1164 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1165}
1166
Douglas Gregorfb629412010-08-23 21:17:50 +00001167bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
David Blaikie4e4d0842012-03-11 07:00:24 +00001168 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1169 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregorfb629412010-08-23 21:17:50 +00001170 return false;
1171
1172 QualType T = getDeclUsageType(SemaRef.Context, ND);
1173 if (T.isNull())
1174 return false;
1175
1176 T = SemaRef.Context.getBaseElementType(T);
1177 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1178 T->isObjCIdType() ||
David Blaikie4e4d0842012-03-11 07:00:24 +00001179 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregorfb629412010-08-23 21:17:50 +00001180}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001181
Douglas Gregor52779fb2010-09-23 23:01:17 +00001182bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1183 return false;
1184}
1185
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001186/// \rief Determines whether the given declaration is an Objective-C
1187/// instance variable.
1188bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1189 return isa<ObjCIvarDecl>(ND);
1190}
1191
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001192namespace {
1193 /// \brief Visible declaration consumer that adds a code-completion result
1194 /// for each visible declaration.
1195 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1196 ResultBuilder &Results;
1197 DeclContext *CurContext;
1198
1199 public:
1200 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1201 : Results(Results), CurContext(CurContext) { }
1202
Erik Verbruggend1205962011-10-06 07:27:49 +00001203 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1204 bool InBaseClass) {
1205 bool Accessible = true;
Douglas Gregor17015ef2011-11-03 16:51:37 +00001206 if (Ctx)
1207 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1208
Erik Verbruggend1205962011-10-06 07:27:49 +00001209 ResultBuilder::Result Result(ND, 0, false, Accessible);
1210 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001211 }
1212 };
1213}
1214
Douglas Gregor86d9a522009-09-21 16:56:56 +00001215/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001216static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001217 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001218 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001219 Results.AddResult(Result("short", CCP_Type));
1220 Results.AddResult(Result("long", CCP_Type));
1221 Results.AddResult(Result("signed", CCP_Type));
1222 Results.AddResult(Result("unsigned", CCP_Type));
1223 Results.AddResult(Result("void", CCP_Type));
1224 Results.AddResult(Result("char", CCP_Type));
1225 Results.AddResult(Result("int", CCP_Type));
1226 Results.AddResult(Result("float", CCP_Type));
1227 Results.AddResult(Result("double", CCP_Type));
1228 Results.AddResult(Result("enum", CCP_Type));
1229 Results.AddResult(Result("struct", CCP_Type));
1230 Results.AddResult(Result("union", CCP_Type));
1231 Results.AddResult(Result("const", CCP_Type));
1232 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001233
Douglas Gregor86d9a522009-09-21 16:56:56 +00001234 if (LangOpts.C99) {
1235 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001236 Results.AddResult(Result("_Complex", CCP_Type));
1237 Results.AddResult(Result("_Imaginary", CCP_Type));
1238 Results.AddResult(Result("_Bool", CCP_Type));
1239 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001240 }
1241
Douglas Gregor218937c2011-02-01 19:23:04 +00001242 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001243 if (LangOpts.CPlusPlus) {
1244 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001245 Results.AddResult(Result("bool", CCP_Type +
1246 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001247 Results.AddResult(Result("class", CCP_Type));
1248 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001249
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001250 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001251 Builder.AddTypedTextChunk("typename");
1252 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1253 Builder.AddPlaceholderChunk("qualifier");
1254 Builder.AddTextChunk("::");
1255 Builder.AddPlaceholderChunk("name");
1256 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001257
Douglas Gregor86d9a522009-09-21 16:56:56 +00001258 if (LangOpts.CPlusPlus0x) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001259 Results.AddResult(Result("auto", CCP_Type));
1260 Results.AddResult(Result("char16_t", CCP_Type));
1261 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001262
Douglas Gregor218937c2011-02-01 19:23:04 +00001263 Builder.AddTypedTextChunk("decltype");
1264 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1265 Builder.AddPlaceholderChunk("expression");
1266 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1267 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001268 }
1269 }
1270
1271 // GNU extensions
1272 if (LangOpts.GNUMode) {
1273 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001274 // Results.AddResult(Result("_Decimal32"));
1275 // Results.AddResult(Result("_Decimal64"));
1276 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001277
Douglas Gregor218937c2011-02-01 19:23:04 +00001278 Builder.AddTypedTextChunk("typeof");
1279 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1280 Builder.AddPlaceholderChunk("expression");
1281 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001282
Douglas Gregor218937c2011-02-01 19:23:04 +00001283 Builder.AddTypedTextChunk("typeof");
1284 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1285 Builder.AddPlaceholderChunk("type");
1286 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1287 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001288 }
1289}
1290
John McCallf312b1e2010-08-26 23:41:50 +00001291static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001292 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001293 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001294 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001295 // Note: we don't suggest either "auto" or "register", because both
1296 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1297 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001298 Results.AddResult(Result("extern"));
1299 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001300}
1301
John McCallf312b1e2010-08-26 23:41:50 +00001302static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001303 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001304 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001305 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001306 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001307 case Sema::PCC_Class:
1308 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001309 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001310 Results.AddResult(Result("explicit"));
1311 Results.AddResult(Result("friend"));
1312 Results.AddResult(Result("mutable"));
1313 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001314 }
1315 // Fall through
1316
John McCallf312b1e2010-08-26 23:41:50 +00001317 case Sema::PCC_ObjCInterface:
1318 case Sema::PCC_ObjCImplementation:
1319 case Sema::PCC_Namespace:
1320 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001321 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001322 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001323 break;
1324
John McCallf312b1e2010-08-26 23:41:50 +00001325 case Sema::PCC_ObjCInstanceVariableList:
1326 case Sema::PCC_Expression:
1327 case Sema::PCC_Statement:
1328 case Sema::PCC_ForInit:
1329 case Sema::PCC_Condition:
1330 case Sema::PCC_RecoveryInFunction:
1331 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001332 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001333 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001334 break;
1335 }
1336}
1337
Douglas Gregorbca403c2010-01-13 23:51:12 +00001338static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1339static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1340static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001341 ResultBuilder &Results,
1342 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001343static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001344 ResultBuilder &Results,
1345 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001346static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001347 ResultBuilder &Results,
1348 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001349static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001350
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001351static void AddTypedefResult(ResultBuilder &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001352 CodeCompletionBuilder Builder(Results.getAllocator());
1353 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))
1417 return BT->getName(Policy);
1418
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();
1445 CodeCompletionBuilder Builder(Allocator);
1446 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();
1461 CodeCompletionBuilder Builder(Allocator);
1462 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");
1545 Builder.AddChunk(CodeCompletionString::CK_Colon);
1546 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001547
1548 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001549 Builder.AddTypedTextChunk("protected");
1550 Builder.AddChunk(CodeCompletionString::CK_Colon);
1551 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001552
1553 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001554 Builder.AddTypedTextChunk("private");
1555 Builder.AddChunk(CodeCompletionString::CK_Colon);
1556 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001557 }
1558 }
1559 // Fall through
1560
John McCallf312b1e2010-08-26 23:41:50 +00001561 case Sema::PCC_Template:
1562 case Sema::PCC_MemberTemplate:
David Blaikie4e4d0842012-03-11 07:00:24 +00001563 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001564 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001565 Builder.AddTypedTextChunk("template");
1566 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1567 Builder.AddPlaceholderChunk("parameters");
1568 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1569 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001570 }
1571
David Blaikie4e4d0842012-03-11 07:00:24 +00001572 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1573 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001574 break;
1575
John McCallf312b1e2010-08-26 23:41:50 +00001576 case Sema::PCC_ObjCInterface:
David Blaikie4e4d0842012-03-11 07:00:24 +00001577 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1578 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1579 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001580 break;
1581
John McCallf312b1e2010-08-26 23:41:50 +00001582 case Sema::PCC_ObjCImplementation:
David Blaikie4e4d0842012-03-11 07:00:24 +00001583 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1584 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1585 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001586 break;
1587
John McCallf312b1e2010-08-26 23:41:50 +00001588 case Sema::PCC_ObjCInstanceVariableList:
David Blaikie4e4d0842012-03-11 07:00:24 +00001589 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001590 break;
1591
John McCallf312b1e2010-08-26 23:41:50 +00001592 case Sema::PCC_RecoveryInFunction:
1593 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001594 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001595
David Blaikie4e4d0842012-03-11 07:00:24 +00001596 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1597 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001598 Builder.AddTypedTextChunk("try");
1599 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1600 Builder.AddPlaceholderChunk("statements");
1601 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1602 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1603 Builder.AddTextChunk("catch");
1604 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1605 Builder.AddPlaceholderChunk("declaration");
1606 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1607 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1608 Builder.AddPlaceholderChunk("statements");
1609 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1610 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1611 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001612 }
David Blaikie4e4d0842012-03-11 07:00:24 +00001613 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001614 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001615
Douglas Gregord8e8a582010-05-25 21:41:55 +00001616 if (Results.includeCodePatterns()) {
1617 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001618 Builder.AddTypedTextChunk("if");
1619 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001620 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001621 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001622 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001623 Builder.AddPlaceholderChunk("expression");
1624 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1625 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1626 Builder.AddPlaceholderChunk("statements");
1627 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1628 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1629 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001630
Douglas Gregord8e8a582010-05-25 21:41:55 +00001631 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001632 Builder.AddTypedTextChunk("switch");
1633 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001634 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001635 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001636 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001637 Builder.AddPlaceholderChunk("expression");
1638 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1639 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1640 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1641 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1642 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001643 }
1644
Douglas Gregor01dfea02010-01-10 23:08:15 +00001645 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001646 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001647 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001648 Builder.AddTypedTextChunk("case");
1649 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1650 Builder.AddPlaceholderChunk("expression");
1651 Builder.AddChunk(CodeCompletionString::CK_Colon);
1652 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001653
1654 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001655 Builder.AddTypedTextChunk("default");
1656 Builder.AddChunk(CodeCompletionString::CK_Colon);
1657 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001658 }
1659
Douglas Gregord8e8a582010-05-25 21:41:55 +00001660 if (Results.includeCodePatterns()) {
1661 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001662 Builder.AddTypedTextChunk("while");
1663 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001664 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001665 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001666 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001667 Builder.AddPlaceholderChunk("expression");
1668 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1669 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1670 Builder.AddPlaceholderChunk("statements");
1671 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1672 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1673 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001674
1675 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001676 Builder.AddTypedTextChunk("do");
1677 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1678 Builder.AddPlaceholderChunk("statements");
1679 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1680 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1681 Builder.AddTextChunk("while");
1682 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1683 Builder.AddPlaceholderChunk("expression");
1684 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1685 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001686
Douglas Gregord8e8a582010-05-25 21:41:55 +00001687 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001688 Builder.AddTypedTextChunk("for");
1689 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001690 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001691 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001692 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001693 Builder.AddPlaceholderChunk("init-expression");
1694 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1695 Builder.AddPlaceholderChunk("condition");
1696 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1697 Builder.AddPlaceholderChunk("inc-expression");
1698 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1699 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1700 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1701 Builder.AddPlaceholderChunk("statements");
1702 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1703 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1704 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001705 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001706
1707 if (S->getContinueParent()) {
1708 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001709 Builder.AddTypedTextChunk("continue");
1710 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001711 }
1712
1713 if (S->getBreakParent()) {
1714 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001715 Builder.AddTypedTextChunk("break");
1716 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001717 }
1718
1719 // "return expression ;" or "return ;", depending on whether we
1720 // know the function is void or not.
1721 bool isVoid = false;
1722 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1723 isVoid = Function->getResultType()->isVoidType();
1724 else if (ObjCMethodDecl *Method
1725 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1726 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001727 else if (SemaRef.getCurBlock() &&
1728 !SemaRef.getCurBlock()->ReturnType.isNull())
1729 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001730 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001731 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001732 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1733 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001734 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001735 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001736
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001737 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001738 Builder.AddTypedTextChunk("goto");
1739 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1740 Builder.AddPlaceholderChunk("label");
1741 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001742
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001743 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001744 Builder.AddTypedTextChunk("using");
1745 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1746 Builder.AddTextChunk("namespace");
1747 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1748 Builder.AddPlaceholderChunk("identifier");
1749 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001750 }
1751
1752 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001753 case Sema::PCC_ForInit:
1754 case Sema::PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00001755 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001756 // Fall through: conditions and statements can have expressions.
1757
Douglas Gregor02688102010-09-14 23:59:36 +00001758 case Sema::PCC_ParenthesizedExpression:
David Blaikie4e4d0842012-03-11 07:00:24 +00001759 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCallf85e1932011-06-15 23:02:42 +00001760 CCC == Sema::PCC_ParenthesizedExpression) {
1761 // (__bridge <type>)<expression>
1762 Builder.AddTypedTextChunk("__bridge");
1763 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1764 Builder.AddPlaceholderChunk("type");
1765 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1766 Builder.AddPlaceholderChunk("expression");
1767 Results.AddResult(Result(Builder.TakeString()));
1768
1769 // (__bridge_transfer <Objective-C type>)<expression>
1770 Builder.AddTypedTextChunk("__bridge_transfer");
1771 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1772 Builder.AddPlaceholderChunk("Objective-C type");
1773 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1774 Builder.AddPlaceholderChunk("expression");
1775 Results.AddResult(Result(Builder.TakeString()));
1776
1777 // (__bridge_retained <CF type>)<expression>
1778 Builder.AddTypedTextChunk("__bridge_retained");
1779 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1780 Builder.AddPlaceholderChunk("CF type");
1781 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1782 Builder.AddPlaceholderChunk("expression");
1783 Results.AddResult(Result(Builder.TakeString()));
1784 }
1785 // Fall through
1786
John McCallf312b1e2010-08-26 23:41:50 +00001787 case Sema::PCC_Expression: {
David Blaikie4e4d0842012-03-11 07:00:24 +00001788 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001789 // 'this', if we're in a non-static member function.
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001790 addThisCompletion(SemaRef, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001791
Douglas Gregor8ca72082011-10-18 21:20:17 +00001792 // true
1793 Builder.AddResultTypeChunk("bool");
1794 Builder.AddTypedTextChunk("true");
1795 Results.AddResult(Result(Builder.TakeString()));
1796
1797 // false
1798 Builder.AddResultTypeChunk("bool");
1799 Builder.AddTypedTextChunk("false");
1800 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001801
David Blaikie4e4d0842012-03-11 07:00:24 +00001802 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001803 // dynamic_cast < type-id > ( expression )
1804 Builder.AddTypedTextChunk("dynamic_cast");
1805 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1806 Builder.AddPlaceholderChunk("type");
1807 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1808 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1809 Builder.AddPlaceholderChunk("expression");
1810 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1811 Results.AddResult(Result(Builder.TakeString()));
1812 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001813
1814 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001815 Builder.AddTypedTextChunk("static_cast");
1816 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1817 Builder.AddPlaceholderChunk("type");
1818 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1819 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1820 Builder.AddPlaceholderChunk("expression");
1821 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1822 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001823
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001824 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001825 Builder.AddTypedTextChunk("reinterpret_cast");
1826 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1827 Builder.AddPlaceholderChunk("type");
1828 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1829 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1830 Builder.AddPlaceholderChunk("expression");
1831 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1832 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001833
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001834 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001835 Builder.AddTypedTextChunk("const_cast");
1836 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1837 Builder.AddPlaceholderChunk("type");
1838 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1839 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1840 Builder.AddPlaceholderChunk("expression");
1841 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1842 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001843
David Blaikie4e4d0842012-03-11 07:00:24 +00001844 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001845 // typeid ( expression-or-type )
Douglas Gregor8ca72082011-10-18 21:20:17 +00001846 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001847 Builder.AddTypedTextChunk("typeid");
1848 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1849 Builder.AddPlaceholderChunk("expression-or-type");
1850 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1851 Results.AddResult(Result(Builder.TakeString()));
1852 }
1853
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001854 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001855 Builder.AddTypedTextChunk("new");
1856 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1857 Builder.AddPlaceholderChunk("type");
1858 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1859 Builder.AddPlaceholderChunk("expressions");
1860 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1861 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001862
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001863 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001864 Builder.AddTypedTextChunk("new");
1865 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1866 Builder.AddPlaceholderChunk("type");
1867 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1868 Builder.AddPlaceholderChunk("size");
1869 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1870 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1871 Builder.AddPlaceholderChunk("expressions");
1872 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1873 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001874
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001875 // delete expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001876 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001877 Builder.AddTypedTextChunk("delete");
1878 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1879 Builder.AddPlaceholderChunk("expression");
1880 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001881
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001882 // delete [] expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001883 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001884 Builder.AddTypedTextChunk("delete");
1885 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1886 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1887 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1888 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1889 Builder.AddPlaceholderChunk("expression");
1890 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001891
David Blaikie4e4d0842012-03-11 07:00:24 +00001892 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001893 // throw expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001894 Builder.AddResultTypeChunk("void");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001895 Builder.AddTypedTextChunk("throw");
1896 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1897 Builder.AddPlaceholderChunk("expression");
1898 Results.AddResult(Result(Builder.TakeString()));
1899 }
Douglas Gregora50216c2011-10-18 16:29:03 +00001900
Douglas Gregor12e13132010-05-26 22:00:08 +00001901 // FIXME: Rethrow?
Douglas Gregora50216c2011-10-18 16:29:03 +00001902
David Blaikie4e4d0842012-03-11 07:00:24 +00001903 if (SemaRef.getLangOpts().CPlusPlus0x) {
Douglas Gregora50216c2011-10-18 16:29:03 +00001904 // nullptr
Douglas Gregor8ca72082011-10-18 21:20:17 +00001905 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001906 Builder.AddTypedTextChunk("nullptr");
1907 Results.AddResult(Result(Builder.TakeString()));
1908
1909 // alignof
Douglas Gregor8ca72082011-10-18 21:20:17 +00001910 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001911 Builder.AddTypedTextChunk("alignof");
1912 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1913 Builder.AddPlaceholderChunk("type");
1914 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1915 Results.AddResult(Result(Builder.TakeString()));
1916
1917 // noexcept
Douglas Gregor8ca72082011-10-18 21:20:17 +00001918 Builder.AddResultTypeChunk("bool");
Douglas Gregora50216c2011-10-18 16:29:03 +00001919 Builder.AddTypedTextChunk("noexcept");
1920 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1921 Builder.AddPlaceholderChunk("expression");
1922 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1923 Results.AddResult(Result(Builder.TakeString()));
1924
1925 // sizeof... expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001926 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001927 Builder.AddTypedTextChunk("sizeof...");
1928 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1929 Builder.AddPlaceholderChunk("parameter-pack");
1930 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1931 Results.AddResult(Result(Builder.TakeString()));
1932 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001933 }
1934
David Blaikie4e4d0842012-03-11 07:00:24 +00001935 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001936 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001937 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1938 // The interface can be NULL.
1939 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregor8ca72082011-10-18 21:20:17 +00001940 if (ID->getSuperClass()) {
1941 std::string SuperType;
1942 SuperType = ID->getSuperClass()->getNameAsString();
1943 if (Method->isInstanceMethod())
1944 SuperType += " *";
1945
1946 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1947 Builder.AddTypedTextChunk("super");
1948 Results.AddResult(Result(Builder.TakeString()));
1949 }
Ted Kremenek681e2562010-05-31 21:43:10 +00001950 }
1951
Douglas Gregorbca403c2010-01-13 23:51:12 +00001952 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001953 }
1954
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001955 // sizeof expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001956 Builder.AddResultTypeChunk("size_t");
Douglas Gregor218937c2011-02-01 19:23:04 +00001957 Builder.AddTypedTextChunk("sizeof");
1958 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1959 Builder.AddPlaceholderChunk("expression-or-type");
1960 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1961 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001962 break;
1963 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001964
John McCallf312b1e2010-08-26 23:41:50 +00001965 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001966 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00001967 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001968 }
1969
David Blaikie4e4d0842012-03-11 07:00:24 +00001970 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
1971 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001972
David Blaikie4e4d0842012-03-11 07:00:24 +00001973 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00001974 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001975}
1976
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001977/// \brief If the given declaration has an associated type, add it as a result
1978/// type chunk.
1979static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00001980 const PrintingPolicy &Policy,
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001981 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00001982 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001983 if (!ND)
1984 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00001985
1986 // Skip constructors and conversion functions, which have their return types
1987 // built into their names.
1988 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
1989 return;
1990
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001991 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00001992 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001993 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
1994 T = Function->getResultType();
1995 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
1996 T = Method->getResultType();
1997 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
1998 T = FunTmpl->getTemplatedDecl()->getResultType();
1999 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
2000 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
2001 else if (isa<UnresolvedUsingValueDecl>(ND)) {
2002 /* Do nothing: ignore unresolved using declarations*/
John McCallf85e1932011-06-15 23:02:42 +00002003 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002004 T = Value->getType();
John McCallf85e1932011-06-15 23:02:42 +00002005 } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002006 T = Property->getType();
2007
2008 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2009 return;
2010
Douglas Gregor8987b232011-09-27 23:30:47 +00002011 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002012 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002013}
2014
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002015static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00002016 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002017 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2018 if (Sentinel->getSentinel() == 0) {
David Blaikie4e4d0842012-03-11 07:00:24 +00002019 if (Context.getLangOpts().ObjC1 &&
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002020 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002021 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002022 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002023 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002024 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002025 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002026 }
2027}
2028
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002029static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2030 std::string Result;
2031 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002032 Result += "in ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002033 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002034 Result += "inout ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002035 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002036 Result += "out ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002037 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002038 Result += "bycopy ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002039 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002040 Result += "byref ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002041 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002042 Result += "oneway ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002043 return Result;
2044}
2045
Douglas Gregor83482d12010-08-24 16:15:59 +00002046static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002047 const PrintingPolicy &Policy,
Douglas Gregoraba48082010-08-29 19:47:46 +00002048 ParmVarDecl *Param,
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002049 bool SuppressName = false,
2050 bool SuppressBlock = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00002051 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2052 if (Param->getType()->isDependentType() ||
2053 !Param->getType()->isBlockPointerType()) {
2054 // The argument for a dependent or non-block parameter is a placeholder
2055 // containing that parameter's type.
2056 std::string Result;
2057
Douglas Gregoraba48082010-08-29 19:47:46 +00002058 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002059 Result = Param->getIdentifier()->getName();
2060
John McCallf85e1932011-06-15 23:02:42 +00002061 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002062
2063 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002064 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2065 + Result + ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00002066 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002067 Result += Param->getIdentifier()->getName();
2068 }
2069 return Result;
2070 }
2071
2072 // The argument for a block pointer parameter is a block literal with
2073 // the appropriate type.
Douglas Gregor830072c2011-02-15 22:37:09 +00002074 FunctionTypeLoc *Block = 0;
2075 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregor83482d12010-08-24 16:15:59 +00002076 TypeLoc TL;
2077 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2078 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2079 while (true) {
2080 // Look through typedefs.
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002081 if (!SuppressBlock) {
2082 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2083 if (TypeSourceInfo *InnerTSInfo
2084 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2085 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2086 continue;
2087 }
2088 }
2089
2090 // Look through qualified types
2091 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2092 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregor83482d12010-08-24 16:15:59 +00002093 continue;
2094 }
2095 }
2096
Douglas Gregor83482d12010-08-24 16:15:59 +00002097 // Try to get the function prototype behind the block pointer type,
2098 // then we're done.
2099 if (BlockPointerTypeLoc *BlockPtr
2100 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00002101 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor830072c2011-02-15 22:37:09 +00002102 Block = dyn_cast<FunctionTypeLoc>(&TL);
2103 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregor83482d12010-08-24 16:15:59 +00002104 }
2105 break;
2106 }
2107 }
2108
2109 if (!Block) {
2110 // We were unable to find a FunctionProtoTypeLoc with parameter names
2111 // for the block; just use the parameter type as a placeholder.
2112 std::string Result;
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002113 if (!ObjCMethodParam && Param->getIdentifier())
2114 Result = Param->getIdentifier()->getName();
2115
John McCallf85e1932011-06-15 23:02:42 +00002116 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002117
2118 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002119 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2120 + Result + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002121 if (Param->getIdentifier())
2122 Result += Param->getIdentifier()->getName();
2123 }
2124
2125 return Result;
2126 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002127
Douglas Gregor83482d12010-08-24 16:15:59 +00002128 // We have the function prototype behind the block pointer type, as it was
2129 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00002130 std::string Result;
2131 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002132 if (!ResultType->isVoidType() || SuppressBlock)
John McCallf85e1932011-06-15 23:02:42 +00002133 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002134
2135 // Format the parameter list.
2136 std::string Params;
Douglas Gregor830072c2011-02-15 22:37:09 +00002137 if (!BlockProto || Block->getNumArgs() == 0) {
2138 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002139 Params = "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00002140 else
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002141 Params = "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00002142 } else {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002143 Params += "(";
Douglas Gregor38276252010-09-08 22:47:51 +00002144 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2145 if (I)
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002146 Params += ", ";
2147 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2148 /*SuppressName=*/false,
2149 /*SuppressBlock=*/true);
Douglas Gregor38276252010-09-08 22:47:51 +00002150
Douglas Gregor830072c2011-02-15 22:37:09 +00002151 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002152 Params += ", ...";
Douglas Gregor38276252010-09-08 22:47:51 +00002153 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002154 Params += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00002155 }
Douglas Gregor38276252010-09-08 22:47:51 +00002156
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002157 if (SuppressBlock) {
2158 // Format as a parameter.
2159 Result = Result + " (^";
2160 if (Param->getIdentifier())
2161 Result += Param->getIdentifier()->getName();
2162 Result += ")";
2163 Result += Params;
2164 } else {
2165 // Format as a block literal argument.
2166 Result = '^' + Result;
2167 Result += Params;
2168
2169 if (Param->getIdentifier())
2170 Result += Param->getIdentifier()->getName();
2171 }
2172
Douglas Gregor83482d12010-08-24 16:15:59 +00002173 return Result;
2174}
2175
Douglas Gregor86d9a522009-09-21 16:56:56 +00002176/// \brief Add function parameter chunks to the given code completion string.
2177static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002178 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002179 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00002180 CodeCompletionBuilder &Result,
2181 unsigned Start = 0,
2182 bool InOptional = false) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002183 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002184
Douglas Gregor218937c2011-02-01 19:23:04 +00002185 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002186 ParmVarDecl *Param = Function->getParamDecl(P);
2187
Douglas Gregor218937c2011-02-01 19:23:04 +00002188 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002189 // When we see an optional default argument, put that argument and
2190 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002191 CodeCompletionBuilder Opt(Result.getAllocator());
2192 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002193 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002194 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregor218937c2011-02-01 19:23:04 +00002195 Result.AddOptionalChunk(Opt.TakeString());
2196 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002197 }
2198
Douglas Gregor218937c2011-02-01 19:23:04 +00002199 if (FirstParameter)
2200 FirstParameter = false;
2201 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002202 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor218937c2011-02-01 19:23:04 +00002203
2204 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002205
2206 // Format the placeholder string.
Douglas Gregor8987b232011-09-27 23:30:47 +00002207 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2208 Param);
Douglas Gregor83482d12010-08-24 16:15:59 +00002209
Douglas Gregore17794f2010-08-31 05:13:43 +00002210 if (Function->isVariadic() && P == N - 1)
2211 PlaceholderStr += ", ...";
2212
Douglas Gregor86d9a522009-09-21 16:56:56 +00002213 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002214 Result.AddPlaceholderChunk(
2215 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002216 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002217
2218 if (const FunctionProtoType *Proto
2219 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002220 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002221 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002222 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002223
Douglas Gregor218937c2011-02-01 19:23:04 +00002224 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002225 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002226}
2227
2228/// \brief Add template parameter chunks to the given code completion string.
2229static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002230 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002231 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002232 CodeCompletionBuilder &Result,
2233 unsigned MaxParameters = 0,
2234 unsigned Start = 0,
2235 bool InDefaultArg = false) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002236 bool FirstParameter = true;
2237
2238 TemplateParameterList *Params = Template->getTemplateParameters();
2239 TemplateParameterList::iterator PEnd = Params->end();
2240 if (MaxParameters)
2241 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002242 for (TemplateParameterList::iterator P = Params->begin() + Start;
2243 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002244 bool HasDefaultArg = false;
2245 std::string PlaceholderStr;
2246 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2247 if (TTP->wasDeclaredWithTypename())
2248 PlaceholderStr = "typename";
2249 else
2250 PlaceholderStr = "class";
2251
2252 if (TTP->getIdentifier()) {
2253 PlaceholderStr += ' ';
2254 PlaceholderStr += TTP->getIdentifier()->getName();
2255 }
2256
2257 HasDefaultArg = TTP->hasDefaultArgument();
2258 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002259 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002260 if (NTTP->getIdentifier())
2261 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCallf85e1932011-06-15 23:02:42 +00002262 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002263 HasDefaultArg = NTTP->hasDefaultArgument();
2264 } else {
2265 assert(isa<TemplateTemplateParmDecl>(*P));
2266 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2267
2268 // Since putting the template argument list into the placeholder would
2269 // be very, very long, we just use an abbreviation.
2270 PlaceholderStr = "template<...> class";
2271 if (TTP->getIdentifier()) {
2272 PlaceholderStr += ' ';
2273 PlaceholderStr += TTP->getIdentifier()->getName();
2274 }
2275
2276 HasDefaultArg = TTP->hasDefaultArgument();
2277 }
2278
Douglas Gregor218937c2011-02-01 19:23:04 +00002279 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002280 // When we see an optional default argument, put that argument and
2281 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002282 CodeCompletionBuilder Opt(Result.getAllocator());
2283 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002284 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002285 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregor218937c2011-02-01 19:23:04 +00002286 P - Params->begin(), true);
2287 Result.AddOptionalChunk(Opt.TakeString());
2288 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002289 }
2290
Douglas Gregor218937c2011-02-01 19:23:04 +00002291 InDefaultArg = false;
2292
Douglas Gregor86d9a522009-09-21 16:56:56 +00002293 if (FirstParameter)
2294 FirstParameter = false;
2295 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002296 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002297
2298 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002299 Result.AddPlaceholderChunk(
2300 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002301 }
2302}
2303
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002304/// \brief Add a qualifier to the given code-completion string, if the
2305/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002306static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002307AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002308 NestedNameSpecifier *Qualifier,
2309 bool QualifierIsInformative,
Douglas Gregor8987b232011-09-27 23:30:47 +00002310 ASTContext &Context,
2311 const PrintingPolicy &Policy) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002312 if (!Qualifier)
2313 return;
2314
2315 std::string PrintedNNS;
2316 {
2317 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor8987b232011-09-27 23:30:47 +00002318 Qualifier->print(OS, Policy);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002319 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002320 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002321 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002322 else
Douglas Gregordae68752011-02-01 22:57:45 +00002323 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002324}
2325
Douglas Gregor218937c2011-02-01 19:23:04 +00002326static void
2327AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2328 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002329 const FunctionProtoType *Proto
2330 = Function->getType()->getAs<FunctionProtoType>();
2331 if (!Proto || !Proto->getTypeQuals())
2332 return;
2333
Douglas Gregora63f6de2011-02-01 21:15:40 +00002334 // FIXME: Add ref-qualifier!
2335
2336 // Handle single qualifiers without copying
2337 if (Proto->getTypeQuals() == Qualifiers::Const) {
2338 Result.AddInformativeChunk(" const");
2339 return;
2340 }
2341
2342 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2343 Result.AddInformativeChunk(" volatile");
2344 return;
2345 }
2346
2347 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2348 Result.AddInformativeChunk(" restrict");
2349 return;
2350 }
2351
2352 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002353 std::string QualsStr;
2354 if (Proto->getTypeQuals() & Qualifiers::Const)
2355 QualsStr += " const";
2356 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2357 QualsStr += " volatile";
2358 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2359 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002360 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002361}
2362
Douglas Gregor6f942b22010-09-21 16:06:22 +00002363/// \brief Add the name of the given declaration
Douglas Gregor8987b232011-09-27 23:30:47 +00002364static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
2365 NamedDecl *ND, CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002366 DeclarationName Name = ND->getDeclName();
2367 if (!Name)
2368 return;
2369
2370 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002371 case DeclarationName::CXXOperatorName: {
2372 const char *OperatorName = 0;
2373 switch (Name.getCXXOverloadedOperator()) {
2374 case OO_None:
2375 case OO_Conditional:
2376 case NUM_OVERLOADED_OPERATORS:
2377 OperatorName = "operator";
2378 break;
2379
2380#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2381 case OO_##Name: OperatorName = "operator" Spelling; break;
2382#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2383#include "clang/Basic/OperatorKinds.def"
2384
2385 case OO_New: OperatorName = "operator new"; break;
2386 case OO_Delete: OperatorName = "operator delete"; break;
2387 case OO_Array_New: OperatorName = "operator new[]"; break;
2388 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2389 case OO_Call: OperatorName = "operator()"; break;
2390 case OO_Subscript: OperatorName = "operator[]"; break;
2391 }
2392 Result.AddTypedTextChunk(OperatorName);
2393 break;
2394 }
2395
Douglas Gregor6f942b22010-09-21 16:06:22 +00002396 case DeclarationName::Identifier:
2397 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002398 case DeclarationName::CXXDestructorName:
2399 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002400 Result.AddTypedTextChunk(
2401 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002402 break;
2403
2404 case DeclarationName::CXXUsingDirective:
2405 case DeclarationName::ObjCZeroArgSelector:
2406 case DeclarationName::ObjCOneArgSelector:
2407 case DeclarationName::ObjCMultiArgSelector:
2408 break;
2409
2410 case DeclarationName::CXXConstructorName: {
2411 CXXRecordDecl *Record = 0;
2412 QualType Ty = Name.getCXXNameType();
2413 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2414 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2415 else if (const InjectedClassNameType *InjectedTy
2416 = Ty->getAs<InjectedClassNameType>())
2417 Record = InjectedTy->getDecl();
2418 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002419 Result.AddTypedTextChunk(
2420 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002421 break;
2422 }
2423
Douglas Gregordae68752011-02-01 22:57:45 +00002424 Result.AddTypedTextChunk(
2425 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002426 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002427 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor8987b232011-09-27 23:30:47 +00002428 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002429 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002430 }
2431 break;
2432 }
2433 }
2434}
2435
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002436CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
2437 CodeCompletionAllocator &Allocator) {
2438 return CreateCodeCompletionString(S.Context, S.PP, Allocator);
2439}
2440
Douglas Gregor86d9a522009-09-21 16:56:56 +00002441/// \brief If possible, create a new code completion string for the given
2442/// result.
2443///
2444/// \returns Either a new, heap-allocated code completion string describing
2445/// how to use this result, or NULL to indicate that the string or name of the
2446/// result is all that is needed.
2447CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002448CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2449 Preprocessor &PP,
Douglas Gregordae68752011-02-01 22:57:45 +00002450 CodeCompletionAllocator &Allocator) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002451 CodeCompletionBuilder Result(Allocator, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002452
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002453 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002454 if (Kind == RK_Pattern) {
2455 Pattern->Priority = Priority;
2456 Pattern->Availability = Availability;
Douglas Gregorba103062012-03-27 23:34:16 +00002457
2458 if (Declaration) {
2459 Result.addParentContext(Declaration->getDeclContext());
2460 Pattern->ParentKind = Result.getParentKind();
2461 Pattern->ParentName = Result.getParentName();
2462 }
2463
Douglas Gregor218937c2011-02-01 19:23:04 +00002464 return Pattern;
2465 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002466
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002467 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002468 Result.AddTypedTextChunk(Keyword);
2469 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002470 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002471
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002472 if (Kind == RK_Macro) {
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002473 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002474 assert(MI && "Not a macro?");
2475
Douglas Gregordae68752011-02-01 22:57:45 +00002476 Result.AddTypedTextChunk(
2477 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002478
2479 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002480 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002481
2482 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002483 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregore4244702011-07-30 08:17:44 +00002484 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002485
2486 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2487 if (MI->isC99Varargs()) {
2488 --AEnd;
2489
2490 if (A == AEnd) {
2491 Result.AddPlaceholderChunk("...");
2492 }
Douglas Gregore4244702011-07-30 08:17:44 +00002493 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002494
Douglas Gregore4244702011-07-30 08:17:44 +00002495 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002496 if (A != MI->arg_begin())
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002497 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002498
2499 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002500 SmallString<32> Arg = (*A)->getName();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002501 if (MI->isC99Varargs())
2502 Arg += ", ...";
2503 else
2504 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002505 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002506 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002507 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002508
2509 // Non-variadic macros are simple.
2510 Result.AddPlaceholderChunk(
2511 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002512 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002513 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002514 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002515 }
2516
Douglas Gregord8e8a582010-05-25 21:41:55 +00002517 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002518 NamedDecl *ND = Declaration;
Douglas Gregorba103062012-03-27 23:34:16 +00002519 Result.addParentContext(ND->getDeclContext());
2520
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002521 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002522 Result.AddTypedTextChunk(
2523 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002524 Result.AddTextChunk("::");
2525 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002526 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002527
2528 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2529 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2530 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2531 }
2532 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002533
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002534 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002535
Douglas Gregor86d9a522009-09-21 16:56:56 +00002536 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002537 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002538 Ctx, Policy);
2539 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002540 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002541 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002542 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002543 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002544 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002545 }
2546
2547 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002548 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002549 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002550 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002551 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002552
Douglas Gregor86d9a522009-09-21 16:56:56 +00002553 // Figure out which template parameters are deduced (or have default
2554 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002555 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002556 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002557 unsigned LastDeducibleArgument;
2558 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2559 --LastDeducibleArgument) {
2560 if (!Deduced[LastDeducibleArgument - 1]) {
2561 // C++0x: Figure out if the template argument has a default. If so,
2562 // the user doesn't need to type this argument.
2563 // FIXME: We need to abstract template parameters better!
2564 bool HasDefaultArg = false;
2565 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002566 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002567 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2568 HasDefaultArg = TTP->hasDefaultArgument();
2569 else if (NonTypeTemplateParmDecl *NTTP
2570 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2571 HasDefaultArg = NTTP->hasDefaultArgument();
2572 else {
2573 assert(isa<TemplateTemplateParmDecl>(Param));
2574 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002575 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002576 }
2577
2578 if (!HasDefaultArg)
2579 break;
2580 }
2581 }
2582
2583 if (LastDeducibleArgument) {
2584 // Some of the function template arguments cannot be deduced from a
2585 // function call, so we introduce an explicit template argument list
2586 // containing all of the arguments up to the first deducible argument.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002587 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002588 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002589 LastDeducibleArgument);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002590 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002591 }
2592
2593 // Add the function parameters
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002594 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002595 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002596 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002597 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002598 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002599 }
2600
2601 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002602 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002603 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002604 Result.AddTypedTextChunk(
2605 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002606 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002607 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002608 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor218937c2011-02-01 19:23:04 +00002609 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002610 }
2611
Douglas Gregor9630eb62009-11-17 16:44:22 +00002612 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002613 Selector Sel = Method->getSelector();
2614 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002615 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002616 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002617 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002618 }
2619
Douglas Gregor813d8342011-02-18 22:29:55 +00002620 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002621 SelName += ':';
2622 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002623 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002624 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002625 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002626
2627 // If there is only one parameter, and we're past it, add an empty
2628 // typed-text chunk since there is nothing to type.
2629 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002630 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002631 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002632 unsigned Idx = 0;
2633 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2634 PEnd = Method->param_end();
2635 P != PEnd; (void)++P, ++Idx) {
2636 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002637 std::string Keyword;
2638 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002639 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002640 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002641 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002642 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002643 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002644 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002645 else
Douglas Gregordae68752011-02-01 22:57:45 +00002646 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002647 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002648
2649 // If we're before the starting parameter, skip the placeholder.
2650 if (Idx < StartParameter)
2651 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002652
2653 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002654
2655 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002656 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002657 else {
John McCallf85e1932011-06-15 23:02:42 +00002658 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002659 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2660 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002661 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002662 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002663 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002664 }
2665
Douglas Gregore17794f2010-08-31 05:13:43 +00002666 if (Method->isVariadic() && (P + 1) == PEnd)
2667 Arg += ", ...";
2668
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002669 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002670 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002671 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002672 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002673 else
Douglas Gregordae68752011-02-01 22:57:45 +00002674 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002675 }
2676
Douglas Gregor2a17af02009-12-23 00:21:46 +00002677 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002678 if (Method->param_size() == 0) {
2679 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002680 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002681 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002682 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002683 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002684 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002685 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002686
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002687 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002688 }
2689
Douglas Gregor218937c2011-02-01 19:23:04 +00002690 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002691 }
2692
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002693 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002694 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002695 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002696
Douglas Gregordae68752011-02-01 22:57:45 +00002697 Result.AddTypedTextChunk(
2698 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002699 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002700}
2701
Douglas Gregor86d802e2009-09-23 00:34:09 +00002702CodeCompletionString *
2703CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2704 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002705 Sema &S,
Douglas Gregordae68752011-02-01 22:57:45 +00002706 CodeCompletionAllocator &Allocator) const {
Douglas Gregor8987b232011-09-27 23:30:47 +00002707 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002708
Douglas Gregor218937c2011-02-01 19:23:04 +00002709 // FIXME: Set priority, availability appropriately.
2710 CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002711 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002712 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002713 const FunctionProtoType *Proto
2714 = dyn_cast<FunctionProtoType>(getFunctionType());
2715 if (!FDecl && !Proto) {
2716 // Function without a prototype. Just give the return type and a
2717 // highlighted ellipsis.
2718 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002719 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002720 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002721 Result.getAllocator()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002722 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2723 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2724 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002725 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002726 }
2727
2728 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002729 Result.AddTextChunk(
2730 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002731 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002732 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002733 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002734 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002735
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002736 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002737 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2738 for (unsigned I = 0; I != NumParams; ++I) {
2739 if (I)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002740 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002741
2742 std::string ArgString;
2743 QualType ArgType;
2744
2745 if (FDecl) {
2746 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2747 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2748 } else {
2749 ArgType = Proto->getArgType(I);
2750 }
2751
John McCallf85e1932011-06-15 23:02:42 +00002752 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002753
2754 if (I == CurrentArg)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002755 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2756 Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002757 else
Douglas Gregordae68752011-02-01 22:57:45 +00002758 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002759 }
2760
2761 if (Proto && Proto->isVariadic()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002762 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002763 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002764 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002765 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002766 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002767 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002768 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002769
Douglas Gregor218937c2011-02-01 19:23:04 +00002770 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002771}
2772
Chris Lattner5f9e2722011-07-23 10:55:15 +00002773unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002774 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002775 bool PreferredTypeIsPointer) {
2776 unsigned Priority = CCP_Macro;
2777
Douglas Gregorb05496d2010-09-20 21:11:48 +00002778 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2779 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2780 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002781 Priority = CCP_Constant;
2782 if (PreferredTypeIsPointer)
2783 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002784 }
2785 // Treat "YES", "NO", "true", and "false" as constants.
2786 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2787 MacroName.equals("true") || MacroName.equals("false"))
2788 Priority = CCP_Constant;
2789 // Treat "bool" as a type.
2790 else if (MacroName.equals("bool"))
2791 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2792
Douglas Gregor1827e102010-08-16 16:18:59 +00002793
2794 return Priority;
2795}
2796
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002797CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2798 if (!D)
2799 return CXCursor_UnexposedDecl;
2800
2801 switch (D->getKind()) {
2802 case Decl::Enum: return CXCursor_EnumDecl;
2803 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2804 case Decl::Field: return CXCursor_FieldDecl;
2805 case Decl::Function:
2806 return CXCursor_FunctionDecl;
2807 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2808 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002809 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002810
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002811 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002812 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2813 case Decl::ObjCMethod:
2814 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2815 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2816 case Decl::CXXMethod: return CXCursor_CXXMethod;
2817 case Decl::CXXConstructor: return CXCursor_Constructor;
2818 case Decl::CXXDestructor: return CXCursor_Destructor;
2819 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2820 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002821 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002822 case Decl::ParmVar: return CXCursor_ParmDecl;
2823 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002824 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002825 case Decl::Var: return CXCursor_VarDecl;
2826 case Decl::Namespace: return CXCursor_Namespace;
2827 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2828 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2829 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2830 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2831 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2832 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002833 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002834 case Decl::ClassTemplatePartialSpecialization:
2835 return CXCursor_ClassTemplatePartialSpecialization;
2836 case Decl::UsingDirective: return CXCursor_UsingDirective;
2837
2838 case Decl::Using:
2839 case Decl::UnresolvedUsingValue:
2840 case Decl::UnresolvedUsingTypename:
2841 return CXCursor_UsingDeclaration;
2842
Douglas Gregor352697a2011-06-03 23:08:58 +00002843 case Decl::ObjCPropertyImpl:
2844 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2845 case ObjCPropertyImplDecl::Dynamic:
2846 return CXCursor_ObjCDynamicDecl;
2847
2848 case ObjCPropertyImplDecl::Synthesize:
2849 return CXCursor_ObjCSynthesizeDecl;
2850 }
Douglas Gregor352697a2011-06-03 23:08:58 +00002851
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002852 default:
2853 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2854 switch (TD->getTagKind()) {
2855 case TTK_Struct: return CXCursor_StructDecl;
2856 case TTK_Class: return CXCursor_ClassDecl;
2857 case TTK_Union: return CXCursor_UnionDecl;
2858 case TTK_Enum: return CXCursor_EnumDecl;
2859 }
2860 }
2861 }
2862
2863 return CXCursor_UnexposedDecl;
2864}
2865
Douglas Gregor590c7d52010-07-08 20:55:51 +00002866static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2867 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002868 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002869
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002870 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002871
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002872 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2873 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002874 M != MEnd; ++M) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002875 Results.AddResult(Result(M->first,
2876 getMacroUsagePriority(M->first->getName(),
David Blaikie4e4d0842012-03-11 07:00:24 +00002877 PP.getLangOpts(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002878 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002879 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002880
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002881 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002882
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002883}
2884
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002885static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2886 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002887 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002888
2889 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002890
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002891 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2892 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2893 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2894 Results.AddResult(Result("__func__", CCP_Constant));
2895 Results.ExitScope();
2896}
2897
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002898static void HandleCodeCompleteResults(Sema *S,
2899 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002900 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002901 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002902 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002903 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002904 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002905}
2906
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002907static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2908 Sema::ParserCompletionContext PCC) {
2909 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002910 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002911 return CodeCompletionContext::CCC_TopLevel;
2912
John McCallf312b1e2010-08-26 23:41:50 +00002913 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002914 return CodeCompletionContext::CCC_ClassStructUnion;
2915
John McCallf312b1e2010-08-26 23:41:50 +00002916 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002917 return CodeCompletionContext::CCC_ObjCInterface;
2918
John McCallf312b1e2010-08-26 23:41:50 +00002919 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002920 return CodeCompletionContext::CCC_ObjCImplementation;
2921
John McCallf312b1e2010-08-26 23:41:50 +00002922 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002923 return CodeCompletionContext::CCC_ObjCIvarList;
2924
John McCallf312b1e2010-08-26 23:41:50 +00002925 case Sema::PCC_Template:
2926 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002927 if (S.CurContext->isFileContext())
2928 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002929 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002930 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002931 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002932
John McCallf312b1e2010-08-26 23:41:50 +00002933 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002934 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002935
John McCallf312b1e2010-08-26 23:41:50 +00002936 case Sema::PCC_ForInit:
David Blaikie4e4d0842012-03-11 07:00:24 +00002937 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2938 S.getLangOpts().ObjC1)
Douglas Gregora5450a02010-10-18 22:01:46 +00002939 return CodeCompletionContext::CCC_ParenthesizedExpression;
2940 else
2941 return CodeCompletionContext::CCC_Expression;
2942
2943 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002944 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002945 return CodeCompletionContext::CCC_Expression;
2946
John McCallf312b1e2010-08-26 23:41:50 +00002947 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002948 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002949
John McCallf312b1e2010-08-26 23:41:50 +00002950 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002951 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002952
2953 case Sema::PCC_ParenthesizedExpression:
2954 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002955
2956 case Sema::PCC_LocalDeclarationSpecifiers:
2957 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002958 }
David Blaikie7530c032012-01-17 06:56:22 +00002959
2960 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002961}
2962
Douglas Gregorf6961522010-08-27 21:18:54 +00002963/// \brief If we're in a C++ virtual member function, add completion results
2964/// that invoke the functions we override, since it's common to invoke the
2965/// overridden function as well as adding new functionality.
2966///
2967/// \param S The semantic analysis object for which we are generating results.
2968///
2969/// \param InContext This context in which the nested-name-specifier preceding
2970/// the code-completion point
2971static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2972 ResultBuilder &Results) {
2973 // Look through blocks.
2974 DeclContext *CurContext = S.CurContext;
2975 while (isa<BlockDecl>(CurContext))
2976 CurContext = CurContext->getParent();
2977
2978
2979 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2980 if (!Method || !Method->isVirtual())
2981 return;
2982
2983 // We need to have names for all of the parameters, if we're going to
2984 // generate a forwarding call.
2985 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2986 PEnd = Method->param_end();
2987 P != PEnd;
2988 ++P) {
2989 if (!(*P)->getDeclName())
2990 return;
2991 }
2992
Douglas Gregor8987b232011-09-27 23:30:47 +00002993 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00002994 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
2995 MEnd = Method->end_overridden_methods();
2996 M != MEnd; ++M) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002997 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf6961522010-08-27 21:18:54 +00002998 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
2999 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3000 continue;
3001
3002 // If we need a nested-name-specifier, add one now.
3003 if (!InContext) {
3004 NestedNameSpecifier *NNS
3005 = getRequiredQualification(S.Context, CurContext,
3006 Overridden->getDeclContext());
3007 if (NNS) {
3008 std::string Str;
3009 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00003010 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00003011 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003012 }
3013 } else if (!InContext->Equals(Overridden->getDeclContext()))
3014 continue;
3015
Douglas Gregordae68752011-02-01 22:57:45 +00003016 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003017 Overridden->getNameAsString()));
3018 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00003019 bool FirstParam = true;
3020 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3021 PEnd = Method->param_end();
3022 P != PEnd; ++P) {
3023 if (FirstParam)
3024 FirstParam = false;
3025 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003026 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003027
Douglas Gregordae68752011-02-01 22:57:45 +00003028 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003029 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003030 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003031 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3032 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003033 CCP_SuperCompletion,
Douglas Gregorba103062012-03-27 23:34:16 +00003034 CXCursor_CXXMethod,
3035 CXAvailability_Available,
3036 Overridden));
Douglas Gregorf6961522010-08-27 21:18:54 +00003037 Results.Ignore(Overridden);
3038 }
3039}
3040
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003041void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3042 ModuleIdPath Path) {
3043 typedef CodeCompletionResult Result;
3044 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3045 CodeCompletionContext::CCC_Other);
3046 Results.EnterNewScope();
3047
3048 CodeCompletionAllocator &Allocator = Results.getAllocator();
3049 CodeCompletionBuilder Builder(Allocator);
3050 typedef CodeCompletionResult Result;
3051 if (Path.empty()) {
3052 // Enumerate all top-level modules.
3053 llvm::SmallVector<Module *, 8> Modules;
3054 PP.getHeaderSearchInfo().collectAllModules(Modules);
3055 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3056 Builder.AddTypedTextChunk(
3057 Builder.getAllocator().CopyString(Modules[I]->Name));
3058 Results.AddResult(Result(Builder.TakeString(),
3059 CCP_Declaration,
3060 CXCursor_NotImplemented,
3061 Modules[I]->isAvailable()
3062 ? CXAvailability_Available
3063 : CXAvailability_NotAvailable));
3064 }
3065 } else {
3066 // Load the named module.
3067 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3068 Module::AllVisible,
3069 /*IsInclusionDirective=*/false);
3070 // Enumerate submodules.
3071 if (Mod) {
3072 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3073 SubEnd = Mod->submodule_end();
3074 Sub != SubEnd; ++Sub) {
3075
3076 Builder.AddTypedTextChunk(
3077 Builder.getAllocator().CopyString((*Sub)->Name));
3078 Results.AddResult(Result(Builder.TakeString(),
3079 CCP_Declaration,
3080 CXCursor_NotImplemented,
3081 (*Sub)->isAvailable()
3082 ? CXAvailability_Available
3083 : CXAvailability_NotAvailable));
3084 }
3085 }
3086 }
3087 Results.ExitScope();
3088 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3089 Results.data(),Results.size());
3090}
3091
Douglas Gregor01dfea02010-01-10 23:08:15 +00003092void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003093 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00003094 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003095 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003096 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003097 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003098
Douglas Gregor01dfea02010-01-10 23:08:15 +00003099 // Determine how to filter results, e.g., so that the names of
3100 // values (functions, enumerators, function templates, etc.) are
3101 // only allowed where we can have an expression.
3102 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003103 case PCC_Namespace:
3104 case PCC_Class:
3105 case PCC_ObjCInterface:
3106 case PCC_ObjCImplementation:
3107 case PCC_ObjCInstanceVariableList:
3108 case PCC_Template:
3109 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003110 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003111 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003112 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3113 break;
3114
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003115 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003116 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003117 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003118 case PCC_ForInit:
3119 case PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00003120 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003121 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3122 else
3123 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003124
David Blaikie4e4d0842012-03-11 07:00:24 +00003125 if (getLangOpts().CPlusPlus)
Douglas Gregorf6961522010-08-27 21:18:54 +00003126 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003127 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003128
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003129 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003130 // Unfiltered
3131 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003132 }
3133
Douglas Gregor3cdee122010-08-26 16:36:48 +00003134 // If we are in a C++ non-static member function, check the qualifiers on
3135 // the member function to filter/prioritize the results list.
3136 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3137 if (CurMethod->isInstance())
3138 Results.setObjectTypeQualifiers(
3139 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3140
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003141 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003142 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3143 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003144
Douglas Gregorbca403c2010-01-13 23:51:12 +00003145 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003146 Results.ExitScope();
3147
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003148 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003149 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003150 case PCC_Expression:
3151 case PCC_Statement:
3152 case PCC_RecoveryInFunction:
3153 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003154 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor72db1082010-08-24 01:11:00 +00003155 break;
3156
3157 case PCC_Namespace:
3158 case PCC_Class:
3159 case PCC_ObjCInterface:
3160 case PCC_ObjCImplementation:
3161 case PCC_ObjCInstanceVariableList:
3162 case PCC_Template:
3163 case PCC_MemberTemplate:
3164 case PCC_ForInit:
3165 case PCC_Condition:
3166 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003167 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003168 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003169 }
3170
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003171 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003172 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003173
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003174 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003175 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003176}
3177
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003178static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3179 ParsedType Receiver,
3180 IdentifierInfo **SelIdents,
3181 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003182 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003183 bool IsSuper,
3184 ResultBuilder &Results);
3185
3186void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3187 bool AllowNonIdentifiers,
3188 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003189 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003190 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003191 AllowNestedNameSpecifiers
3192 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3193 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003194 Results.EnterNewScope();
3195
3196 // Type qualifiers can come after names.
3197 Results.AddResult(Result("const"));
3198 Results.AddResult(Result("volatile"));
David Blaikie4e4d0842012-03-11 07:00:24 +00003199 if (getLangOpts().C99)
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003200 Results.AddResult(Result("restrict"));
3201
David Blaikie4e4d0842012-03-11 07:00:24 +00003202 if (getLangOpts().CPlusPlus) {
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003203 if (AllowNonIdentifiers) {
3204 Results.AddResult(Result("operator"));
3205 }
3206
3207 // Add nested-name-specifiers.
3208 if (AllowNestedNameSpecifiers) {
3209 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003210 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003211 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3212 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3213 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003214 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003215 }
3216 }
3217 Results.ExitScope();
3218
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003219 // If we're in a context where we might have an expression (rather than a
3220 // declaration), and what we've seen so far is an Objective-C type that could
3221 // be a receiver of a class message, this may be a class message send with
3222 // the initial opening bracket '[' missing. Add appropriate completions.
3223 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3224 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3225 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3226 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3227 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3228 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3229 DS.getTypeQualifiers() == 0 &&
3230 S &&
3231 (S->getFlags() & Scope::DeclScope) != 0 &&
3232 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3233 Scope::FunctionPrototypeScope |
3234 Scope::AtCatchScope)) == 0) {
3235 ParsedType T = DS.getRepAsType();
3236 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003237 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003238 }
3239
Douglas Gregor4497dd42010-08-24 04:59:56 +00003240 // Note that we intentionally suppress macro results here, since we do not
3241 // encourage using macros to produce the names of entities.
3242
Douglas Gregor52779fb2010-09-23 23:01:17 +00003243 HandleCodeCompleteResults(this, CodeCompleter,
3244 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003245 Results.data(), Results.size());
3246}
3247
Douglas Gregorfb629412010-08-23 21:17:50 +00003248struct Sema::CodeCompleteExpressionData {
3249 CodeCompleteExpressionData(QualType PreferredType = QualType())
3250 : PreferredType(PreferredType), IntegralConstantExpression(false),
3251 ObjCCollection(false) { }
3252
3253 QualType PreferredType;
3254 bool IntegralConstantExpression;
3255 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003256 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003257};
3258
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003259/// \brief Perform code-completion in an expression context when we know what
3260/// type we're looking for.
Douglas Gregorf9578432010-07-28 21:50:18 +00003261///
3262/// \param IntegralConstantExpression Only permit integral constant
3263/// expressions.
Douglas Gregorfb629412010-08-23 21:17:50 +00003264void Sema::CodeCompleteExpression(Scope *S,
3265 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00003266 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003267 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3268 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003269 if (Data.ObjCCollection)
3270 Results.setFilter(&ResultBuilder::IsObjCCollection);
3271 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003272 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikie4e4d0842012-03-11 07:00:24 +00003273 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003274 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3275 else
3276 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003277
3278 if (!Data.PreferredType.isNull())
3279 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3280
3281 // Ignore any declarations that we were told that we don't care about.
3282 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3283 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003284
3285 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003286 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3287 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003288
3289 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003290 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003291 Results.ExitScope();
3292
Douglas Gregor590c7d52010-07-08 20:55:51 +00003293 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003294 if (!Data.PreferredType.isNull())
3295 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3296 || Data.PreferredType->isMemberPointerType()
3297 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003298
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003299 if (S->getFnParent() &&
3300 !Data.ObjCCollection &&
3301 !Data.IntegralConstantExpression)
David Blaikie4e4d0842012-03-11 07:00:24 +00003302 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003303
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003304 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003305 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003306 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003307 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3308 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003309 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003310}
3311
Douglas Gregorac5fd842010-09-18 01:28:11 +00003312void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3313 if (E.isInvalid())
3314 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikie4e4d0842012-03-11 07:00:24 +00003315 else if (getLangOpts().ObjC1)
Douglas Gregorac5fd842010-09-18 01:28:11 +00003316 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003317}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003318
Douglas Gregor73449212010-12-09 23:01:55 +00003319/// \brief The set of properties that have already been added, referenced by
3320/// property name.
3321typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3322
Douglas Gregor95ac6552009-11-18 01:29:26 +00003323static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003324 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003325 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003326 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003327 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003328 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003329 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003330
3331 // Add properties in this container.
3332 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3333 PEnd = Container->prop_end();
3334 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003335 ++P) {
3336 if (AddedProperties.insert(P->getIdentifier()))
3337 Results.MaybeAddResult(Result(*P, 0), CurContext);
3338 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003339
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003340 // Add nullary methods
3341 if (AllowNullaryMethods) {
3342 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003343 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003344 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3345 MEnd = Container->meth_end();
3346 M != MEnd; ++M) {
3347 if (M->getSelector().isUnarySelector())
3348 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3349 if (AddedProperties.insert(Name)) {
3350 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor8987b232011-09-27 23:30:47 +00003351 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003352 Builder.AddTypedTextChunk(
3353 Results.getAllocator().CopyString(Name->getName()));
3354
Douglas Gregorba103062012-03-27 23:34:16 +00003355 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
3356 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003357 CurContext);
3358 }
3359 }
3360 }
3361
3362
Douglas Gregor95ac6552009-11-18 01:29:26 +00003363 // Add properties in referenced protocols.
3364 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3365 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3366 PEnd = Protocol->protocol_end();
3367 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003368 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3369 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003370 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003371 if (AllowCategories) {
3372 // Look through categories.
3373 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3374 Category; Category = Category->getNextClassCategory())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003375 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3376 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003377 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003378
3379 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003380 for (ObjCInterfaceDecl::all_protocol_iterator
3381 I = IFace->all_referenced_protocol_begin(),
3382 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003383 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3384 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003385
3386 // Look in the superclass.
3387 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003388 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3389 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003390 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003391 } else if (const ObjCCategoryDecl *Category
3392 = dyn_cast<ObjCCategoryDecl>(Container)) {
3393 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003394 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3395 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003396 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003397 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3398 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003399 }
3400}
3401
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003402void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003403 SourceLocation OpLoc,
3404 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003405 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003406 return;
3407
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003408 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3409 if (ConvertedBase.isInvalid())
3410 return;
3411 Base = ConvertedBase.get();
3412
John McCall0a2c5e22010-08-25 06:19:51 +00003413 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003414
Douglas Gregor81b747b2009-09-17 21:32:03 +00003415 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003416
3417 if (IsArrow) {
3418 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3419 BaseType = Ptr->getPointeeType();
3420 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003421 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003422 else
3423 return;
3424 }
3425
Douglas Gregor3da626b2011-07-07 16:03:39 +00003426 enum CodeCompletionContext::Kind contextKind;
3427
3428 if (IsArrow) {
3429 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3430 }
3431 else {
3432 if (BaseType->isObjCObjectPointerType() ||
3433 BaseType->isObjCObjectOrInterfaceType()) {
3434 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3435 }
3436 else {
3437 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3438 }
3439 }
3440
Douglas Gregor218937c2011-02-01 19:23:04 +00003441 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003442 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003443 BaseType),
3444 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003445 Results.EnterNewScope();
3446 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003447 // Indicate that we are performing a member access, and the cv-qualifiers
3448 // for the base object type.
3449 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3450
Douglas Gregor95ac6552009-11-18 01:29:26 +00003451 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003452 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003453 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003454 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3455 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003456
David Blaikie4e4d0842012-03-11 07:00:24 +00003457 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003458 if (!Results.empty()) {
3459 // The "template" keyword can follow "->" or "." in the grammar.
3460 // However, we only want to suggest the template keyword if something
3461 // is dependent.
3462 bool IsDependent = BaseType->isDependentType();
3463 if (!IsDependent) {
3464 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3465 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3466 IsDependent = Ctx->isDependentContext();
3467 break;
3468 }
3469 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003470
Douglas Gregor95ac6552009-11-18 01:29:26 +00003471 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003472 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003473 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003474 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003475 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3476 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003477 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003478
3479 // Add property results based on our interface.
3480 const ObjCObjectPointerType *ObjCPtr
3481 = BaseType->getAsObjCInterfacePointerType();
3482 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003483 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3484 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003485 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003486
3487 // Add properties from the protocols in a qualified interface.
3488 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3489 E = ObjCPtr->qual_end();
3490 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003491 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3492 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003493 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003494 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003495 // Objective-C instance variable access.
3496 ObjCInterfaceDecl *Class = 0;
3497 if (const ObjCObjectPointerType *ObjCPtr
3498 = BaseType->getAs<ObjCObjectPointerType>())
3499 Class = ObjCPtr->getInterfaceDecl();
3500 else
John McCallc12c5bb2010-05-15 11:32:37 +00003501 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003502
3503 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003504 if (Class) {
3505 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3506 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003507 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3508 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003509 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003510 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003511
3512 // FIXME: How do we cope with isa?
3513
3514 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003515
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003516 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003517 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003518 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003519 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003520}
3521
Douglas Gregor374929f2009-09-18 15:37:17 +00003522void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3523 if (!CodeCompleter)
3524 return;
3525
John McCall0a2c5e22010-08-25 06:19:51 +00003526 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003527 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003528 enum CodeCompletionContext::Kind ContextKind
3529 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003530 switch ((DeclSpec::TST)TagSpec) {
3531 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003532 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003533 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003534 break;
3535
3536 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003537 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003538 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003539 break;
3540
3541 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003542 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003543 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003544 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003545 break;
3546
3547 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003548 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003549 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003550
Douglas Gregor218937c2011-02-01 19:23:04 +00003551 ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003552 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003553
3554 // First pass: look for tags.
3555 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003556 LookupVisibleDecls(S, LookupTagName, Consumer,
3557 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003558
Douglas Gregor8071e422010-08-15 06:18:01 +00003559 if (CodeCompleter->includeGlobals()) {
3560 // Second pass: look for nested name specifiers.
3561 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3562 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3563 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003564
Douglas Gregor52779fb2010-09-23 23:01:17 +00003565 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003566 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003567}
3568
Douglas Gregor1a480c42010-08-27 17:35:51 +00003569void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003570 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3571 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003572 Results.EnterNewScope();
3573 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3574 Results.AddResult("const");
3575 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3576 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003577 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003578 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3579 Results.AddResult("restrict");
3580 Results.ExitScope();
3581 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003582 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003583 Results.data(), Results.size());
3584}
3585
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003586void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003587 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003588 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003589
John McCall781472f2010-08-25 08:40:02 +00003590 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003591 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3592 if (!type->isEnumeralType()) {
3593 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003594 Data.IntegralConstantExpression = true;
3595 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003596 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003597 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003598
3599 // Code-complete the cases of a switch statement over an enumeration type
3600 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003601 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003602
3603 // Determine which enumerators we have already seen in the switch statement.
3604 // FIXME: Ideally, we would also be able to look *past* the code-completion
3605 // token, in case we are code-completing in the middle of the switch and not
3606 // at the end. However, we aren't able to do so at the moment.
3607 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003608 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003609 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3610 SC = SC->getNextSwitchCase()) {
3611 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3612 if (!Case)
3613 continue;
3614
3615 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3616 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3617 if (EnumConstantDecl *Enumerator
3618 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3619 // We look into the AST of the case statement to determine which
3620 // enumerator was named. Alternatively, we could compute the value of
3621 // the integral constant expression, then compare it against the
3622 // values of each enumerator. However, value-based approach would not
3623 // work as well with C++ templates where enumerators declared within a
3624 // template are type- and value-dependent.
3625 EnumeratorsSeen.insert(Enumerator);
3626
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003627 // If this is a qualified-id, keep track of the nested-name-specifier
3628 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003629 //
3630 // switch (TagD.getKind()) {
3631 // case TagDecl::TK_enum:
3632 // break;
3633 // case XXX
3634 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003635 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003636 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3637 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003638 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003639 }
3640 }
3641
David Blaikie4e4d0842012-03-11 07:00:24 +00003642 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003643 // If there are no prior enumerators in C++, check whether we have to
3644 // qualify the names of the enumerators that we suggest, because they
3645 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003646 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003647 }
3648
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003649 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003650 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3651 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003652 Results.EnterNewScope();
3653 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3654 EEnd = Enum->enumerator_end();
3655 E != EEnd; ++E) {
3656 if (EnumeratorsSeen.count(*E))
3657 continue;
3658
Douglas Gregor5c722c702011-02-18 23:30:37 +00003659 CodeCompletionResult R(*E, Qualifier);
3660 R.Priority = CCP_EnumInCase;
3661 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003662 }
3663 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003664
Douglas Gregor3da626b2011-07-07 16:03:39 +00003665 //We need to make sure we're setting the right context,
3666 //so only say we include macros if the code completer says we do
3667 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3668 if (CodeCompleter->includeMacros()) {
Douglas Gregorbca403c2010-01-13 23:51:12 +00003669 AddMacroResults(PP, Results);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003670 kind = CodeCompletionContext::CCC_OtherWithMacros;
3671 }
3672
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003673 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003674 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003675 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003676}
3677
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003678namespace {
3679 struct IsBetterOverloadCandidate {
3680 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003681 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003682
3683 public:
John McCall5769d612010-02-08 23:07:23 +00003684 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3685 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003686
3687 bool
3688 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003689 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003690 }
3691 };
3692}
3693
Ahmed Charles13a140c2012-02-25 11:00:22 +00003694static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3695 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003696 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003697
3698 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003699 if (!Args[I])
3700 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003701
Douglas Gregord28dcd72010-05-30 06:10:08 +00003702 return false;
3703}
3704
Richard Trieuf81e5a92011-09-09 02:00:50 +00003705void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charles13a140c2012-02-25 11:00:22 +00003706 llvm::ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003707 if (!CodeCompleter)
3708 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003709
3710 // When we're code-completing for a call, we fall back to ordinary
3711 // name code-completion whenever we can't produce specific
3712 // results. We may want to revisit this strategy in the future,
3713 // e.g., by merging the two kinds of results.
3714
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003715 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003716
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003717 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003718 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3719 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003720 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003721 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003722 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003723
John McCall3b4294e2009-12-16 12:17:52 +00003724 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003725 SourceLocation Loc = Fn->getExprLoc();
3726 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003727
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003728 // FIXME: What if we're calling something that isn't a function declaration?
3729 // FIXME: What if we're calling a pseudo-destructor?
3730 // FIXME: What if we're calling a member function?
3731
Douglas Gregorc0265402010-01-21 15:46:19 +00003732 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003733 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003734
John McCall3b4294e2009-12-16 12:17:52 +00003735 Expr *NakedFn = Fn->IgnoreParenCasts();
3736 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003737 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003738 /*PartialOverloading=*/ true);
3739 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3740 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003741 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003742 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003743 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003744 Results.push_back(ResultCandidate(FDecl));
3745 else
John McCall86820f52010-01-26 01:37:31 +00003746 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003747 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3748 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003749 }
John McCall3b4294e2009-12-16 12:17:52 +00003750 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003751
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003752 QualType ParamType;
3753
Douglas Gregorc0265402010-01-21 15:46:19 +00003754 if (!CandidateSet.empty()) {
3755 // Sort the overload candidate set by placing the best overloads first.
3756 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003757 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003758
Douglas Gregorc0265402010-01-21 15:46:19 +00003759 // Add the remaining viable overload candidates as code-completion reslults.
3760 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3761 CandEnd = CandidateSet.end();
3762 Cand != CandEnd; ++Cand) {
3763 if (Cand->Viable)
3764 Results.push_back(ResultCandidate(Cand->Function));
3765 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003766
3767 // From the viable candidates, try to determine the type of this parameter.
3768 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3769 if (const FunctionType *FType = Results[I].getFunctionType())
3770 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003771 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003772 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003773 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003774 else if (!Context.hasSameUnqualifiedType(
3775 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003776 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003777 ParamType = QualType();
3778 break;
3779 }
3780 }
3781 }
3782 } else {
3783 // Try to determine the parameter type from the type of the expression
3784 // being called.
3785 QualType FunctionType = Fn->getType();
3786 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3787 FunctionType = Ptr->getPointeeType();
3788 else if (const BlockPointerType *BlockPtr
3789 = FunctionType->getAs<BlockPointerType>())
3790 FunctionType = BlockPtr->getPointeeType();
3791 else if (const MemberPointerType *MemPtr
3792 = FunctionType->getAs<MemberPointerType>())
3793 FunctionType = MemPtr->getPointeeType();
3794
3795 if (const FunctionProtoType *Proto
3796 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003797 if (Args.size() < Proto->getNumArgs())
3798 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003799 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003800 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003801
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003802 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003803 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003804 else
3805 CodeCompleteExpression(S, ParamType);
3806
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003807 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003808 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003809 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003810}
3811
John McCalld226f652010-08-21 09:40:31 +00003812void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3813 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003814 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003815 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003816 return;
3817 }
3818
3819 CodeCompleteExpression(S, VD->getType());
3820}
3821
3822void Sema::CodeCompleteReturn(Scope *S) {
3823 QualType ResultType;
3824 if (isa<BlockDecl>(CurContext)) {
3825 if (BlockScopeInfo *BSI = getCurBlock())
3826 ResultType = BSI->ReturnType;
3827 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3828 ResultType = Function->getResultType();
3829 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3830 ResultType = Method->getResultType();
3831
3832 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003833 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003834 else
3835 CodeCompleteExpression(S, ResultType);
3836}
3837
Douglas Gregord2d8be62011-07-30 08:36:53 +00003838void Sema::CodeCompleteAfterIf(Scope *S) {
3839 typedef CodeCompletionResult Result;
3840 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3841 mapCodeCompletionContext(*this, PCC_Statement));
3842 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3843 Results.EnterNewScope();
3844
3845 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3846 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3847 CodeCompleter->includeGlobals());
3848
3849 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3850
3851 // "else" block
3852 CodeCompletionBuilder Builder(Results.getAllocator());
3853 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00003854 if (Results.includeCodePatterns()) {
3855 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3856 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3857 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3858 Builder.AddPlaceholderChunk("statements");
3859 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3860 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3861 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003862 Results.AddResult(Builder.TakeString());
3863
3864 // "else if" block
3865 Builder.AddTypedTextChunk("else");
3866 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3867 Builder.AddTextChunk("if");
3868 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3869 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00003870 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00003871 Builder.AddPlaceholderChunk("condition");
3872 else
3873 Builder.AddPlaceholderChunk("expression");
3874 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00003875 if (Results.includeCodePatterns()) {
3876 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3877 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3878 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3879 Builder.AddPlaceholderChunk("statements");
3880 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3881 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3882 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003883 Results.AddResult(Builder.TakeString());
3884
3885 Results.ExitScope();
3886
3887 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003888 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003889
3890 if (CodeCompleter->includeMacros())
3891 AddMacroResults(PP, Results);
3892
3893 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3894 Results.data(),Results.size());
3895}
3896
Richard Trieuf81e5a92011-09-09 02:00:50 +00003897void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003898 if (LHS)
3899 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3900 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003901 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003902}
3903
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003904void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003905 bool EnteringContext) {
3906 if (!SS.getScopeRep() || !CodeCompleter)
3907 return;
3908
Douglas Gregor86d9a522009-09-21 16:56:56 +00003909 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3910 if (!Ctx)
3911 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003912
3913 // Try to instantiate any non-dependent declaration contexts before
3914 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003915 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003916 return;
3917
Douglas Gregor218937c2011-02-01 19:23:04 +00003918 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3919 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003920 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003921
Douglas Gregor86d9a522009-09-21 16:56:56 +00003922 // The "template" keyword can follow "::" in the grammar, but only
3923 // put it into the grammar if the nested-name-specifier is dependent.
3924 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3925 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003926 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003927
3928 // Add calls to overridden virtual functions, if there are any.
3929 //
3930 // FIXME: This isn't wonderful, because we don't know whether we're actually
3931 // in a context that permits expressions. This is a general issue with
3932 // qualified-id completions.
3933 if (!EnteringContext)
3934 MaybeAddOverrideCalls(*this, Ctx, Results);
3935 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003936
Douglas Gregorf6961522010-08-27 21:18:54 +00003937 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3938 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3939
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003940 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00003941 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003942 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003943}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003944
3945void Sema::CodeCompleteUsing(Scope *S) {
3946 if (!CodeCompleter)
3947 return;
3948
Douglas Gregor218937c2011-02-01 19:23:04 +00003949 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003950 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3951 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003952 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003953
3954 // If we aren't in class scope, we could see the "namespace" keyword.
3955 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00003956 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003957
3958 // After "using", we can see anything that would start a
3959 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003960 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003961 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3962 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003963 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003964
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003965 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003966 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003967 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003968}
3969
3970void Sema::CodeCompleteUsingDirective(Scope *S) {
3971 if (!CodeCompleter)
3972 return;
3973
Douglas Gregor86d9a522009-09-21 16:56:56 +00003974 // After "using namespace", we expect to see a namespace name or namespace
3975 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003976 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3977 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003978 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003979 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003980 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003981 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3982 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003983 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003984 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003985 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003986 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003987}
3988
3989void Sema::CodeCompleteNamespaceDecl(Scope *S) {
3990 if (!CodeCompleter)
3991 return;
3992
Douglas Gregor86d9a522009-09-21 16:56:56 +00003993 DeclContext *Ctx = (DeclContext *)S->getEntity();
3994 if (!S->getParent())
3995 Ctx = Context.getTranslationUnitDecl();
3996
Douglas Gregor52779fb2010-09-23 23:01:17 +00003997 bool SuppressedGlobalResults
3998 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
3999
Douglas Gregor218937c2011-02-01 19:23:04 +00004000 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004001 SuppressedGlobalResults
4002 ? CodeCompletionContext::CCC_Namespace
4003 : CodeCompletionContext::CCC_Other,
4004 &ResultBuilder::IsNamespace);
4005
4006 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004007 // We only want to see those namespaces that have already been defined
4008 // within this scope, because its likely that the user is creating an
4009 // extended namespace declaration. Keep track of the most recent
4010 // definition of each namespace.
4011 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4012 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4013 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4014 NS != NSEnd; ++NS)
4015 OrigToLatest[NS->getOriginalNamespace()] = *NS;
4016
4017 // Add the most recent definition (or extended definition) of each
4018 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004019 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004020 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregorba103062012-03-27 23:34:16 +00004021 NS = OrigToLatest.begin(),
4022 NSEnd = OrigToLatest.end();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004023 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004024 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004025 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004026 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004027 }
4028
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004029 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004030 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004031 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004032}
4033
4034void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4035 if (!CodeCompleter)
4036 return;
4037
Douglas Gregor86d9a522009-09-21 16:56:56 +00004038 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004039 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4040 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004041 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004042 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004043 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4044 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004045 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004046 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004047 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004048}
4049
Douglas Gregored8d3222009-09-18 20:05:18 +00004050void Sema::CodeCompleteOperatorName(Scope *S) {
4051 if (!CodeCompleter)
4052 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004053
John McCall0a2c5e22010-08-25 06:19:51 +00004054 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004055 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4056 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004057 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004058 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004059
Douglas Gregor86d9a522009-09-21 16:56:56 +00004060 // Add the names of overloadable operators.
4061#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4062 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004063 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004064#include "clang/Basic/OperatorKinds.def"
4065
4066 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004067 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004068 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004069 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4070 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004071
4072 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004073 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004074 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004075
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004076 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004077 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004078 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004079}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004080
Douglas Gregor0133f522010-08-28 00:00:50 +00004081void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004082 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004083 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004084 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004085 CXXConstructorDecl *Constructor
4086 = static_cast<CXXConstructorDecl *>(ConstructorD);
4087 if (!Constructor)
4088 return;
4089
Douglas Gregor218937c2011-02-01 19:23:04 +00004090 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004091 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004092 Results.EnterNewScope();
4093
4094 // Fill in any already-initialized fields or base classes.
4095 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4096 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4097 for (unsigned I = 0; I != NumInitializers; ++I) {
4098 if (Initializers[I]->isBaseInitializer())
4099 InitializedBases.insert(
4100 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4101 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004102 InitializedFields.insert(cast<FieldDecl>(
4103 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004104 }
4105
4106 // Add completions for base classes.
Douglas Gregor218937c2011-02-01 19:23:04 +00004107 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004108 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004109 CXXRecordDecl *ClassDecl = Constructor->getParent();
4110 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4111 BaseEnd = ClassDecl->bases_end();
4112 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004113 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4114 SawLastInitializer
4115 = NumInitializers > 0 &&
4116 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4117 Context.hasSameUnqualifiedType(Base->getType(),
4118 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004119 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004120 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004121
Douglas Gregor218937c2011-02-01 19:23:04 +00004122 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004123 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004124 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004125 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4126 Builder.AddPlaceholderChunk("args");
4127 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4128 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004129 SawLastInitializer? CCP_NextInitializer
4130 : CCP_MemberDeclaration));
4131 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004132 }
4133
4134 // Add completions for virtual base classes.
4135 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4136 BaseEnd = ClassDecl->vbases_end();
4137 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004138 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4139 SawLastInitializer
4140 = NumInitializers > 0 &&
4141 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4142 Context.hasSameUnqualifiedType(Base->getType(),
4143 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004144 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004145 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004146
Douglas Gregor218937c2011-02-01 19:23:04 +00004147 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004148 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004149 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004150 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4151 Builder.AddPlaceholderChunk("args");
4152 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4153 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004154 SawLastInitializer? CCP_NextInitializer
4155 : CCP_MemberDeclaration));
4156 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004157 }
4158
4159 // Add completions for members.
4160 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4161 FieldEnd = ClassDecl->field_end();
4162 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004163 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4164 SawLastInitializer
4165 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004166 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
4167 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
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
4171 if (!Field->getDeclName())
4172 continue;
4173
Douglas Gregordae68752011-02-01 22:57:45 +00004174 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004175 Field->getIdentifier()->getName()));
4176 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4177 Builder.AddPlaceholderChunk("args");
4178 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4179 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004180 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004181 : CCP_MemberDeclaration,
Douglas Gregorba103062012-03-27 23:34:16 +00004182 CXCursor_MemberRef,
4183 CXAvailability_Available,
4184 *Field));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004185 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004186 }
4187 Results.ExitScope();
4188
Douglas Gregor52779fb2010-09-23 23:01:17 +00004189 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004190 Results.data(), Results.size());
4191}
4192
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004193/// \brief Determine whether this scope denotes a namespace.
4194static bool isNamespaceScope(Scope *S) {
4195 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4196 if (!DC)
4197 return false;
4198
4199 return DC->isFileContext();
4200}
4201
4202void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4203 bool AfterAmpersand) {
4204 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4205 CodeCompletionContext::CCC_Other);
4206 Results.EnterNewScope();
4207
4208 // Note what has already been captured.
4209 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4210 bool IncludedThis = false;
4211 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4212 CEnd = Intro.Captures.end();
4213 C != CEnd; ++C) {
4214 if (C->Kind == LCK_This) {
4215 IncludedThis = true;
4216 continue;
4217 }
4218
4219 Known.insert(C->Id);
4220 }
4221
4222 // Look for other capturable variables.
4223 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4224 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4225 D != DEnd; ++D) {
4226 VarDecl *Var = dyn_cast<VarDecl>(*D);
4227 if (!Var ||
4228 !Var->hasLocalStorage() ||
4229 Var->hasAttr<BlocksAttr>())
4230 continue;
4231
4232 if (Known.insert(Var->getIdentifier()))
4233 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4234 }
4235 }
4236
4237 // Add 'this', if it would be valid.
4238 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4239 addThisCompletion(*this, Results);
4240
4241 Results.ExitScope();
4242
4243 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4244 Results.data(), Results.size());
4245}
4246
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004247// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
4248// true or false.
4249#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorbca403c2010-01-13 23:51:12 +00004250static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004251 ResultBuilder &Results,
4252 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004253 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004254 // Since we have an implementation, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004255 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004256
Douglas Gregor218937c2011-02-01 19:23:04 +00004257 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004258 if (LangOpts.ObjC2) {
4259 // @dynamic
Douglas Gregor218937c2011-02-01 19:23:04 +00004260 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
4261 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4262 Builder.AddPlaceholderChunk("property");
4263 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004264
4265 // @synthesize
Douglas Gregor218937c2011-02-01 19:23:04 +00004266 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
4267 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4268 Builder.AddPlaceholderChunk("property");
4269 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004270 }
4271}
4272
Douglas Gregorbca403c2010-01-13 23:51:12 +00004273static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004274 ResultBuilder &Results,
4275 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004276 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004277
4278 // Since we have an interface or protocol, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004279 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004280
4281 if (LangOpts.ObjC2) {
4282 // @property
Douglas Gregora4477812010-01-14 16:01:26 +00004283 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004284
4285 // @required
Douglas Gregora4477812010-01-14 16:01:26 +00004286 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004287
4288 // @optional
Douglas Gregora4477812010-01-14 16:01:26 +00004289 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004290 }
4291}
4292
Douglas Gregorbca403c2010-01-13 23:51:12 +00004293static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004294 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004295 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004296
4297 // @class name ;
Douglas Gregor218937c2011-02-01 19:23:04 +00004298 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
4299 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4300 Builder.AddPlaceholderChunk("name");
4301 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004302
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004303 if (Results.includeCodePatterns()) {
4304 // @interface name
4305 // FIXME: Could introduce the whole pattern, including superclasses and
4306 // such.
Douglas Gregor218937c2011-02-01 19:23:04 +00004307 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
4308 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4309 Builder.AddPlaceholderChunk("class");
4310 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004311
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004312 // @protocol name
Douglas Gregor218937c2011-02-01 19:23:04 +00004313 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4314 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4315 Builder.AddPlaceholderChunk("protocol");
4316 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004317
4318 // @implementation name
Douglas Gregor218937c2011-02-01 19:23:04 +00004319 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
4320 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4321 Builder.AddPlaceholderChunk("class");
4322 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004323 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004324
4325 // @compatibility_alias name
Douglas Gregor218937c2011-02-01 19:23:04 +00004326 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
4327 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4328 Builder.AddPlaceholderChunk("alias");
4329 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4330 Builder.AddPlaceholderChunk("class");
4331 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004332}
4333
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004334void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004335 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004336 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4337 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004338 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004339 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004340 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004341 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004342 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004343 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004344 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004345 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004346 HandleCodeCompleteResults(this, CodeCompleter,
4347 CodeCompletionContext::CCC_Other,
4348 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004349}
4350
Douglas Gregorbca403c2010-01-13 23:51:12 +00004351static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004352 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004353 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004354
4355 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004356 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004357 if (Results.getSema().getLangOpts().CPlusPlus ||
4358 Results.getSema().getLangOpts().ConstStrings)
Douglas Gregor8ca72082011-10-18 21:20:17 +00004359 EncodeType = " const char[]";
4360 Builder.AddResultTypeChunk(EncodeType);
Douglas Gregor218937c2011-02-01 19:23:04 +00004361 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
4362 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4363 Builder.AddPlaceholderChunk("type-name");
4364 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4365 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004366
4367 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004368 Builder.AddResultTypeChunk("Protocol *");
Douglas Gregor218937c2011-02-01 19:23:04 +00004369 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4370 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4371 Builder.AddPlaceholderChunk("protocol-name");
4372 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4373 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004374
4375 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004376 Builder.AddResultTypeChunk("SEL");
Douglas Gregor218937c2011-02-01 19:23:04 +00004377 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
4378 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4379 Builder.AddPlaceholderChunk("selector");
4380 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4381 Results.AddResult(Result(Builder.TakeString()));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004382
4383 // @[ objects, ... ]
4384 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,[));
4385 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4386 Builder.AddPlaceholderChunk("objects, ...");
4387 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4388 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4389 Results.AddResult(Result(Builder.TakeString()));
4390
4391 // @{ key : object, ... }
4392 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,{));
4393 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4394 Builder.AddPlaceholderChunk("key");
4395 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4396 Builder.AddChunk(CodeCompletionString::CK_Colon);
4397 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4398 Builder.AddPlaceholderChunk("object, ...");
4399 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4400 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4401 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004402}
4403
Douglas Gregorbca403c2010-01-13 23:51:12 +00004404static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004405 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004406 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004407
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004408 if (Results.includeCodePatterns()) {
4409 // @try { statements } @catch ( declaration ) { statements } @finally
4410 // { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004411 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
4412 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4413 Builder.AddPlaceholderChunk("statements");
4414 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4415 Builder.AddTextChunk("@catch");
4416 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4417 Builder.AddPlaceholderChunk("parameter");
4418 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4419 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4420 Builder.AddPlaceholderChunk("statements");
4421 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4422 Builder.AddTextChunk("@finally");
4423 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4424 Builder.AddPlaceholderChunk("statements");
4425 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4426 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004427 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004428
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004429 // @throw
Douglas Gregor218937c2011-02-01 19:23:04 +00004430 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
4431 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4432 Builder.AddPlaceholderChunk("expression");
4433 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004434
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004435 if (Results.includeCodePatterns()) {
4436 // @synchronized ( expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004437 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
4438 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4439 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4440 Builder.AddPlaceholderChunk("expression");
4441 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4442 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4443 Builder.AddPlaceholderChunk("statements");
4444 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4445 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004446 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004447}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004448
Douglas Gregorbca403c2010-01-13 23:51:12 +00004449static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004450 ResultBuilder &Results,
4451 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004452 typedef CodeCompletionResult Result;
Douglas Gregora4477812010-01-14 16:01:26 +00004453 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
4454 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
4455 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004456 if (LangOpts.ObjC2)
Douglas Gregora4477812010-01-14 16:01:26 +00004457 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004458}
4459
4460void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004461 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4462 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004463 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004464 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004465 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004466 HandleCodeCompleteResults(this, CodeCompleter,
4467 CodeCompletionContext::CCC_Other,
4468 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004469}
4470
4471void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004472 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4473 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004474 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004475 AddObjCStatementResults(Results, false);
4476 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004477 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004478 HandleCodeCompleteResults(this, CodeCompleter,
4479 CodeCompletionContext::CCC_Other,
4480 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004481}
4482
4483void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004484 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4485 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004486 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004487 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004488 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004489 HandleCodeCompleteResults(this, CodeCompleter,
4490 CodeCompletionContext::CCC_Other,
4491 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004492}
4493
Douglas Gregor988358f2009-11-19 00:14:45 +00004494/// \brief Determine whether the addition of the given flag to an Objective-C
4495/// property's attributes will cause a conflict.
4496static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4497 // Check if we've already added this flag.
4498 if (Attributes & NewFlag)
4499 return true;
4500
4501 Attributes |= NewFlag;
4502
4503 // Check for collisions with "readonly".
4504 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4505 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4506 ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004507 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004508 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004509 ObjCDeclSpec::DQ_PR_retain |
4510 ObjCDeclSpec::DQ_PR_strong)))
Douglas Gregor988358f2009-11-19 00:14:45 +00004511 return true;
4512
John McCallf85e1932011-06-15 23:02:42 +00004513 // Check for more than one of { assign, copy, retain, strong }.
Douglas Gregor988358f2009-11-19 00:14:45 +00004514 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004515 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004516 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004517 ObjCDeclSpec::DQ_PR_retain|
4518 ObjCDeclSpec::DQ_PR_strong);
Douglas Gregor988358f2009-11-19 00:14:45 +00004519 if (AssignCopyRetMask &&
4520 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004521 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004522 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004523 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
4524 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
Douglas Gregor988358f2009-11-19 00:14:45 +00004525 return true;
4526
4527 return false;
4528}
4529
Douglas Gregora93b1082009-11-18 23:08:07 +00004530void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004531 if (!CodeCompleter)
4532 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004533
Steve Naroffece8e712009-10-08 21:55:05 +00004534 unsigned Attributes = ODS.getPropertyAttributes();
4535
John McCall0a2c5e22010-08-25 06:19:51 +00004536 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004537 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4538 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004539 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004540 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004541 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004542 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004543 Results.AddResult(CodeCompletionResult("assign"));
John McCallf85e1932011-06-15 23:02:42 +00004544 if (!ObjCPropertyFlagConflicts(Attributes,
4545 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4546 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004547 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004548 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004549 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004550 Results.AddResult(CodeCompletionResult("retain"));
John McCallf85e1932011-06-15 23:02:42 +00004551 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4552 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004553 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004554 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004555 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004556 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004557 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4558 Results.AddResult(CodeCompletionResult("atomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004559 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004560 CodeCompletionBuilder Setter(Results.getAllocator());
4561 Setter.AddTypedTextChunk("setter");
4562 Setter.AddTextChunk(" = ");
4563 Setter.AddPlaceholderChunk("method");
4564 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004565 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004566 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004567 CodeCompletionBuilder Getter(Results.getAllocator());
4568 Getter.AddTypedTextChunk("getter");
4569 Getter.AddTextChunk(" = ");
4570 Getter.AddPlaceholderChunk("method");
4571 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004572 }
Steve Naroffece8e712009-10-08 21:55:05 +00004573 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004574 HandleCodeCompleteResults(this, CodeCompleter,
4575 CodeCompletionContext::CCC_Other,
4576 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004577}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004578
Douglas Gregor4ad96852009-11-19 07:41:15 +00004579/// \brief Descripts the kind of Objective-C method that we want to find
4580/// via code completion.
4581enum ObjCMethodKind {
4582 MK_Any, //< Any kind of method, provided it means other specified criteria.
4583 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4584 MK_OneArgSelector //< One-argument selector.
4585};
4586
Douglas Gregor458433d2010-08-26 15:07:07 +00004587static bool isAcceptableObjCSelector(Selector Sel,
4588 ObjCMethodKind WantKind,
4589 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004590 unsigned NumSelIdents,
4591 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004592 if (NumSelIdents > Sel.getNumArgs())
4593 return false;
4594
4595 switch (WantKind) {
4596 case MK_Any: break;
4597 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4598 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4599 }
4600
Douglas Gregorcf544262010-11-17 21:36:08 +00004601 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4602 return false;
4603
Douglas Gregor458433d2010-08-26 15:07:07 +00004604 for (unsigned I = 0; I != NumSelIdents; ++I)
4605 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4606 return false;
4607
4608 return true;
4609}
4610
Douglas Gregor4ad96852009-11-19 07:41:15 +00004611static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4612 ObjCMethodKind WantKind,
4613 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004614 unsigned NumSelIdents,
4615 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004616 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004617 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004618}
Douglas Gregord36adf52010-09-16 16:06:31 +00004619
4620namespace {
4621 /// \brief A set of selectors, which is used to avoid introducing multiple
4622 /// completions with the same selector into the result set.
4623 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4624}
4625
Douglas Gregor36ecb042009-11-17 23:22:23 +00004626/// \brief Add all of the Objective-C methods in the given Objective-C
4627/// container to the set of results.
4628///
4629/// The container will be a class, protocol, category, or implementation of
4630/// any of the above. This mether will recurse to include methods from
4631/// the superclasses of classes along with their categories, protocols, and
4632/// implementations.
4633///
4634/// \param Container the container in which we'll look to find methods.
4635///
4636/// \param WantInstance whether to add instance methods (only); if false, this
4637/// routine will add factory methods (only).
4638///
4639/// \param CurContext the context in which we're performing the lookup that
4640/// finds methods.
4641///
Douglas Gregorcf544262010-11-17 21:36:08 +00004642/// \param AllowSameLength Whether we allow a method to be added to the list
4643/// when it has the same number of parameters as we have selector identifiers.
4644///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004645/// \param Results the structure into which we'll add results.
4646static void AddObjCMethods(ObjCContainerDecl *Container,
4647 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004648 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004649 IdentifierInfo **SelIdents,
4650 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004651 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004652 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004653 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004654 ResultBuilder &Results,
4655 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004656 typedef CodeCompletionResult Result;
Douglas Gregor36ecb042009-11-17 23:22:23 +00004657 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4658 MEnd = Container->meth_end();
4659 M != MEnd; ++M) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004660 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4661 // Check whether the selector identifiers we've been given are a
4662 // subset of the identifiers for this particular method.
Douglas Gregorcf544262010-11-17 21:36:08 +00004663 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4664 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004665 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004666
Douglas Gregord36adf52010-09-16 16:06:31 +00004667 if (!Selectors.insert((*M)->getSelector()))
4668 continue;
4669
Douglas Gregord3c68542009-11-19 01:08:35 +00004670 Result R = Result(*M, 0);
4671 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004672 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004673 if (!InOriginalClass)
4674 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004675 Results.MaybeAddResult(R, CurContext);
4676 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004677 }
4678
Douglas Gregore396c7b2010-09-16 15:34:59 +00004679 // Visit the protocols of protocols.
4680 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004681 if (Protocol->hasDefinition()) {
4682 const ObjCList<ObjCProtocolDecl> &Protocols
4683 = Protocol->getReferencedProtocols();
4684 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4685 E = Protocols.end();
4686 I != E; ++I)
4687 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4688 NumSelIdents, CurContext, Selectors, AllowSameLength,
4689 Results, false);
4690 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004691 }
4692
Douglas Gregor36ecb042009-11-17 23:22:23 +00004693 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004694 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004695 return;
4696
4697 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004698 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4699 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004700 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004701 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004702 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004703
4704 // Add methods in categories.
4705 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4706 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004707 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004708 NumSelIdents, CurContext, Selectors, AllowSameLength,
4709 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004710
4711 // Add a categories protocol methods.
4712 const ObjCList<ObjCProtocolDecl> &Protocols
4713 = CatDecl->getReferencedProtocols();
4714 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4715 E = Protocols.end();
4716 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004717 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004718 NumSelIdents, CurContext, Selectors, AllowSameLength,
4719 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004720
4721 // Add methods in category implementations.
4722 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004723 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004724 NumSelIdents, CurContext, Selectors, AllowSameLength,
4725 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004726 }
4727
4728 // Add methods in superclass.
4729 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004730 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004731 SelIdents, NumSelIdents, CurContext, Selectors,
4732 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004733
4734 // Add methods in our implementation, if any.
4735 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004736 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004737 NumSelIdents, CurContext, Selectors, AllowSameLength,
4738 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004739}
4740
4741
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004742void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004743 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004744
4745 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004746 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004747 if (!Class) {
4748 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004749 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004750 Class = Category->getClassInterface();
4751
4752 if (!Class)
4753 return;
4754 }
4755
4756 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004757 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4758 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004759 Results.EnterNewScope();
4760
Douglas Gregord36adf52010-09-16 16:06:31 +00004761 VisitedSelectorSet Selectors;
4762 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004763 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004764 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004765 HandleCodeCompleteResults(this, CodeCompleter,
4766 CodeCompletionContext::CCC_Other,
4767 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004768}
4769
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004770void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004771 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004772
4773 // Try to find the interface where setters might live.
4774 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004775 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004776 if (!Class) {
4777 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004778 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004779 Class = Category->getClassInterface();
4780
4781 if (!Class)
4782 return;
4783 }
4784
4785 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004786 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4787 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004788 Results.EnterNewScope();
4789
Douglas Gregord36adf52010-09-16 16:06:31 +00004790 VisitedSelectorSet Selectors;
4791 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004792 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004793
4794 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004795 HandleCodeCompleteResults(this, CodeCompleter,
4796 CodeCompletionContext::CCC_Other,
4797 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004798}
4799
Douglas Gregorafc45782011-02-15 22:19:42 +00004800void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4801 bool IsParameter) {
John McCall0a2c5e22010-08-25 06:19:51 +00004802 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004803 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4804 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004805 Results.EnterNewScope();
4806
4807 // Add context-sensitive, Objective-C parameter-passing keywords.
4808 bool AddedInOut = false;
4809 if ((DS.getObjCDeclQualifier() &
4810 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4811 Results.AddResult("in");
4812 Results.AddResult("inout");
4813 AddedInOut = true;
4814 }
4815 if ((DS.getObjCDeclQualifier() &
4816 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4817 Results.AddResult("out");
4818 if (!AddedInOut)
4819 Results.AddResult("inout");
4820 }
4821 if ((DS.getObjCDeclQualifier() &
4822 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4823 ObjCDeclSpec::DQ_Oneway)) == 0) {
4824 Results.AddResult("bycopy");
4825 Results.AddResult("byref");
4826 Results.AddResult("oneway");
4827 }
4828
Douglas Gregorafc45782011-02-15 22:19:42 +00004829 // If we're completing the return type of an Objective-C method and the
4830 // identifier IBAction refers to a macro, provide a completion item for
4831 // an action, e.g.,
4832 // IBAction)<#selector#>:(id)sender
4833 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4834 Context.Idents.get("IBAction").hasMacroDefinition()) {
Douglas Gregorafc45782011-02-15 22:19:42 +00004835 CodeCompletionBuilder Builder(Results.getAllocator(), CCP_CodePattern,
4836 CXAvailability_Available);
4837 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004838 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004839 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004840 Builder.AddChunk(CodeCompletionString::CK_Colon);
4841 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004842 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004843 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004844 Builder.AddTextChunk("sender");
4845 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4846 }
4847
Douglas Gregord32b0222010-08-24 01:06:58 +00004848 // Add various builtin type names and specifiers.
4849 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4850 Results.ExitScope();
4851
4852 // Add the various type names
4853 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4854 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4855 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4856 CodeCompleter->includeGlobals());
4857
4858 if (CodeCompleter->includeMacros())
4859 AddMacroResults(PP, Results);
4860
4861 HandleCodeCompleteResults(this, CodeCompleter,
4862 CodeCompletionContext::CCC_Type,
4863 Results.data(), Results.size());
4864}
4865
Douglas Gregor22f56992010-04-06 19:22:33 +00004866/// \brief When we have an expression with type "id", we may assume
4867/// that it has some more-specific class type based on knowledge of
4868/// common uses of Objective-C. This routine returns that class type,
4869/// or NULL if no better result could be determined.
4870static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004871 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004872 if (!Msg)
4873 return 0;
4874
4875 Selector Sel = Msg->getSelector();
4876 if (Sel.isNull())
4877 return 0;
4878
4879 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4880 if (!Id)
4881 return 0;
4882
4883 ObjCMethodDecl *Method = Msg->getMethodDecl();
4884 if (!Method)
4885 return 0;
4886
4887 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004888 ObjCInterfaceDecl *IFace = 0;
4889 switch (Msg->getReceiverKind()) {
4890 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004891 if (const ObjCObjectType *ObjType
4892 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4893 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004894 break;
4895
4896 case ObjCMessageExpr::Instance: {
4897 QualType T = Msg->getInstanceReceiver()->getType();
4898 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4899 IFace = Ptr->getInterfaceDecl();
4900 break;
4901 }
4902
4903 case ObjCMessageExpr::SuperInstance:
4904 case ObjCMessageExpr::SuperClass:
4905 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00004906 }
4907
4908 if (!IFace)
4909 return 0;
4910
4911 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4912 if (Method->isInstanceMethod())
4913 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4914 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00004915 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00004916 .Case("autorelease", IFace)
4917 .Case("copy", IFace)
4918 .Case("copyWithZone", IFace)
4919 .Case("mutableCopy", IFace)
4920 .Case("mutableCopyWithZone", IFace)
4921 .Case("awakeFromCoder", IFace)
4922 .Case("replacementObjectFromCoder", IFace)
4923 .Case("class", IFace)
4924 .Case("classForCoder", IFace)
4925 .Case("superclass", Super)
4926 .Default(0);
4927
4928 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4929 .Case("new", IFace)
4930 .Case("alloc", IFace)
4931 .Case("allocWithZone", IFace)
4932 .Case("class", IFace)
4933 .Case("superclass", Super)
4934 .Default(0);
4935}
4936
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004937// Add a special completion for a message send to "super", which fills in the
4938// most likely case of forwarding all of our arguments to the superclass
4939// function.
4940///
4941/// \param S The semantic analysis object.
4942///
4943/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4944/// the "super" keyword. Otherwise, we just need to provide the arguments.
4945///
4946/// \param SelIdents The identifiers in the selector that have already been
4947/// provided as arguments for a send to "super".
4948///
4949/// \param NumSelIdents The number of identifiers in \p SelIdents.
4950///
4951/// \param Results The set of results to augment.
4952///
4953/// \returns the Objective-C method declaration that would be invoked by
4954/// this "super" completion. If NULL, no completion was added.
4955static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4956 IdentifierInfo **SelIdents,
4957 unsigned NumSelIdents,
4958 ResultBuilder &Results) {
4959 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
4960 if (!CurMethod)
4961 return 0;
4962
4963 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
4964 if (!Class)
4965 return 0;
4966
4967 // Try to find a superclass method with the same selector.
4968 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00004969 while ((Class = Class->getSuperClass()) && !SuperMethod) {
4970 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004971 SuperMethod = Class->getMethod(CurMethod->getSelector(),
4972 CurMethod->isInstanceMethod());
4973
Douglas Gregor78bcd912011-02-16 00:51:18 +00004974 // Check in categories or class extensions.
4975 if (!SuperMethod) {
4976 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
4977 Category = Category->getNextClassCategory())
4978 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
4979 CurMethod->isInstanceMethod())))
4980 break;
4981 }
4982 }
4983
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004984 if (!SuperMethod)
4985 return 0;
4986
4987 // Check whether the superclass method has the same signature.
4988 if (CurMethod->param_size() != SuperMethod->param_size() ||
4989 CurMethod->isVariadic() != SuperMethod->isVariadic())
4990 return 0;
4991
4992 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
4993 CurPEnd = CurMethod->param_end(),
4994 SuperP = SuperMethod->param_begin();
4995 CurP != CurPEnd; ++CurP, ++SuperP) {
4996 // Make sure the parameter types are compatible.
4997 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
4998 (*SuperP)->getType()))
4999 return 0;
5000
5001 // Make sure we have a parameter name to forward!
5002 if (!(*CurP)->getIdentifier())
5003 return 0;
5004 }
5005
5006 // We have a superclass method. Now, form the send-to-super completion.
Douglas Gregor218937c2011-02-01 19:23:04 +00005007 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005008
5009 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005010 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5011 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005012
5013 // If we need the "super" keyword, add it (plus some spacing).
5014 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005015 Builder.AddTypedTextChunk("super");
5016 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005017 }
5018
5019 Selector Sel = CurMethod->getSelector();
5020 if (Sel.isUnarySelector()) {
5021 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005022 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005023 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005024 else
Douglas Gregordae68752011-02-01 22:57:45 +00005025 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005026 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005027 } else {
5028 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5029 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5030 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005031 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005032
5033 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005034 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005035 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005036 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005037 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005038 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005039 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005040 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005041 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005042 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005043 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005044 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005045 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005046 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005047 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005048 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005049 }
5050 }
5051 }
5052
Douglas Gregorba103062012-03-27 23:34:16 +00005053 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5054 CCP_SuperCompletion));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005055 return SuperMethod;
5056}
5057
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005058void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005059 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005060 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5061 CodeCompletionContext::CCC_ObjCMessageReceiver,
David Blaikie4e4d0842012-03-11 07:00:24 +00005062 getLangOpts().CPlusPlus0x
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005063 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5064 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005065
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005066 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5067 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005068 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5069 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005070
5071 // If we are in an Objective-C method inside a class that has a superclass,
5072 // add "super" as an option.
5073 if (ObjCMethodDecl *Method = getCurMethodDecl())
5074 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005075 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005076 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005077
5078 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5079 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005080
David Blaikie4e4d0842012-03-11 07:00:24 +00005081 if (getLangOpts().CPlusPlus0x)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005082 addThisCompletion(*this, Results);
5083
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005084 Results.ExitScope();
5085
5086 if (CodeCompleter->includeMacros())
5087 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005088 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005089 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005090
5091}
5092
Douglas Gregor2725ca82010-04-21 19:57:20 +00005093void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5094 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005095 unsigned NumSelIdents,
5096 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005097 ObjCInterfaceDecl *CDecl = 0;
5098 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5099 // Figure out which interface we're in.
5100 CDecl = CurMethod->getClassInterface();
5101 if (!CDecl)
5102 return;
5103
5104 // Find the superclass of this class.
5105 CDecl = CDecl->getSuperClass();
5106 if (!CDecl)
5107 return;
5108
5109 if (CurMethod->isInstanceMethod()) {
5110 // We are inside an instance method, which means that the message
5111 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005112 // current object.
5113 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005114 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005115 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005116 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005117 }
5118
5119 // Fall through to send to the superclass in CDecl.
5120 } else {
5121 // "super" may be the name of a type or variable. Figure out which
5122 // it is.
5123 IdentifierInfo *Super = &Context.Idents.get("super");
5124 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5125 LookupOrdinaryName);
5126 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5127 // "super" names an interface. Use it.
5128 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005129 if (const ObjCObjectType *Iface
5130 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5131 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005132 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5133 // "super" names an unresolved type; we can't be more specific.
5134 } else {
5135 // Assume that "super" names some kind of value and parse that way.
5136 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005137 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005138 UnqualifiedId id;
5139 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005140 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5141 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005142 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005143 SelIdents, NumSelIdents,
5144 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005145 }
5146
5147 // Fall through
5148 }
5149
John McCallb3d87482010-08-24 05:47:05 +00005150 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005151 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005152 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005153 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005154 NumSelIdents, AtArgumentExpression,
5155 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005156}
5157
Douglas Gregorb9d77572010-09-21 00:03:25 +00005158/// \brief Given a set of code-completion results for the argument of a message
5159/// send, determine the preferred type (if any) for that argument expression.
5160static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5161 unsigned NumSelIdents) {
5162 typedef CodeCompletionResult Result;
5163 ASTContext &Context = Results.getSema().Context;
5164
5165 QualType PreferredType;
5166 unsigned BestPriority = CCP_Unlikely * 2;
5167 Result *ResultsData = Results.data();
5168 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5169 Result &R = ResultsData[I];
5170 if (R.Kind == Result::RK_Declaration &&
5171 isa<ObjCMethodDecl>(R.Declaration)) {
5172 if (R.Priority <= BestPriority) {
5173 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5174 if (NumSelIdents <= Method->param_size()) {
5175 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5176 ->getType();
5177 if (R.Priority < BestPriority || PreferredType.isNull()) {
5178 BestPriority = R.Priority;
5179 PreferredType = MyPreferredType;
5180 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5181 MyPreferredType)) {
5182 PreferredType = QualType();
5183 }
5184 }
5185 }
5186 }
5187 }
5188
5189 return PreferredType;
5190}
5191
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005192static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5193 ParsedType Receiver,
5194 IdentifierInfo **SelIdents,
5195 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005196 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005197 bool IsSuper,
5198 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005199 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005200 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005201
Douglas Gregor24a069f2009-11-17 17:59:40 +00005202 // If the given name refers to an interface type, retrieve the
5203 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005204 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005205 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005206 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005207 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5208 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005209 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005210
Douglas Gregor36ecb042009-11-17 23:22:23 +00005211 // Add all of the factory methods in this Objective-C class, its protocols,
5212 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005213 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005214
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005215 // If this is a send-to-super, try to add the special "super" send
5216 // completion.
5217 if (IsSuper) {
5218 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005219 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5220 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005221 Results.Ignore(SuperMethod);
5222 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005223
Douglas Gregor265f7492010-08-27 15:29:55 +00005224 // If we're inside an Objective-C method definition, prefer its selector to
5225 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005226 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005227 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005228
Douglas Gregord36adf52010-09-16 16:06:31 +00005229 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005230 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005231 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005232 SemaRef.CurContext, Selectors, AtArgumentExpression,
5233 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005234 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005235 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005236
Douglas Gregor719770d2010-04-06 17:30:22 +00005237 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005238 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005239 if (SemaRef.ExternalSource) {
5240 for (uint32_t I = 0,
5241 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005242 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005243 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5244 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005245 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005246
5247 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005248 }
5249 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005250
5251 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5252 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005253 M != MEnd; ++M) {
5254 for (ObjCMethodList *MethList = &M->second.second;
5255 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005256 MethList = MethList->Next) {
5257 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5258 NumSelIdents))
5259 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005260
Douglas Gregor13438f92010-04-06 16:40:00 +00005261 Result R(MethList->Method, 0);
5262 R.StartParameter = NumSelIdents;
5263 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005264 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005265 }
5266 }
5267 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005268
5269 Results.ExitScope();
5270}
Douglas Gregor13438f92010-04-06 16:40:00 +00005271
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005272void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5273 IdentifierInfo **SelIdents,
5274 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005275 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005276 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005277
5278 QualType T = this->GetTypeFromParser(Receiver);
5279
Douglas Gregor218937c2011-02-01 19:23:04 +00005280 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005281 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005282 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005283
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005284 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5285 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005286
5287 // If we're actually at the argument expression (rather than prior to the
5288 // selector), we're actually performing code completion for an expression.
5289 // Determine whether we have a single, best method. If so, we can
5290 // code-complete the expression using the corresponding parameter type as
5291 // our preferred type, improving completion results.
5292 if (AtArgumentExpression) {
5293 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005294 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005295 if (PreferredType.isNull())
5296 CodeCompleteOrdinaryName(S, PCC_Expression);
5297 else
5298 CodeCompleteExpression(S, PreferredType);
5299 return;
5300 }
5301
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005302 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005303 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005304 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005305}
5306
Richard Trieuf81e5a92011-09-09 02:00:50 +00005307void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005308 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005309 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005310 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005311 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005312 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005313
5314 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005315
Douglas Gregor36ecb042009-11-17 23:22:23 +00005316 // If necessary, apply function/array conversion to the receiver.
5317 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005318 if (RecExpr) {
5319 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5320 if (Conv.isInvalid()) // conversion failed. bail.
5321 return;
5322 RecExpr = Conv.take();
5323 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005324 QualType ReceiverType = RecExpr? RecExpr->getType()
5325 : Super? Context.getObjCObjectPointerType(
5326 Context.getObjCInterfaceType(Super))
5327 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005328
Douglas Gregorda892642010-11-08 21:12:30 +00005329 // If we're messaging an expression with type "id" or "Class", check
5330 // whether we know something special about the receiver that allows
5331 // us to assume a more-specific receiver type.
5332 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5333 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5334 if (ReceiverType->isObjCClassType())
5335 return CodeCompleteObjCClassMessage(S,
5336 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5337 SelIdents, NumSelIdents,
5338 AtArgumentExpression, Super);
5339
5340 ReceiverType = Context.getObjCObjectPointerType(
5341 Context.getObjCInterfaceType(IFace));
5342 }
5343
Douglas Gregor36ecb042009-11-17 23:22:23 +00005344 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005345 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005346 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005347 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005348
Douglas Gregor36ecb042009-11-17 23:22:23 +00005349 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005350
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005351 // If this is a send-to-super, try to add the special "super" send
5352 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005353 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005354 if (ObjCMethodDecl *SuperMethod
5355 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5356 Results))
5357 Results.Ignore(SuperMethod);
5358 }
5359
Douglas Gregor265f7492010-08-27 15:29:55 +00005360 // If we're inside an Objective-C method definition, prefer its selector to
5361 // others.
5362 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5363 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005364
Douglas Gregord36adf52010-09-16 16:06:31 +00005365 // Keep track of the selectors we've already added.
5366 VisitedSelectorSet Selectors;
5367
Douglas Gregorf74a4192009-11-18 00:06:18 +00005368 // Handle messages to Class. This really isn't a message to an instance
5369 // method, so we treat it the same way we would treat a message send to a
5370 // class method.
5371 if (ReceiverType->isObjCClassType() ||
5372 ReceiverType->isObjCQualifiedClassType()) {
5373 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5374 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005375 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005376 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005377 }
5378 }
5379 // Handle messages to a qualified ID ("id<foo>").
5380 else if (const ObjCObjectPointerType *QualID
5381 = ReceiverType->getAsObjCQualifiedIdType()) {
5382 // Search protocols for instance methods.
5383 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5384 E = QualID->qual_end();
5385 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005386 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005387 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005388 }
5389 // Handle messages to a pointer to interface type.
5390 else if (const ObjCObjectPointerType *IFacePtr
5391 = ReceiverType->getAsObjCInterfacePointerType()) {
5392 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005393 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005394 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5395 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005396
5397 // Search protocols for instance methods.
5398 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5399 E = IFacePtr->qual_end();
5400 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005401 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005402 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005403 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005404 // Handle messages to "id".
5405 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005406 // We're messaging "id", so provide all instance methods we know
5407 // about as code-completion results.
5408
5409 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005410 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005411 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005412 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5413 I != N; ++I) {
5414 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005415 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005416 continue;
5417
Sebastian Redldb9d2142010-08-02 23:18:59 +00005418 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005419 }
5420 }
5421
Sebastian Redldb9d2142010-08-02 23:18:59 +00005422 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5423 MEnd = MethodPool.end();
5424 M != MEnd; ++M) {
5425 for (ObjCMethodList *MethList = &M->second.first;
5426 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005427 MethList = MethList->Next) {
5428 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5429 NumSelIdents))
5430 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005431
5432 if (!Selectors.insert(MethList->Method->getSelector()))
5433 continue;
5434
Douglas Gregor13438f92010-04-06 16:40:00 +00005435 Result R(MethList->Method, 0);
5436 R.StartParameter = NumSelIdents;
5437 R.AllParametersAreInformative = false;
5438 Results.MaybeAddResult(R, CurContext);
5439 }
5440 }
5441 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005442 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005443
5444
5445 // If we're actually at the argument expression (rather than prior to the
5446 // selector), we're actually performing code completion for an expression.
5447 // Determine whether we have a single, best method. If so, we can
5448 // code-complete the expression using the corresponding parameter type as
5449 // our preferred type, improving completion results.
5450 if (AtArgumentExpression) {
5451 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5452 NumSelIdents);
5453 if (PreferredType.isNull())
5454 CodeCompleteOrdinaryName(S, PCC_Expression);
5455 else
5456 CodeCompleteExpression(S, PreferredType);
5457 return;
5458 }
5459
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005460 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005461 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005462 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005463}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005464
Douglas Gregorfb629412010-08-23 21:17:50 +00005465void Sema::CodeCompleteObjCForCollection(Scope *S,
5466 DeclGroupPtrTy IterationVar) {
5467 CodeCompleteExpressionData Data;
5468 Data.ObjCCollection = true;
5469
5470 if (IterationVar.getAsOpaquePtr()) {
5471 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5472 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5473 if (*I)
5474 Data.IgnoreDecls.push_back(*I);
5475 }
5476 }
5477
5478 CodeCompleteExpression(S, Data);
5479}
5480
Douglas Gregor458433d2010-08-26 15:07:07 +00005481void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5482 unsigned NumSelIdents) {
5483 // If we have an external source, load the entire class method
5484 // pool from the AST file.
5485 if (ExternalSource) {
5486 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5487 I != N; ++I) {
5488 Selector Sel = ExternalSource->GetExternalSelector(I);
5489 if (Sel.isNull() || MethodPool.count(Sel))
5490 continue;
5491
5492 ReadMethodPool(Sel);
5493 }
5494 }
5495
Douglas Gregor218937c2011-02-01 19:23:04 +00005496 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5497 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005498 Results.EnterNewScope();
5499 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5500 MEnd = MethodPool.end();
5501 M != MEnd; ++M) {
5502
5503 Selector Sel = M->first;
5504 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5505 continue;
5506
Douglas Gregor218937c2011-02-01 19:23:04 +00005507 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor458433d2010-08-26 15:07:07 +00005508 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005509 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005510 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005511 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005512 continue;
5513 }
5514
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005515 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005516 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005517 if (I == NumSelIdents) {
5518 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005519 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005520 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005521 Accumulator.clear();
5522 }
5523 }
5524
Benjamin Kramera0651c52011-07-26 16:59:25 +00005525 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005526 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005527 }
Douglas Gregordae68752011-02-01 22:57:45 +00005528 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005529 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005530 }
5531 Results.ExitScope();
5532
5533 HandleCodeCompleteResults(this, CodeCompleter,
5534 CodeCompletionContext::CCC_SelectorName,
5535 Results.data(), Results.size());
5536}
5537
Douglas Gregor55385fe2009-11-18 04:19:12 +00005538/// \brief Add all of the protocol declarations that we find in the given
5539/// (translation unit) context.
5540static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005541 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005542 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005543 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005544
5545 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5546 DEnd = Ctx->decls_end();
5547 D != DEnd; ++D) {
5548 // Record any protocols we find.
5549 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005550 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005551 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005552 }
5553}
5554
5555void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5556 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005557 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5558 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005559
Douglas Gregor70c23352010-12-09 21:44:02 +00005560 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5561 Results.EnterNewScope();
5562
5563 // Tell the result set to ignore all of the protocols we have
5564 // already seen.
5565 // FIXME: This doesn't work when caching code-completion results.
5566 for (unsigned I = 0; I != NumProtocols; ++I)
5567 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5568 Protocols[I].second))
5569 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005570
Douglas Gregor70c23352010-12-09 21:44:02 +00005571 // Add all protocols.
5572 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5573 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005574
Douglas Gregor70c23352010-12-09 21:44:02 +00005575 Results.ExitScope();
5576 }
5577
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005578 HandleCodeCompleteResults(this, CodeCompleter,
5579 CodeCompletionContext::CCC_ObjCProtocolName,
5580 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005581}
5582
5583void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005584 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5585 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005586
Douglas Gregor70c23352010-12-09 21:44:02 +00005587 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5588 Results.EnterNewScope();
5589
5590 // Add all protocols.
5591 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5592 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005593
Douglas Gregor70c23352010-12-09 21:44:02 +00005594 Results.ExitScope();
5595 }
5596
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005597 HandleCodeCompleteResults(this, CodeCompleter,
5598 CodeCompletionContext::CCC_ObjCProtocolName,
5599 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005600}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005601
5602/// \brief Add all of the Objective-C interface declarations that we find in
5603/// the given (translation unit) context.
5604static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5605 bool OnlyForwardDeclarations,
5606 bool OnlyUnimplemented,
5607 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005608 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005609
5610 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5611 DEnd = Ctx->decls_end();
5612 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005613 // Record any interfaces we find.
5614 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005615 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005616 (!OnlyUnimplemented || !Class->getImplementation()))
5617 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005618 }
5619}
5620
5621void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005622 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5623 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005624 Results.EnterNewScope();
5625
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005626 if (CodeCompleter->includeGlobals()) {
5627 // Add all classes.
5628 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5629 false, Results);
5630 }
5631
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005632 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005633
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005634 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005635 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005636 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005637}
5638
Douglas Gregorc83c6872010-04-15 22:33:43 +00005639void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5640 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005641 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005642 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005643 Results.EnterNewScope();
5644
5645 // Make sure that we ignore the class we're currently defining.
5646 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005647 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005648 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005649 Results.Ignore(CurClass);
5650
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005651 if (CodeCompleter->includeGlobals()) {
5652 // Add all classes.
5653 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5654 false, Results);
5655 }
5656
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005657 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005658
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005659 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005660 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005661 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005662}
5663
5664void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005665 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5666 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005667 Results.EnterNewScope();
5668
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005669 if (CodeCompleter->includeGlobals()) {
5670 // Add all unimplemented classes.
5671 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5672 true, Results);
5673 }
5674
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005675 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005676
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005677 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005678 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005679 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005680}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005681
5682void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005683 IdentifierInfo *ClassName,
5684 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005685 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005686
Douglas Gregor218937c2011-02-01 19:23:04 +00005687 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005688 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005689
5690 // Ignore any categories we find that have already been implemented by this
5691 // interface.
5692 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5693 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005694 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005695 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5696 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5697 Category = Category->getNextClassCategory())
5698 CategoryNames.insert(Category->getIdentifier());
5699
5700 // Add all of the categories we know about.
5701 Results.EnterNewScope();
5702 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5703 for (DeclContext::decl_iterator D = TU->decls_begin(),
5704 DEnd = TU->decls_end();
5705 D != DEnd; ++D)
5706 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5707 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005708 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005709 Results.ExitScope();
5710
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005711 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005712 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005713 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005714}
5715
5716void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005717 IdentifierInfo *ClassName,
5718 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005719 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005720
5721 // Find the corresponding interface. If we couldn't find the interface, the
5722 // program itself is ill-formed. However, we'll try to be helpful still by
5723 // providing the list of all of the categories we know about.
5724 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005725 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005726 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5727 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005728 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005729
Douglas Gregor218937c2011-02-01 19:23:04 +00005730 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005731 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005732
5733 // Add all of the categories that have have corresponding interface
5734 // declarations in this class and any of its superclasses, except for
5735 // already-implemented categories in the class itself.
5736 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5737 Results.EnterNewScope();
5738 bool IgnoreImplemented = true;
5739 while (Class) {
5740 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5741 Category = Category->getNextClassCategory())
5742 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5743 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005744 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005745
5746 Class = Class->getSuperClass();
5747 IgnoreImplemented = false;
5748 }
5749 Results.ExitScope();
5750
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005751 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005752 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005753 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005754}
Douglas Gregor322328b2009-11-18 22:32:06 +00005755
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005756void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005757 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005758 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5759 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005760
5761 // Figure out where this @synthesize lives.
5762 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005763 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005764 if (!Container ||
5765 (!isa<ObjCImplementationDecl>(Container) &&
5766 !isa<ObjCCategoryImplDecl>(Container)))
5767 return;
5768
5769 // Ignore any properties that have already been implemented.
5770 for (DeclContext::decl_iterator D = Container->decls_begin(),
5771 DEnd = Container->decls_end();
5772 D != DEnd; ++D)
5773 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5774 Results.Ignore(PropertyImpl->getPropertyDecl());
5775
5776 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005777 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005778 Results.EnterNewScope();
5779 if (ObjCImplementationDecl *ClassImpl
5780 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005781 AddObjCProperties(ClassImpl->getClassInterface(), false,
5782 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005783 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005784 else
5785 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005786 false, /*AllowNullaryMethods=*/false, CurContext,
5787 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005788 Results.ExitScope();
5789
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005790 HandleCodeCompleteResults(this, CodeCompleter,
5791 CodeCompletionContext::CCC_Other,
5792 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005793}
5794
5795void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005796 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005797 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005798 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5799 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005800
5801 // Figure out where this @synthesize lives.
5802 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005803 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005804 if (!Container ||
5805 (!isa<ObjCImplementationDecl>(Container) &&
5806 !isa<ObjCCategoryImplDecl>(Container)))
5807 return;
5808
5809 // Figure out which interface we're looking into.
5810 ObjCInterfaceDecl *Class = 0;
5811 if (ObjCImplementationDecl *ClassImpl
5812 = dyn_cast<ObjCImplementationDecl>(Container))
5813 Class = ClassImpl->getClassInterface();
5814 else
5815 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5816 ->getClassInterface();
5817
Douglas Gregore8426052011-04-18 14:40:46 +00005818 // Determine the type of the property we're synthesizing.
5819 QualType PropertyType = Context.getObjCIdType();
5820 if (Class) {
5821 if (ObjCPropertyDecl *Property
5822 = Class->FindPropertyDeclaration(PropertyName)) {
5823 PropertyType
5824 = Property->getType().getNonReferenceType().getUnqualifiedType();
5825
5826 // Give preference to ivars
5827 Results.setPreferredType(PropertyType);
5828 }
5829 }
5830
Douglas Gregor322328b2009-11-18 22:32:06 +00005831 // Add all of the instance variables in this class and its superclasses.
5832 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005833 bool SawSimilarlyNamedIvar = false;
5834 std::string NameWithPrefix;
5835 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005836 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005837 std::string NameWithSuffix = PropertyName->getName().str();
5838 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005839 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005840 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5841 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005842 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5843
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005844 // Determine whether we've seen an ivar with a name similar to the
5845 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005846 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005847 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005848 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005849 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005850
5851 // Reduce the priority of this result by one, to give it a slight
5852 // advantage over other results whose names don't match so closely.
5853 if (Results.size() &&
5854 Results.data()[Results.size() - 1].Kind
5855 == CodeCompletionResult::RK_Declaration &&
5856 Results.data()[Results.size() - 1].Declaration == Ivar)
5857 Results.data()[Results.size() - 1].Priority--;
5858 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005859 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005860 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005861
5862 if (!SawSimilarlyNamedIvar) {
5863 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005864 // an ivar of the appropriate type.
5865 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005866 typedef CodeCompletionResult Result;
5867 CodeCompletionAllocator &Allocator = Results.getAllocator();
5868 CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available);
5869
Douglas Gregor8987b232011-09-27 23:30:47 +00005870 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00005871 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005872 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005873 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5874 Results.AddResult(Result(Builder.TakeString(), Priority,
5875 CXCursor_ObjCIvarDecl));
5876 }
5877
Douglas Gregor322328b2009-11-18 22:32:06 +00005878 Results.ExitScope();
5879
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005880 HandleCodeCompleteResults(this, CodeCompleter,
5881 CodeCompletionContext::CCC_Other,
5882 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005883}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005884
Douglas Gregor408be5a2010-08-25 01:08:01 +00005885// Mapping from selectors to the methods that implement that selector, along
5886// with the "in original class" flag.
5887typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5888 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005889
5890/// \brief Find all of the methods that reside in the given container
5891/// (and its superclasses, protocols, etc.) that meet the given
5892/// criteria. Insert those methods into the map of known methods,
5893/// indexed by selector so they can be easily found.
5894static void FindImplementableMethods(ASTContext &Context,
5895 ObjCContainerDecl *Container,
5896 bool WantInstanceMethods,
5897 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00005898 KnownMethodsMap &KnownMethods,
5899 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005900 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5901 // Recurse into protocols.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00005902 if (!IFace->hasDefinition())
5903 return;
5904
Douglas Gregore8f5a172010-04-07 00:21:17 +00005905 const ObjCList<ObjCProtocolDecl> &Protocols
5906 = IFace->getReferencedProtocols();
5907 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005908 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005909 I != E; ++I)
5910 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005911 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005912
Douglas Gregorea766182010-10-18 18:21:28 +00005913 // Add methods from any class extensions and categories.
5914 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5915 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00005916 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5917 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005918 KnownMethods, false);
5919
5920 // Visit the superclass.
5921 if (IFace->getSuperClass())
5922 FindImplementableMethods(Context, IFace->getSuperClass(),
5923 WantInstanceMethods, ReturnType,
5924 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005925 }
5926
5927 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5928 // Recurse into protocols.
5929 const ObjCList<ObjCProtocolDecl> &Protocols
5930 = Category->getReferencedProtocols();
5931 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005932 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005933 I != E; ++I)
5934 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005935 KnownMethods, InOriginalClass);
5936
5937 // If this category is the original class, jump to the interface.
5938 if (InOriginalClass && Category->getClassInterface())
5939 FindImplementableMethods(Context, Category->getClassInterface(),
5940 WantInstanceMethods, ReturnType, KnownMethods,
5941 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005942 }
5943
5944 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005945 if (Protocol->hasDefinition()) {
5946 // Recurse into protocols.
5947 const ObjCList<ObjCProtocolDecl> &Protocols
5948 = Protocol->getReferencedProtocols();
5949 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5950 E = Protocols.end();
5951 I != E; ++I)
5952 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
5953 KnownMethods, false);
5954 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00005955 }
5956
5957 // Add methods in this container. This operation occurs last because
5958 // we want the methods from this container to override any methods
5959 // we've previously seen with the same selector.
5960 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
5961 MEnd = Container->meth_end();
5962 M != MEnd; ++M) {
5963 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
5964 if (!ReturnType.isNull() &&
5965 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
5966 continue;
5967
Douglas Gregor408be5a2010-08-25 01:08:01 +00005968 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005969 }
5970 }
5971}
5972
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005973/// \brief Add the parenthesized return or parameter type chunk to a code
5974/// completion string.
5975static void AddObjCPassingTypeChunk(QualType Type,
5976 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005977 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005978 CodeCompletionBuilder &Builder) {
5979 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor8987b232011-09-27 23:30:47 +00005980 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005981 Builder.getAllocator()));
5982 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5983}
5984
5985/// \brief Determine whether the given class is or inherits from a class by
5986/// the given name.
5987static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00005988 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005989 if (!Class)
5990 return false;
5991
5992 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
5993 return true;
5994
5995 return InheritsFromClassNamed(Class->getSuperClass(), Name);
5996}
5997
5998/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
5999/// Key-Value Observing (KVO).
6000static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6001 bool IsInstanceMethod,
6002 QualType ReturnType,
6003 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006004 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006005 ResultBuilder &Results) {
6006 IdentifierInfo *PropName = Property->getIdentifier();
6007 if (!PropName || PropName->getLength() == 0)
6008 return;
6009
Douglas Gregor8987b232011-09-27 23:30:47 +00006010 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6011
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006012 // Builder that will create each code completion.
6013 typedef CodeCompletionResult Result;
6014 CodeCompletionAllocator &Allocator = Results.getAllocator();
6015 CodeCompletionBuilder Builder(Allocator);
6016
6017 // The selector table.
6018 SelectorTable &Selectors = Context.Selectors;
6019
6020 // The property name, copied into the code completion allocation region
6021 // on demand.
6022 struct KeyHolder {
6023 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006024 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006025 const char *CopiedKey;
6026
Chris Lattner5f9e2722011-07-23 10:55:15 +00006027 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006028 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6029
6030 operator const char *() {
6031 if (CopiedKey)
6032 return CopiedKey;
6033
6034 return CopiedKey = Allocator.CopyString(Key);
6035 }
6036 } Key(Allocator, PropName->getName());
6037
6038 // The uppercased name of the property name.
6039 std::string UpperKey = PropName->getName();
6040 if (!UpperKey.empty())
6041 UpperKey[0] = toupper(UpperKey[0]);
6042
6043 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6044 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6045 Property->getType());
6046 bool ReturnTypeMatchesVoid
6047 = ReturnType.isNull() || ReturnType->isVoidType();
6048
6049 // Add the normal accessor -(type)key.
6050 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006051 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006052 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6053 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00006054 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006055
6056 Builder.AddTypedTextChunk(Key);
6057 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6058 CXCursor_ObjCInstanceMethodDecl));
6059 }
6060
6061 // If we have an integral or boolean property (or the user has provided
6062 // an integral or boolean return type), add the accessor -(type)isKey.
6063 if (IsInstanceMethod &&
6064 ((!ReturnType.isNull() &&
6065 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6066 (ReturnType.isNull() &&
6067 (Property->getType()->isIntegerType() ||
6068 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006069 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006070 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006071 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006072 if (ReturnType.isNull()) {
6073 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6074 Builder.AddTextChunk("BOOL");
6075 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6076 }
6077
6078 Builder.AddTypedTextChunk(
6079 Allocator.CopyString(SelectorId->getName()));
6080 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6081 CXCursor_ObjCInstanceMethodDecl));
6082 }
6083 }
6084
6085 // Add the normal mutator.
6086 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6087 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006088 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006089 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006090 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006091 if (ReturnType.isNull()) {
6092 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6093 Builder.AddTextChunk("void");
6094 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6095 }
6096
6097 Builder.AddTypedTextChunk(
6098 Allocator.CopyString(SelectorId->getName()));
6099 Builder.AddTypedTextChunk(":");
Douglas Gregor8987b232011-09-27 23:30:47 +00006100 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006101 Builder.AddTextChunk(Key);
6102 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6103 CXCursor_ObjCInstanceMethodDecl));
6104 }
6105 }
6106
6107 // Indexed and unordered accessors
6108 unsigned IndexedGetterPriority = CCP_CodePattern;
6109 unsigned IndexedSetterPriority = CCP_CodePattern;
6110 unsigned UnorderedGetterPriority = CCP_CodePattern;
6111 unsigned UnorderedSetterPriority = CCP_CodePattern;
6112 if (const ObjCObjectPointerType *ObjCPointer
6113 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6114 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6115 // If this interface type is not provably derived from a known
6116 // collection, penalize the corresponding completions.
6117 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6118 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6119 if (!InheritsFromClassNamed(IFace, "NSArray"))
6120 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6121 }
6122
6123 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6124 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6125 if (!InheritsFromClassNamed(IFace, "NSSet"))
6126 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6127 }
6128 }
6129 } else {
6130 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6131 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6132 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6133 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6134 }
6135
6136 // Add -(NSUInteger)countOf<key>
6137 if (IsInstanceMethod &&
6138 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006139 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006140 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006141 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006142 if (ReturnType.isNull()) {
6143 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6144 Builder.AddTextChunk("NSUInteger");
6145 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6146 }
6147
6148 Builder.AddTypedTextChunk(
6149 Allocator.CopyString(SelectorId->getName()));
6150 Results.AddResult(Result(Builder.TakeString(),
6151 std::min(IndexedGetterPriority,
6152 UnorderedGetterPriority),
6153 CXCursor_ObjCInstanceMethodDecl));
6154 }
6155 }
6156
6157 // Indexed getters
6158 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6159 if (IsInstanceMethod &&
6160 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006161 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006162 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006163 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006164 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006165 if (ReturnType.isNull()) {
6166 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6167 Builder.AddTextChunk("id");
6168 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6169 }
6170
6171 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6172 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6173 Builder.AddTextChunk("NSUInteger");
6174 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6175 Builder.AddTextChunk("index");
6176 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6177 CXCursor_ObjCInstanceMethodDecl));
6178 }
6179 }
6180
6181 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6182 if (IsInstanceMethod &&
6183 (ReturnType.isNull() ||
6184 (ReturnType->isObjCObjectPointerType() &&
6185 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6186 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6187 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006188 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006189 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006190 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006191 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006192 if (ReturnType.isNull()) {
6193 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6194 Builder.AddTextChunk("NSArray *");
6195 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6196 }
6197
6198 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6199 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6200 Builder.AddTextChunk("NSIndexSet *");
6201 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6202 Builder.AddTextChunk("indexes");
6203 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6204 CXCursor_ObjCInstanceMethodDecl));
6205 }
6206 }
6207
6208 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6209 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006210 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006211 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006212 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006213 &Context.Idents.get("range")
6214 };
6215
Douglas Gregore74c25c2011-05-04 23:50:46 +00006216 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006217 if (ReturnType.isNull()) {
6218 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6219 Builder.AddTextChunk("void");
6220 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6221 }
6222
6223 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6224 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6225 Builder.AddPlaceholderChunk("object-type");
6226 Builder.AddTextChunk(" **");
6227 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6228 Builder.AddTextChunk("buffer");
6229 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6230 Builder.AddTypedTextChunk("range:");
6231 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6232 Builder.AddTextChunk("NSRange");
6233 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6234 Builder.AddTextChunk("inRange");
6235 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6236 CXCursor_ObjCInstanceMethodDecl));
6237 }
6238 }
6239
6240 // Mutable indexed accessors
6241
6242 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6243 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006244 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006245 IdentifierInfo *SelectorIds[2] = {
6246 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006247 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006248 };
6249
Douglas Gregore74c25c2011-05-04 23:50:46 +00006250 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006251 if (ReturnType.isNull()) {
6252 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6253 Builder.AddTextChunk("void");
6254 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6255 }
6256
6257 Builder.AddTypedTextChunk("insertObject:");
6258 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6259 Builder.AddPlaceholderChunk("object-type");
6260 Builder.AddTextChunk(" *");
6261 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6262 Builder.AddTextChunk("object");
6263 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6264 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6265 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6266 Builder.AddPlaceholderChunk("NSUInteger");
6267 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6268 Builder.AddTextChunk("index");
6269 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6270 CXCursor_ObjCInstanceMethodDecl));
6271 }
6272 }
6273
6274 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6275 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006276 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006277 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006278 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006279 &Context.Idents.get("atIndexes")
6280 };
6281
Douglas Gregore74c25c2011-05-04 23:50:46 +00006282 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006283 if (ReturnType.isNull()) {
6284 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6285 Builder.AddTextChunk("void");
6286 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6287 }
6288
6289 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6290 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6291 Builder.AddTextChunk("NSArray *");
6292 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6293 Builder.AddTextChunk("array");
6294 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6295 Builder.AddTypedTextChunk("atIndexes:");
6296 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6297 Builder.AddPlaceholderChunk("NSIndexSet *");
6298 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6299 Builder.AddTextChunk("indexes");
6300 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6301 CXCursor_ObjCInstanceMethodDecl));
6302 }
6303 }
6304
6305 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6306 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006307 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006308 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006309 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006310 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006311 if (ReturnType.isNull()) {
6312 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6313 Builder.AddTextChunk("void");
6314 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6315 }
6316
6317 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6318 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6319 Builder.AddTextChunk("NSUInteger");
6320 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6321 Builder.AddTextChunk("index");
6322 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6323 CXCursor_ObjCInstanceMethodDecl));
6324 }
6325 }
6326
6327 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6328 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006329 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006330 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006331 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006332 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006333 if (ReturnType.isNull()) {
6334 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6335 Builder.AddTextChunk("void");
6336 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6337 }
6338
6339 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6340 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6341 Builder.AddTextChunk("NSIndexSet *");
6342 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6343 Builder.AddTextChunk("indexes");
6344 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6345 CXCursor_ObjCInstanceMethodDecl));
6346 }
6347 }
6348
6349 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6350 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006351 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006352 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006353 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006354 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006355 &Context.Idents.get("withObject")
6356 };
6357
Douglas Gregore74c25c2011-05-04 23:50:46 +00006358 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006359 if (ReturnType.isNull()) {
6360 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6361 Builder.AddTextChunk("void");
6362 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6363 }
6364
6365 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6366 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6367 Builder.AddPlaceholderChunk("NSUInteger");
6368 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6369 Builder.AddTextChunk("index");
6370 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6371 Builder.AddTypedTextChunk("withObject:");
6372 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6373 Builder.AddTextChunk("id");
6374 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6375 Builder.AddTextChunk("object");
6376 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6377 CXCursor_ObjCInstanceMethodDecl));
6378 }
6379 }
6380
6381 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6382 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006383 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006384 = (Twine("replace") + UpperKey + "AtIndexes").str();
6385 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006386 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006387 &Context.Idents.get(SelectorName1),
6388 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006389 };
6390
Douglas Gregore74c25c2011-05-04 23:50:46 +00006391 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006392 if (ReturnType.isNull()) {
6393 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6394 Builder.AddTextChunk("void");
6395 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6396 }
6397
6398 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6399 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6400 Builder.AddPlaceholderChunk("NSIndexSet *");
6401 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6402 Builder.AddTextChunk("indexes");
6403 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6404 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6405 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6406 Builder.AddTextChunk("NSArray *");
6407 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6408 Builder.AddTextChunk("array");
6409 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6410 CXCursor_ObjCInstanceMethodDecl));
6411 }
6412 }
6413
6414 // Unordered getters
6415 // - (NSEnumerator *)enumeratorOfKey
6416 if (IsInstanceMethod &&
6417 (ReturnType.isNull() ||
6418 (ReturnType->isObjCObjectPointerType() &&
6419 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6420 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6421 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006422 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006423 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006424 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006425 if (ReturnType.isNull()) {
6426 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6427 Builder.AddTextChunk("NSEnumerator *");
6428 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6429 }
6430
6431 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6432 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6433 CXCursor_ObjCInstanceMethodDecl));
6434 }
6435 }
6436
6437 // - (type *)memberOfKey:(type *)object
6438 if (IsInstanceMethod &&
6439 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006440 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006441 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006442 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006443 if (ReturnType.isNull()) {
6444 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6445 Builder.AddPlaceholderChunk("object-type");
6446 Builder.AddTextChunk(" *");
6447 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6448 }
6449
6450 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6451 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6452 if (ReturnType.isNull()) {
6453 Builder.AddPlaceholderChunk("object-type");
6454 Builder.AddTextChunk(" *");
6455 } else {
6456 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006457 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006458 Builder.getAllocator()));
6459 }
6460 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6461 Builder.AddTextChunk("object");
6462 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6463 CXCursor_ObjCInstanceMethodDecl));
6464 }
6465 }
6466
6467 // Mutable unordered accessors
6468 // - (void)addKeyObject:(type *)object
6469 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006470 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006471 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006472 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006473 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
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("object-type");
6483 Builder.AddTextChunk(" *");
6484 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6485 Builder.AddTextChunk("object");
6486 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6487 CXCursor_ObjCInstanceMethodDecl));
6488 }
6489 }
6490
6491 // - (void)addKey:(NSSet *)objects
6492 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006493 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006494 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006495 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006496 if (ReturnType.isNull()) {
6497 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6498 Builder.AddTextChunk("void");
6499 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6500 }
6501
6502 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6503 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6504 Builder.AddTextChunk("NSSet *");
6505 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6506 Builder.AddTextChunk("objects");
6507 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6508 CXCursor_ObjCInstanceMethodDecl));
6509 }
6510 }
6511
6512 // - (void)removeKeyObject:(type *)object
6513 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006514 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006515 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006516 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006517 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006518 if (ReturnType.isNull()) {
6519 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6520 Builder.AddTextChunk("void");
6521 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6522 }
6523
6524 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6525 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6526 Builder.AddPlaceholderChunk("object-type");
6527 Builder.AddTextChunk(" *");
6528 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6529 Builder.AddTextChunk("object");
6530 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6531 CXCursor_ObjCInstanceMethodDecl));
6532 }
6533 }
6534
6535 // - (void)removeKey:(NSSet *)objects
6536 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006537 std::string SelectorName = (Twine("remove") + 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.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006540 if (ReturnType.isNull()) {
6541 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6542 Builder.AddTextChunk("void");
6543 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6544 }
6545
6546 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6547 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6548 Builder.AddTextChunk("NSSet *");
6549 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6550 Builder.AddTextChunk("objects");
6551 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6552 CXCursor_ObjCInstanceMethodDecl));
6553 }
6554 }
6555
6556 // - (void)intersectKey:(NSSet *)objects
6557 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006558 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006559 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006560 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006561 if (ReturnType.isNull()) {
6562 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6563 Builder.AddTextChunk("void");
6564 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6565 }
6566
6567 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6568 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6569 Builder.AddTextChunk("NSSet *");
6570 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6571 Builder.AddTextChunk("objects");
6572 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6573 CXCursor_ObjCInstanceMethodDecl));
6574 }
6575 }
6576
6577 // Key-Value Observing
6578 // + (NSSet *)keyPathsForValuesAffectingKey
6579 if (!IsInstanceMethod &&
6580 (ReturnType.isNull() ||
6581 (ReturnType->isObjCObjectPointerType() &&
6582 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6583 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6584 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006585 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006586 = (Twine("keyPathsForValuesAffecting") + UpperKey).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.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006589 if (ReturnType.isNull()) {
6590 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6591 Builder.AddTextChunk("NSSet *");
6592 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6593 }
6594
6595 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6596 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006597 CXCursor_ObjCClassMethodDecl));
6598 }
6599 }
6600
6601 // + (BOOL)automaticallyNotifiesObserversForKey
6602 if (!IsInstanceMethod &&
6603 (ReturnType.isNull() ||
6604 ReturnType->isIntegerType() ||
6605 ReturnType->isBooleanType())) {
6606 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006607 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006608 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6609 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6610 if (ReturnType.isNull()) {
6611 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6612 Builder.AddTextChunk("BOOL");
6613 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6614 }
6615
6616 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6617 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6618 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006619 }
6620 }
6621}
6622
Douglas Gregore8f5a172010-04-07 00:21:17 +00006623void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6624 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006625 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006626 // Determine the return type of the method we're declaring, if
6627 // provided.
6628 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006629 Decl *IDecl = 0;
6630 if (CurContext->isObjCContainer()) {
6631 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6632 IDecl = cast<Decl>(OCD);
6633 }
Douglas Gregorea766182010-10-18 18:21:28 +00006634 // Determine where we should start searching for methods.
6635 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006636 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006637 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006638 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6639 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006640 IsInImplementation = true;
6641 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006642 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006643 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006644 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006645 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006646 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006647 }
6648
6649 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006650 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006651 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006652 }
6653
Douglas Gregorea766182010-10-18 18:21:28 +00006654 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006655 HandleCodeCompleteResults(this, CodeCompleter,
6656 CodeCompletionContext::CCC_Other,
6657 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006658 return;
6659 }
6660
6661 // Find all of the methods that we could declare/implement here.
6662 KnownMethodsMap KnownMethods;
6663 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006664 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006665
Douglas Gregore8f5a172010-04-07 00:21:17 +00006666 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006667 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006668 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6669 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006670 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006671 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006672 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6673 MEnd = KnownMethods.end();
6674 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006675 ObjCMethodDecl *Method = M->second.first;
Douglas Gregor218937c2011-02-01 19:23:04 +00006676 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006677
6678 // If the result type was not already provided, add it to the
6679 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006680 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00006681 AddObjCPassingTypeChunk(Method->getResultType(), Context, Policy,
6682 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006683
6684 Selector Sel = Method->getSelector();
6685
6686 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006687 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006688 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006689
6690 // Add parameters to the pattern.
6691 unsigned I = 0;
6692 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6693 PEnd = Method->param_end();
6694 P != PEnd; (void)++P, ++I) {
6695 // Add the part of the selector name.
6696 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006697 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006698 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006699 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6700 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006701 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006702 } else
6703 break;
6704
6705 // Add the parameter type.
Douglas Gregor8987b232011-09-27 23:30:47 +00006706 AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Policy,
6707 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006708
6709 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006710 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006711 }
6712
6713 if (Method->isVariadic()) {
6714 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006715 Builder.AddChunk(CodeCompletionString::CK_Comma);
6716 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006717 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006718
Douglas Gregor447107d2010-05-28 00:57:46 +00006719 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006720 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006721 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6722 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6723 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006724 if (!Method->getResultType()->isVoidType()) {
6725 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006726 Builder.AddTextChunk("return");
6727 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6728 Builder.AddPlaceholderChunk("expression");
6729 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006730 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006731 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006732
Douglas Gregor218937c2011-02-01 19:23:04 +00006733 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6734 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006735 }
6736
Douglas Gregor408be5a2010-08-25 01:08:01 +00006737 unsigned Priority = CCP_CodePattern;
6738 if (!M->second.second)
6739 Priority += CCD_InBaseClass;
6740
Douglas Gregorba103062012-03-27 23:34:16 +00006741 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006742 }
6743
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006744 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6745 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006746 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006747 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006748 Containers.push_back(SearchDecl);
6749
Douglas Gregore74c25c2011-05-04 23:50:46 +00006750 VisitedSelectorSet KnownSelectors;
6751 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6752 MEnd = KnownMethods.end();
6753 M != MEnd; ++M)
6754 KnownSelectors.insert(M->first);
6755
6756
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006757 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6758 if (!IFace)
6759 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6760 IFace = Category->getClassInterface();
6761
6762 if (IFace) {
6763 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6764 Category = Category->getNextClassCategory())
6765 Containers.push_back(Category);
6766 }
6767
6768 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6769 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6770 PEnd = Containers[I]->prop_end();
6771 P != PEnd; ++P) {
6772 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006773 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006774 }
6775 }
6776 }
6777
Douglas Gregore8f5a172010-04-07 00:21:17 +00006778 Results.ExitScope();
6779
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006780 HandleCodeCompleteResults(this, CodeCompleter,
6781 CodeCompletionContext::CCC_Other,
6782 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006783}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006784
6785void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6786 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006787 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006788 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006789 IdentifierInfo **SelIdents,
6790 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006791 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006792 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006793 if (ExternalSource) {
6794 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6795 I != N; ++I) {
6796 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006797 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006798 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006799
6800 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006801 }
6802 }
6803
6804 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006805 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006806 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6807 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006808
6809 if (ReturnTy)
6810 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006811
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006812 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006813 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6814 MEnd = MethodPool.end();
6815 M != MEnd; ++M) {
6816 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6817 &M->second.second;
6818 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006819 MethList = MethList->Next) {
6820 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6821 NumSelIdents))
6822 continue;
6823
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006824 if (AtParameterName) {
6825 // Suggest parameter names we've seen before.
6826 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6827 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6828 if (Param->getIdentifier()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006829 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregordae68752011-02-01 22:57:45 +00006830 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006831 Param->getIdentifier()->getName()));
6832 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006833 }
6834 }
6835
6836 continue;
6837 }
6838
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006839 Result R(MethList->Method, 0);
6840 R.StartParameter = NumSelIdents;
6841 R.AllParametersAreInformative = false;
6842 R.DeclaringEntity = true;
6843 Results.MaybeAddResult(R, CurContext);
6844 }
6845 }
6846
6847 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006848 HandleCodeCompleteResults(this, CodeCompleter,
6849 CodeCompletionContext::CCC_Other,
6850 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006851}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006852
Douglas Gregorf29c5232010-08-24 22:20:20 +00006853void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006854 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006855 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006856 Results.EnterNewScope();
6857
6858 // #if <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006859 CodeCompletionBuilder Builder(Results.getAllocator());
6860 Builder.AddTypedTextChunk("if");
6861 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6862 Builder.AddPlaceholderChunk("condition");
6863 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006864
6865 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006866 Builder.AddTypedTextChunk("ifdef");
6867 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6868 Builder.AddPlaceholderChunk("macro");
6869 Results.AddResult(Builder.TakeString());
6870
Douglas Gregorf44e8542010-08-24 19:08:16 +00006871 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006872 Builder.AddTypedTextChunk("ifndef");
6873 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6874 Builder.AddPlaceholderChunk("macro");
6875 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006876
6877 if (InConditional) {
6878 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006879 Builder.AddTypedTextChunk("elif");
6880 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6881 Builder.AddPlaceholderChunk("condition");
6882 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006883
6884 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00006885 Builder.AddTypedTextChunk("else");
6886 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006887
6888 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00006889 Builder.AddTypedTextChunk("endif");
6890 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006891 }
6892
6893 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006894 Builder.AddTypedTextChunk("include");
6895 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6896 Builder.AddTextChunk("\"");
6897 Builder.AddPlaceholderChunk("header");
6898 Builder.AddTextChunk("\"");
6899 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006900
6901 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006902 Builder.AddTypedTextChunk("include");
6903 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6904 Builder.AddTextChunk("<");
6905 Builder.AddPlaceholderChunk("header");
6906 Builder.AddTextChunk(">");
6907 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006908
6909 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006910 Builder.AddTypedTextChunk("define");
6911 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6912 Builder.AddPlaceholderChunk("macro");
6913 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006914
6915 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00006916 Builder.AddTypedTextChunk("define");
6917 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6918 Builder.AddPlaceholderChunk("macro");
6919 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6920 Builder.AddPlaceholderChunk("args");
6921 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6922 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006923
6924 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006925 Builder.AddTypedTextChunk("undef");
6926 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6927 Builder.AddPlaceholderChunk("macro");
6928 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006929
6930 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00006931 Builder.AddTypedTextChunk("line");
6932 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6933 Builder.AddPlaceholderChunk("number");
6934 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006935
6936 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00006937 Builder.AddTypedTextChunk("line");
6938 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6939 Builder.AddPlaceholderChunk("number");
6940 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6941 Builder.AddTextChunk("\"");
6942 Builder.AddPlaceholderChunk("filename");
6943 Builder.AddTextChunk("\"");
6944 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006945
6946 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006947 Builder.AddTypedTextChunk("error");
6948 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6949 Builder.AddPlaceholderChunk("message");
6950 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006951
6952 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00006953 Builder.AddTypedTextChunk("pragma");
6954 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6955 Builder.AddPlaceholderChunk("arguments");
6956 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006957
David Blaikie4e4d0842012-03-11 07:00:24 +00006958 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00006959 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006960 Builder.AddTypedTextChunk("import");
6961 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6962 Builder.AddTextChunk("\"");
6963 Builder.AddPlaceholderChunk("header");
6964 Builder.AddTextChunk("\"");
6965 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006966
6967 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006968 Builder.AddTypedTextChunk("import");
6969 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6970 Builder.AddTextChunk("<");
6971 Builder.AddPlaceholderChunk("header");
6972 Builder.AddTextChunk(">");
6973 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006974 }
6975
6976 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006977 Builder.AddTypedTextChunk("include_next");
6978 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6979 Builder.AddTextChunk("\"");
6980 Builder.AddPlaceholderChunk("header");
6981 Builder.AddTextChunk("\"");
6982 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006983
6984 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006985 Builder.AddTypedTextChunk("include_next");
6986 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6987 Builder.AddTextChunk("<");
6988 Builder.AddPlaceholderChunk("header");
6989 Builder.AddTextChunk(">");
6990 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006991
6992 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006993 Builder.AddTypedTextChunk("warning");
6994 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6995 Builder.AddPlaceholderChunk("message");
6996 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006997
6998 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
6999 // completions for them. And __include_macros is a Clang-internal extension
7000 // that we don't want to encourage anyone to use.
7001
7002 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7003 Results.ExitScope();
7004
Douglas Gregorf44e8542010-08-24 19:08:16 +00007005 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00007006 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00007007 Results.data(), Results.size());
7008}
7009
7010void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007011 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007012 S->getFnParent()? Sema::PCC_RecoveryInFunction
7013 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007014}
7015
Douglas Gregorf29c5232010-08-24 22:20:20 +00007016void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007017 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007018 IsDefinition? CodeCompletionContext::CCC_MacroName
7019 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007020 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7021 // Add just the names of macros, not their arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00007022 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007023 Results.EnterNewScope();
7024 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7025 MEnd = PP.macro_end();
7026 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007027 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007028 M->first->getName()));
7029 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007030 }
7031 Results.ExitScope();
7032 } else if (IsDefinition) {
7033 // FIXME: Can we detect when the user just wrote an include guard above?
7034 }
7035
Douglas Gregor52779fb2010-09-23 23:01:17 +00007036 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007037 Results.data(), Results.size());
7038}
7039
Douglas Gregorf29c5232010-08-24 22:20:20 +00007040void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007041 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007042 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007043
7044 if (!CodeCompleter || CodeCompleter->includeMacros())
7045 AddMacroResults(PP, Results);
7046
7047 // defined (<macro>)
7048 Results.EnterNewScope();
Douglas Gregor218937c2011-02-01 19:23:04 +00007049 CodeCompletionBuilder Builder(Results.getAllocator());
7050 Builder.AddTypedTextChunk("defined");
7051 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7052 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7053 Builder.AddPlaceholderChunk("macro");
7054 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7055 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007056 Results.ExitScope();
7057
7058 HandleCodeCompleteResults(this, CodeCompleter,
7059 CodeCompletionContext::CCC_PreprocessorExpression,
7060 Results.data(), Results.size());
7061}
7062
7063void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7064 IdentifierInfo *Macro,
7065 MacroInfo *MacroInfo,
7066 unsigned Argument) {
7067 // FIXME: In the future, we could provide "overload" results, much like we
7068 // do for function calls.
7069
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007070 // Now just ignore this. There will be another code-completion callback
7071 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007072}
7073
Douglas Gregor55817af2010-08-25 17:04:25 +00007074void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007075 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007076 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007077 0, 0);
7078}
7079
Douglas Gregordae68752011-02-01 22:57:45 +00007080void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007081 SmallVectorImpl<CodeCompletionResult> &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007082 ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007083 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7084 CodeCompletionDeclConsumer Consumer(Builder,
7085 Context.getTranslationUnitDecl());
7086 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7087 Consumer);
7088 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007089
7090 if (!CodeCompleter || CodeCompleter->includeMacros())
7091 AddMacroResults(PP, Builder);
7092
7093 Results.clear();
7094 Results.insert(Results.end(),
7095 Builder.data(), Builder.data() + Builder.size());
7096}