blob: b33c1697bf49126869c0a7c079bce5cd9a879870 [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;
2457 return Pattern;
2458 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002459
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002460 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002461 Result.AddTypedTextChunk(Keyword);
2462 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002463 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002464
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002465 if (Kind == RK_Macro) {
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002466 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002467 assert(MI && "Not a macro?");
2468
Douglas Gregordae68752011-02-01 22:57:45 +00002469 Result.AddTypedTextChunk(
2470 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002471
2472 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002473 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002474
2475 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002476 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregore4244702011-07-30 08:17:44 +00002477 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002478
2479 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2480 if (MI->isC99Varargs()) {
2481 --AEnd;
2482
2483 if (A == AEnd) {
2484 Result.AddPlaceholderChunk("...");
2485 }
Douglas Gregore4244702011-07-30 08:17:44 +00002486 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002487
Douglas Gregore4244702011-07-30 08:17:44 +00002488 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002489 if (A != MI->arg_begin())
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002490 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002491
2492 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002493 SmallString<32> Arg = (*A)->getName();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002494 if (MI->isC99Varargs())
2495 Arg += ", ...";
2496 else
2497 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002498 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002499 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002500 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002501
2502 // Non-variadic macros are simple.
2503 Result.AddPlaceholderChunk(
2504 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002505 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002506 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002507 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002508 }
2509
Douglas Gregord8e8a582010-05-25 21:41:55 +00002510 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002511 NamedDecl *ND = Declaration;
2512
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002513 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002514 Result.AddTypedTextChunk(
2515 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002516 Result.AddTextChunk("::");
2517 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002518 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002519
2520 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2521 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2522 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2523 }
2524 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002525
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002526 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002527
Douglas Gregor86d9a522009-09-21 16:56:56 +00002528 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002529 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002530 Ctx, Policy);
2531 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002532 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002533 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002534 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002535 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002536 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002537 }
2538
2539 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002540 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002541 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002542 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002543 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002544
Douglas Gregor86d9a522009-09-21 16:56:56 +00002545 // Figure out which template parameters are deduced (or have default
2546 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002547 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002548 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002549 unsigned LastDeducibleArgument;
2550 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2551 --LastDeducibleArgument) {
2552 if (!Deduced[LastDeducibleArgument - 1]) {
2553 // C++0x: Figure out if the template argument has a default. If so,
2554 // the user doesn't need to type this argument.
2555 // FIXME: We need to abstract template parameters better!
2556 bool HasDefaultArg = false;
2557 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002558 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002559 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2560 HasDefaultArg = TTP->hasDefaultArgument();
2561 else if (NonTypeTemplateParmDecl *NTTP
2562 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2563 HasDefaultArg = NTTP->hasDefaultArgument();
2564 else {
2565 assert(isa<TemplateTemplateParmDecl>(Param));
2566 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002567 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002568 }
2569
2570 if (!HasDefaultArg)
2571 break;
2572 }
2573 }
2574
2575 if (LastDeducibleArgument) {
2576 // Some of the function template arguments cannot be deduced from a
2577 // function call, so we introduce an explicit template argument list
2578 // containing all of the arguments up to the first deducible argument.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002579 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002580 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002581 LastDeducibleArgument);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002582 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002583 }
2584
2585 // Add the function parameters
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002586 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002587 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002588 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002589 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002590 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002591 }
2592
2593 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002594 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002595 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002596 Result.AddTypedTextChunk(
2597 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002598 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002599 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002600 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor218937c2011-02-01 19:23:04 +00002601 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002602 }
2603
Douglas Gregor9630eb62009-11-17 16:44:22 +00002604 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002605 Selector Sel = Method->getSelector();
2606 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002607 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002608 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002609 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002610 }
2611
Douglas Gregor813d8342011-02-18 22:29:55 +00002612 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002613 SelName += ':';
2614 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002615 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002616 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002617 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002618
2619 // If there is only one parameter, and we're past it, add an empty
2620 // typed-text chunk since there is nothing to type.
2621 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002622 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002623 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002624 unsigned Idx = 0;
2625 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2626 PEnd = Method->param_end();
2627 P != PEnd; (void)++P, ++Idx) {
2628 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002629 std::string Keyword;
2630 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002631 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002632 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002633 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002634 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002635 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002636 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002637 else
Douglas Gregordae68752011-02-01 22:57:45 +00002638 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002639 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002640
2641 // If we're before the starting parameter, skip the placeholder.
2642 if (Idx < StartParameter)
2643 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002644
2645 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002646
2647 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002648 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002649 else {
John McCallf85e1932011-06-15 23:02:42 +00002650 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002651 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2652 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002653 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002654 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002655 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002656 }
2657
Douglas Gregore17794f2010-08-31 05:13:43 +00002658 if (Method->isVariadic() && (P + 1) == PEnd)
2659 Arg += ", ...";
2660
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002661 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002662 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002663 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002664 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002665 else
Douglas Gregordae68752011-02-01 22:57:45 +00002666 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002667 }
2668
Douglas Gregor2a17af02009-12-23 00:21:46 +00002669 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002670 if (Method->param_size() == 0) {
2671 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002672 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002673 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002674 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002675 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002676 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002677 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002678
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002679 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002680 }
2681
Douglas Gregor218937c2011-02-01 19:23:04 +00002682 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002683 }
2684
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002685 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002686 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002687 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002688
Douglas Gregordae68752011-02-01 22:57:45 +00002689 Result.AddTypedTextChunk(
2690 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002691 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002692}
2693
Douglas Gregor86d802e2009-09-23 00:34:09 +00002694CodeCompletionString *
2695CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2696 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002697 Sema &S,
Douglas Gregordae68752011-02-01 22:57:45 +00002698 CodeCompletionAllocator &Allocator) const {
Douglas Gregor8987b232011-09-27 23:30:47 +00002699 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002700
Douglas Gregor218937c2011-02-01 19:23:04 +00002701 // FIXME: Set priority, availability appropriately.
2702 CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002703 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002704 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002705 const FunctionProtoType *Proto
2706 = dyn_cast<FunctionProtoType>(getFunctionType());
2707 if (!FDecl && !Proto) {
2708 // Function without a prototype. Just give the return type and a
2709 // highlighted ellipsis.
2710 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002711 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002712 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002713 Result.getAllocator()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002714 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2715 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2716 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002717 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002718 }
2719
2720 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002721 Result.AddTextChunk(
2722 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002723 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002724 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002725 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002726 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002727
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002728 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002729 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2730 for (unsigned I = 0; I != NumParams; ++I) {
2731 if (I)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002732 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002733
2734 std::string ArgString;
2735 QualType ArgType;
2736
2737 if (FDecl) {
2738 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2739 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2740 } else {
2741 ArgType = Proto->getArgType(I);
2742 }
2743
John McCallf85e1932011-06-15 23:02:42 +00002744 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002745
2746 if (I == CurrentArg)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002747 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2748 Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002749 else
Douglas Gregordae68752011-02-01 22:57:45 +00002750 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002751 }
2752
2753 if (Proto && Proto->isVariadic()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002754 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002755 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002756 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002757 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002758 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002759 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002760 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002761
Douglas Gregor218937c2011-02-01 19:23:04 +00002762 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002763}
2764
Chris Lattner5f9e2722011-07-23 10:55:15 +00002765unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002766 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002767 bool PreferredTypeIsPointer) {
2768 unsigned Priority = CCP_Macro;
2769
Douglas Gregorb05496d2010-09-20 21:11:48 +00002770 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2771 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2772 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002773 Priority = CCP_Constant;
2774 if (PreferredTypeIsPointer)
2775 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002776 }
2777 // Treat "YES", "NO", "true", and "false" as constants.
2778 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2779 MacroName.equals("true") || MacroName.equals("false"))
2780 Priority = CCP_Constant;
2781 // Treat "bool" as a type.
2782 else if (MacroName.equals("bool"))
2783 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2784
Douglas Gregor1827e102010-08-16 16:18:59 +00002785
2786 return Priority;
2787}
2788
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002789CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2790 if (!D)
2791 return CXCursor_UnexposedDecl;
2792
2793 switch (D->getKind()) {
2794 case Decl::Enum: return CXCursor_EnumDecl;
2795 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2796 case Decl::Field: return CXCursor_FieldDecl;
2797 case Decl::Function:
2798 return CXCursor_FunctionDecl;
2799 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2800 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002801 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002802
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002803 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002804 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2805 case Decl::ObjCMethod:
2806 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2807 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2808 case Decl::CXXMethod: return CXCursor_CXXMethod;
2809 case Decl::CXXConstructor: return CXCursor_Constructor;
2810 case Decl::CXXDestructor: return CXCursor_Destructor;
2811 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2812 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002813 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002814 case Decl::ParmVar: return CXCursor_ParmDecl;
2815 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002816 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002817 case Decl::Var: return CXCursor_VarDecl;
2818 case Decl::Namespace: return CXCursor_Namespace;
2819 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2820 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2821 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2822 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2823 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2824 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002825 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002826 case Decl::ClassTemplatePartialSpecialization:
2827 return CXCursor_ClassTemplatePartialSpecialization;
2828 case Decl::UsingDirective: return CXCursor_UsingDirective;
2829
2830 case Decl::Using:
2831 case Decl::UnresolvedUsingValue:
2832 case Decl::UnresolvedUsingTypename:
2833 return CXCursor_UsingDeclaration;
2834
Douglas Gregor352697a2011-06-03 23:08:58 +00002835 case Decl::ObjCPropertyImpl:
2836 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2837 case ObjCPropertyImplDecl::Dynamic:
2838 return CXCursor_ObjCDynamicDecl;
2839
2840 case ObjCPropertyImplDecl::Synthesize:
2841 return CXCursor_ObjCSynthesizeDecl;
2842 }
Douglas Gregor352697a2011-06-03 23:08:58 +00002843
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002844 default:
2845 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2846 switch (TD->getTagKind()) {
2847 case TTK_Struct: return CXCursor_StructDecl;
2848 case TTK_Class: return CXCursor_ClassDecl;
2849 case TTK_Union: return CXCursor_UnionDecl;
2850 case TTK_Enum: return CXCursor_EnumDecl;
2851 }
2852 }
2853 }
2854
2855 return CXCursor_UnexposedDecl;
2856}
2857
Douglas Gregor590c7d52010-07-08 20:55:51 +00002858static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2859 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002860 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002861
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002862 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002863
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002864 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2865 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002866 M != MEnd; ++M) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002867 Results.AddResult(Result(M->first,
2868 getMacroUsagePriority(M->first->getName(),
David Blaikie4e4d0842012-03-11 07:00:24 +00002869 PP.getLangOpts(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002870 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002871 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002872
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002873 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002874
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002875}
2876
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002877static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2878 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002879 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002880
2881 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002882
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002883 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2884 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2885 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2886 Results.AddResult(Result("__func__", CCP_Constant));
2887 Results.ExitScope();
2888}
2889
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002890static void HandleCodeCompleteResults(Sema *S,
2891 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002892 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002893 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002894 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002895 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002896 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002897}
2898
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002899static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2900 Sema::ParserCompletionContext PCC) {
2901 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002902 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002903 return CodeCompletionContext::CCC_TopLevel;
2904
John McCallf312b1e2010-08-26 23:41:50 +00002905 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002906 return CodeCompletionContext::CCC_ClassStructUnion;
2907
John McCallf312b1e2010-08-26 23:41:50 +00002908 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002909 return CodeCompletionContext::CCC_ObjCInterface;
2910
John McCallf312b1e2010-08-26 23:41:50 +00002911 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002912 return CodeCompletionContext::CCC_ObjCImplementation;
2913
John McCallf312b1e2010-08-26 23:41:50 +00002914 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002915 return CodeCompletionContext::CCC_ObjCIvarList;
2916
John McCallf312b1e2010-08-26 23:41:50 +00002917 case Sema::PCC_Template:
2918 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002919 if (S.CurContext->isFileContext())
2920 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002921 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002922 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002923 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002924
John McCallf312b1e2010-08-26 23:41:50 +00002925 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002926 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002927
John McCallf312b1e2010-08-26 23:41:50 +00002928 case Sema::PCC_ForInit:
David Blaikie4e4d0842012-03-11 07:00:24 +00002929 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2930 S.getLangOpts().ObjC1)
Douglas Gregora5450a02010-10-18 22:01:46 +00002931 return CodeCompletionContext::CCC_ParenthesizedExpression;
2932 else
2933 return CodeCompletionContext::CCC_Expression;
2934
2935 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002936 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002937 return CodeCompletionContext::CCC_Expression;
2938
John McCallf312b1e2010-08-26 23:41:50 +00002939 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002940 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002941
John McCallf312b1e2010-08-26 23:41:50 +00002942 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002943 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002944
2945 case Sema::PCC_ParenthesizedExpression:
2946 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002947
2948 case Sema::PCC_LocalDeclarationSpecifiers:
2949 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002950 }
David Blaikie7530c032012-01-17 06:56:22 +00002951
2952 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002953}
2954
Douglas Gregorf6961522010-08-27 21:18:54 +00002955/// \brief If we're in a C++ virtual member function, add completion results
2956/// that invoke the functions we override, since it's common to invoke the
2957/// overridden function as well as adding new functionality.
2958///
2959/// \param S The semantic analysis object for which we are generating results.
2960///
2961/// \param InContext This context in which the nested-name-specifier preceding
2962/// the code-completion point
2963static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2964 ResultBuilder &Results) {
2965 // Look through blocks.
2966 DeclContext *CurContext = S.CurContext;
2967 while (isa<BlockDecl>(CurContext))
2968 CurContext = CurContext->getParent();
2969
2970
2971 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2972 if (!Method || !Method->isVirtual())
2973 return;
2974
2975 // We need to have names for all of the parameters, if we're going to
2976 // generate a forwarding call.
2977 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2978 PEnd = Method->param_end();
2979 P != PEnd;
2980 ++P) {
2981 if (!(*P)->getDeclName())
2982 return;
2983 }
2984
Douglas Gregor8987b232011-09-27 23:30:47 +00002985 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00002986 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
2987 MEnd = Method->end_overridden_methods();
2988 M != MEnd; ++M) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002989 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf6961522010-08-27 21:18:54 +00002990 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
2991 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
2992 continue;
2993
2994 // If we need a nested-name-specifier, add one now.
2995 if (!InContext) {
2996 NestedNameSpecifier *NNS
2997 = getRequiredQualification(S.Context, CurContext,
2998 Overridden->getDeclContext());
2999 if (NNS) {
3000 std::string Str;
3001 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00003002 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00003003 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003004 }
3005 } else if (!InContext->Equals(Overridden->getDeclContext()))
3006 continue;
3007
Douglas Gregordae68752011-02-01 22:57:45 +00003008 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003009 Overridden->getNameAsString()));
3010 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00003011 bool FirstParam = true;
3012 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3013 PEnd = Method->param_end();
3014 P != PEnd; ++P) {
3015 if (FirstParam)
3016 FirstParam = false;
3017 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003018 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003019
Douglas Gregordae68752011-02-01 22:57:45 +00003020 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003021 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003022 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003023 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3024 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003025 CCP_SuperCompletion,
3026 CXCursor_CXXMethod));
3027 Results.Ignore(Overridden);
3028 }
3029}
3030
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003031void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3032 ModuleIdPath Path) {
3033 typedef CodeCompletionResult Result;
3034 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3035 CodeCompletionContext::CCC_Other);
3036 Results.EnterNewScope();
3037
3038 CodeCompletionAllocator &Allocator = Results.getAllocator();
3039 CodeCompletionBuilder Builder(Allocator);
3040 typedef CodeCompletionResult Result;
3041 if (Path.empty()) {
3042 // Enumerate all top-level modules.
3043 llvm::SmallVector<Module *, 8> Modules;
3044 PP.getHeaderSearchInfo().collectAllModules(Modules);
3045 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3046 Builder.AddTypedTextChunk(
3047 Builder.getAllocator().CopyString(Modules[I]->Name));
3048 Results.AddResult(Result(Builder.TakeString(),
3049 CCP_Declaration,
3050 CXCursor_NotImplemented,
3051 Modules[I]->isAvailable()
3052 ? CXAvailability_Available
3053 : CXAvailability_NotAvailable));
3054 }
3055 } else {
3056 // Load the named module.
3057 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3058 Module::AllVisible,
3059 /*IsInclusionDirective=*/false);
3060 // Enumerate submodules.
3061 if (Mod) {
3062 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3063 SubEnd = Mod->submodule_end();
3064 Sub != SubEnd; ++Sub) {
3065
3066 Builder.AddTypedTextChunk(
3067 Builder.getAllocator().CopyString((*Sub)->Name));
3068 Results.AddResult(Result(Builder.TakeString(),
3069 CCP_Declaration,
3070 CXCursor_NotImplemented,
3071 (*Sub)->isAvailable()
3072 ? CXAvailability_Available
3073 : CXAvailability_NotAvailable));
3074 }
3075 }
3076 }
3077 Results.ExitScope();
3078 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3079 Results.data(),Results.size());
3080}
3081
Douglas Gregor01dfea02010-01-10 23:08:15 +00003082void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003083 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00003084 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003085 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003086 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003087 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003088
Douglas Gregor01dfea02010-01-10 23:08:15 +00003089 // Determine how to filter results, e.g., so that the names of
3090 // values (functions, enumerators, function templates, etc.) are
3091 // only allowed where we can have an expression.
3092 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003093 case PCC_Namespace:
3094 case PCC_Class:
3095 case PCC_ObjCInterface:
3096 case PCC_ObjCImplementation:
3097 case PCC_ObjCInstanceVariableList:
3098 case PCC_Template:
3099 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003100 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003101 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003102 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3103 break;
3104
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003105 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003106 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003107 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003108 case PCC_ForInit:
3109 case PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00003110 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003111 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3112 else
3113 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003114
David Blaikie4e4d0842012-03-11 07:00:24 +00003115 if (getLangOpts().CPlusPlus)
Douglas Gregorf6961522010-08-27 21:18:54 +00003116 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003117 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003118
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003119 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003120 // Unfiltered
3121 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003122 }
3123
Douglas Gregor3cdee122010-08-26 16:36:48 +00003124 // If we are in a C++ non-static member function, check the qualifiers on
3125 // the member function to filter/prioritize the results list.
3126 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3127 if (CurMethod->isInstance())
3128 Results.setObjectTypeQualifiers(
3129 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3130
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003131 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003132 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3133 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003134
Douglas Gregorbca403c2010-01-13 23:51:12 +00003135 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003136 Results.ExitScope();
3137
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003138 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003139 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003140 case PCC_Expression:
3141 case PCC_Statement:
3142 case PCC_RecoveryInFunction:
3143 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003144 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor72db1082010-08-24 01:11:00 +00003145 break;
3146
3147 case PCC_Namespace:
3148 case PCC_Class:
3149 case PCC_ObjCInterface:
3150 case PCC_ObjCImplementation:
3151 case PCC_ObjCInstanceVariableList:
3152 case PCC_Template:
3153 case PCC_MemberTemplate:
3154 case PCC_ForInit:
3155 case PCC_Condition:
3156 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003157 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003158 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003159 }
3160
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003161 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003162 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003163
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003164 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003165 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003166}
3167
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003168static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3169 ParsedType Receiver,
3170 IdentifierInfo **SelIdents,
3171 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003172 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003173 bool IsSuper,
3174 ResultBuilder &Results);
3175
3176void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3177 bool AllowNonIdentifiers,
3178 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003179 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003180 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003181 AllowNestedNameSpecifiers
3182 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3183 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003184 Results.EnterNewScope();
3185
3186 // Type qualifiers can come after names.
3187 Results.AddResult(Result("const"));
3188 Results.AddResult(Result("volatile"));
David Blaikie4e4d0842012-03-11 07:00:24 +00003189 if (getLangOpts().C99)
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003190 Results.AddResult(Result("restrict"));
3191
David Blaikie4e4d0842012-03-11 07:00:24 +00003192 if (getLangOpts().CPlusPlus) {
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003193 if (AllowNonIdentifiers) {
3194 Results.AddResult(Result("operator"));
3195 }
3196
3197 // Add nested-name-specifiers.
3198 if (AllowNestedNameSpecifiers) {
3199 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003200 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003201 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3202 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3203 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003204 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003205 }
3206 }
3207 Results.ExitScope();
3208
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003209 // If we're in a context where we might have an expression (rather than a
3210 // declaration), and what we've seen so far is an Objective-C type that could
3211 // be a receiver of a class message, this may be a class message send with
3212 // the initial opening bracket '[' missing. Add appropriate completions.
3213 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3214 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3215 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3216 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3217 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3218 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3219 DS.getTypeQualifiers() == 0 &&
3220 S &&
3221 (S->getFlags() & Scope::DeclScope) != 0 &&
3222 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3223 Scope::FunctionPrototypeScope |
3224 Scope::AtCatchScope)) == 0) {
3225 ParsedType T = DS.getRepAsType();
3226 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003227 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003228 }
3229
Douglas Gregor4497dd42010-08-24 04:59:56 +00003230 // Note that we intentionally suppress macro results here, since we do not
3231 // encourage using macros to produce the names of entities.
3232
Douglas Gregor52779fb2010-09-23 23:01:17 +00003233 HandleCodeCompleteResults(this, CodeCompleter,
3234 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003235 Results.data(), Results.size());
3236}
3237
Douglas Gregorfb629412010-08-23 21:17:50 +00003238struct Sema::CodeCompleteExpressionData {
3239 CodeCompleteExpressionData(QualType PreferredType = QualType())
3240 : PreferredType(PreferredType), IntegralConstantExpression(false),
3241 ObjCCollection(false) { }
3242
3243 QualType PreferredType;
3244 bool IntegralConstantExpression;
3245 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003246 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003247};
3248
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003249/// \brief Perform code-completion in an expression context when we know what
3250/// type we're looking for.
Douglas Gregorf9578432010-07-28 21:50:18 +00003251///
3252/// \param IntegralConstantExpression Only permit integral constant
3253/// expressions.
Douglas Gregorfb629412010-08-23 21:17:50 +00003254void Sema::CodeCompleteExpression(Scope *S,
3255 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00003256 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003257 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3258 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003259 if (Data.ObjCCollection)
3260 Results.setFilter(&ResultBuilder::IsObjCCollection);
3261 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003262 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikie4e4d0842012-03-11 07:00:24 +00003263 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003264 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3265 else
3266 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003267
3268 if (!Data.PreferredType.isNull())
3269 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3270
3271 // Ignore any declarations that we were told that we don't care about.
3272 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3273 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003274
3275 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003276 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3277 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003278
3279 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003280 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003281 Results.ExitScope();
3282
Douglas Gregor590c7d52010-07-08 20:55:51 +00003283 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003284 if (!Data.PreferredType.isNull())
3285 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3286 || Data.PreferredType->isMemberPointerType()
3287 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003288
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003289 if (S->getFnParent() &&
3290 !Data.ObjCCollection &&
3291 !Data.IntegralConstantExpression)
David Blaikie4e4d0842012-03-11 07:00:24 +00003292 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003293
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003294 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003295 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003296 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003297 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3298 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003299 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003300}
3301
Douglas Gregorac5fd842010-09-18 01:28:11 +00003302void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3303 if (E.isInvalid())
3304 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikie4e4d0842012-03-11 07:00:24 +00003305 else if (getLangOpts().ObjC1)
Douglas Gregorac5fd842010-09-18 01:28:11 +00003306 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003307}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003308
Douglas Gregor73449212010-12-09 23:01:55 +00003309/// \brief The set of properties that have already been added, referenced by
3310/// property name.
3311typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3312
Douglas Gregor95ac6552009-11-18 01:29:26 +00003313static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003314 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003315 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003316 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003317 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003318 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003319 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003320
3321 // Add properties in this container.
3322 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3323 PEnd = Container->prop_end();
3324 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003325 ++P) {
3326 if (AddedProperties.insert(P->getIdentifier()))
3327 Results.MaybeAddResult(Result(*P, 0), CurContext);
3328 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003329
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003330 // Add nullary methods
3331 if (AllowNullaryMethods) {
3332 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003333 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003334 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3335 MEnd = Container->meth_end();
3336 M != MEnd; ++M) {
3337 if (M->getSelector().isUnarySelector())
3338 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3339 if (AddedProperties.insert(Name)) {
3340 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor8987b232011-09-27 23:30:47 +00003341 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003342 Builder.AddTypedTextChunk(
3343 Results.getAllocator().CopyString(Name->getName()));
3344
3345 CXAvailabilityKind Availability = CXAvailability_Available;
3346 switch (M->getAvailability()) {
3347 case AR_Available:
3348 case AR_NotYetIntroduced:
3349 Availability = CXAvailability_Available;
3350 break;
3351
3352 case AR_Deprecated:
3353 Availability = CXAvailability_Deprecated;
3354 break;
3355
3356 case AR_Unavailable:
3357 Availability = CXAvailability_NotAvailable;
3358 break;
3359 }
3360
3361 Results.MaybeAddResult(Result(Builder.TakeString(),
3362 CCP_MemberDeclaration + CCD_MethodAsProperty,
3363 M->isInstanceMethod()
3364 ? CXCursor_ObjCInstanceMethodDecl
3365 : CXCursor_ObjCClassMethodDecl,
3366 Availability),
3367 CurContext);
3368 }
3369 }
3370 }
3371
3372
Douglas Gregor95ac6552009-11-18 01:29:26 +00003373 // Add properties in referenced protocols.
3374 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3375 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3376 PEnd = Protocol->protocol_end();
3377 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003378 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3379 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003380 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003381 if (AllowCategories) {
3382 // Look through categories.
3383 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3384 Category; Category = Category->getNextClassCategory())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003385 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3386 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003387 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003388
3389 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003390 for (ObjCInterfaceDecl::all_protocol_iterator
3391 I = IFace->all_referenced_protocol_begin(),
3392 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003393 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3394 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003395
3396 // Look in the superclass.
3397 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003398 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3399 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003400 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003401 } else if (const ObjCCategoryDecl *Category
3402 = dyn_cast<ObjCCategoryDecl>(Container)) {
3403 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003404 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3405 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003406 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003407 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3408 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003409 }
3410}
3411
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003412void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003413 SourceLocation OpLoc,
3414 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003415 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003416 return;
3417
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003418 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3419 if (ConvertedBase.isInvalid())
3420 return;
3421 Base = ConvertedBase.get();
3422
John McCall0a2c5e22010-08-25 06:19:51 +00003423 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003424
Douglas Gregor81b747b2009-09-17 21:32:03 +00003425 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003426
3427 if (IsArrow) {
3428 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3429 BaseType = Ptr->getPointeeType();
3430 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003431 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003432 else
3433 return;
3434 }
3435
Douglas Gregor3da626b2011-07-07 16:03:39 +00003436 enum CodeCompletionContext::Kind contextKind;
3437
3438 if (IsArrow) {
3439 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3440 }
3441 else {
3442 if (BaseType->isObjCObjectPointerType() ||
3443 BaseType->isObjCObjectOrInterfaceType()) {
3444 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3445 }
3446 else {
3447 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3448 }
3449 }
3450
Douglas Gregor218937c2011-02-01 19:23:04 +00003451 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003452 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003453 BaseType),
3454 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003455 Results.EnterNewScope();
3456 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003457 // Indicate that we are performing a member access, and the cv-qualifiers
3458 // for the base object type.
3459 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3460
Douglas Gregor95ac6552009-11-18 01:29:26 +00003461 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003462 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003463 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003464 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3465 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003466
David Blaikie4e4d0842012-03-11 07:00:24 +00003467 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003468 if (!Results.empty()) {
3469 // The "template" keyword can follow "->" or "." in the grammar.
3470 // However, we only want to suggest the template keyword if something
3471 // is dependent.
3472 bool IsDependent = BaseType->isDependentType();
3473 if (!IsDependent) {
3474 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3475 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3476 IsDependent = Ctx->isDependentContext();
3477 break;
3478 }
3479 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003480
Douglas Gregor95ac6552009-11-18 01:29:26 +00003481 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003482 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003483 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003484 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003485 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3486 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003487 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003488
3489 // Add property results based on our interface.
3490 const ObjCObjectPointerType *ObjCPtr
3491 = BaseType->getAsObjCInterfacePointerType();
3492 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003493 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3494 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003495 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003496
3497 // Add properties from the protocols in a qualified interface.
3498 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3499 E = ObjCPtr->qual_end();
3500 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003501 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3502 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003503 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003504 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003505 // Objective-C instance variable access.
3506 ObjCInterfaceDecl *Class = 0;
3507 if (const ObjCObjectPointerType *ObjCPtr
3508 = BaseType->getAs<ObjCObjectPointerType>())
3509 Class = ObjCPtr->getInterfaceDecl();
3510 else
John McCallc12c5bb2010-05-15 11:32:37 +00003511 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003512
3513 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003514 if (Class) {
3515 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3516 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003517 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3518 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003519 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003520 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003521
3522 // FIXME: How do we cope with isa?
3523
3524 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003525
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003526 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003527 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003528 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003529 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003530}
3531
Douglas Gregor374929f2009-09-18 15:37:17 +00003532void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3533 if (!CodeCompleter)
3534 return;
3535
John McCall0a2c5e22010-08-25 06:19:51 +00003536 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003537 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003538 enum CodeCompletionContext::Kind ContextKind
3539 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003540 switch ((DeclSpec::TST)TagSpec) {
3541 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003542 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003543 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003544 break;
3545
3546 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003547 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003548 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003549 break;
3550
3551 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003552 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003553 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003554 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003555 break;
3556
3557 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003558 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003559 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003560
Douglas Gregor218937c2011-02-01 19:23:04 +00003561 ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003562 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003563
3564 // First pass: look for tags.
3565 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003566 LookupVisibleDecls(S, LookupTagName, Consumer,
3567 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003568
Douglas Gregor8071e422010-08-15 06:18:01 +00003569 if (CodeCompleter->includeGlobals()) {
3570 // Second pass: look for nested name specifiers.
3571 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3572 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3573 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003574
Douglas Gregor52779fb2010-09-23 23:01:17 +00003575 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003576 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003577}
3578
Douglas Gregor1a480c42010-08-27 17:35:51 +00003579void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003580 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3581 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003582 Results.EnterNewScope();
3583 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3584 Results.AddResult("const");
3585 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3586 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003587 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003588 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3589 Results.AddResult("restrict");
3590 Results.ExitScope();
3591 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003592 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003593 Results.data(), Results.size());
3594}
3595
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003596void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003597 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003598 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003599
John McCall781472f2010-08-25 08:40:02 +00003600 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003601 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3602 if (!type->isEnumeralType()) {
3603 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003604 Data.IntegralConstantExpression = true;
3605 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003606 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003607 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003608
3609 // Code-complete the cases of a switch statement over an enumeration type
3610 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003611 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003612
3613 // Determine which enumerators we have already seen in the switch statement.
3614 // FIXME: Ideally, we would also be able to look *past* the code-completion
3615 // token, in case we are code-completing in the middle of the switch and not
3616 // at the end. However, we aren't able to do so at the moment.
3617 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003618 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003619 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3620 SC = SC->getNextSwitchCase()) {
3621 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3622 if (!Case)
3623 continue;
3624
3625 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3626 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3627 if (EnumConstantDecl *Enumerator
3628 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3629 // We look into the AST of the case statement to determine which
3630 // enumerator was named. Alternatively, we could compute the value of
3631 // the integral constant expression, then compare it against the
3632 // values of each enumerator. However, value-based approach would not
3633 // work as well with C++ templates where enumerators declared within a
3634 // template are type- and value-dependent.
3635 EnumeratorsSeen.insert(Enumerator);
3636
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003637 // If this is a qualified-id, keep track of the nested-name-specifier
3638 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003639 //
3640 // switch (TagD.getKind()) {
3641 // case TagDecl::TK_enum:
3642 // break;
3643 // case XXX
3644 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003645 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003646 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3647 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003648 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003649 }
3650 }
3651
David Blaikie4e4d0842012-03-11 07:00:24 +00003652 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003653 // If there are no prior enumerators in C++, check whether we have to
3654 // qualify the names of the enumerators that we suggest, because they
3655 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003656 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003657 }
3658
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003659 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003660 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3661 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003662 Results.EnterNewScope();
3663 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3664 EEnd = Enum->enumerator_end();
3665 E != EEnd; ++E) {
3666 if (EnumeratorsSeen.count(*E))
3667 continue;
3668
Douglas Gregor5c722c702011-02-18 23:30:37 +00003669 CodeCompletionResult R(*E, Qualifier);
3670 R.Priority = CCP_EnumInCase;
3671 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003672 }
3673 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003674
Douglas Gregor3da626b2011-07-07 16:03:39 +00003675 //We need to make sure we're setting the right context,
3676 //so only say we include macros if the code completer says we do
3677 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3678 if (CodeCompleter->includeMacros()) {
Douglas Gregorbca403c2010-01-13 23:51:12 +00003679 AddMacroResults(PP, Results);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003680 kind = CodeCompletionContext::CCC_OtherWithMacros;
3681 }
3682
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003683 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003684 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003685 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003686}
3687
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003688namespace {
3689 struct IsBetterOverloadCandidate {
3690 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003691 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003692
3693 public:
John McCall5769d612010-02-08 23:07:23 +00003694 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3695 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003696
3697 bool
3698 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003699 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003700 }
3701 };
3702}
3703
Ahmed Charles13a140c2012-02-25 11:00:22 +00003704static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3705 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003706 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003707
3708 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003709 if (!Args[I])
3710 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003711
Douglas Gregord28dcd72010-05-30 06:10:08 +00003712 return false;
3713}
3714
Richard Trieuf81e5a92011-09-09 02:00:50 +00003715void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charles13a140c2012-02-25 11:00:22 +00003716 llvm::ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003717 if (!CodeCompleter)
3718 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003719
3720 // When we're code-completing for a call, we fall back to ordinary
3721 // name code-completion whenever we can't produce specific
3722 // results. We may want to revisit this strategy in the future,
3723 // e.g., by merging the two kinds of results.
3724
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003725 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003726
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003727 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003728 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3729 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003730 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003731 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003732 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003733
John McCall3b4294e2009-12-16 12:17:52 +00003734 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003735 SourceLocation Loc = Fn->getExprLoc();
3736 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003737
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003738 // FIXME: What if we're calling something that isn't a function declaration?
3739 // FIXME: What if we're calling a pseudo-destructor?
3740 // FIXME: What if we're calling a member function?
3741
Douglas Gregorc0265402010-01-21 15:46:19 +00003742 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003743 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003744
John McCall3b4294e2009-12-16 12:17:52 +00003745 Expr *NakedFn = Fn->IgnoreParenCasts();
3746 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003747 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003748 /*PartialOverloading=*/ true);
3749 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3750 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003751 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003752 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003753 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003754 Results.push_back(ResultCandidate(FDecl));
3755 else
John McCall86820f52010-01-26 01:37:31 +00003756 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003757 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3758 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003759 }
John McCall3b4294e2009-12-16 12:17:52 +00003760 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003761
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003762 QualType ParamType;
3763
Douglas Gregorc0265402010-01-21 15:46:19 +00003764 if (!CandidateSet.empty()) {
3765 // Sort the overload candidate set by placing the best overloads first.
3766 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003767 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003768
Douglas Gregorc0265402010-01-21 15:46:19 +00003769 // Add the remaining viable overload candidates as code-completion reslults.
3770 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3771 CandEnd = CandidateSet.end();
3772 Cand != CandEnd; ++Cand) {
3773 if (Cand->Viable)
3774 Results.push_back(ResultCandidate(Cand->Function));
3775 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003776
3777 // From the viable candidates, try to determine the type of this parameter.
3778 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3779 if (const FunctionType *FType = Results[I].getFunctionType())
3780 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003781 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003782 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003783 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003784 else if (!Context.hasSameUnqualifiedType(
3785 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003786 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003787 ParamType = QualType();
3788 break;
3789 }
3790 }
3791 }
3792 } else {
3793 // Try to determine the parameter type from the type of the expression
3794 // being called.
3795 QualType FunctionType = Fn->getType();
3796 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3797 FunctionType = Ptr->getPointeeType();
3798 else if (const BlockPointerType *BlockPtr
3799 = FunctionType->getAs<BlockPointerType>())
3800 FunctionType = BlockPtr->getPointeeType();
3801 else if (const MemberPointerType *MemPtr
3802 = FunctionType->getAs<MemberPointerType>())
3803 FunctionType = MemPtr->getPointeeType();
3804
3805 if (const FunctionProtoType *Proto
3806 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003807 if (Args.size() < Proto->getNumArgs())
3808 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003809 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003810 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003811
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003812 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003813 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003814 else
3815 CodeCompleteExpression(S, ParamType);
3816
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003817 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003818 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003819 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003820}
3821
John McCalld226f652010-08-21 09:40:31 +00003822void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3823 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003824 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003825 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003826 return;
3827 }
3828
3829 CodeCompleteExpression(S, VD->getType());
3830}
3831
3832void Sema::CodeCompleteReturn(Scope *S) {
3833 QualType ResultType;
3834 if (isa<BlockDecl>(CurContext)) {
3835 if (BlockScopeInfo *BSI = getCurBlock())
3836 ResultType = BSI->ReturnType;
3837 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3838 ResultType = Function->getResultType();
3839 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3840 ResultType = Method->getResultType();
3841
3842 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003843 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003844 else
3845 CodeCompleteExpression(S, ResultType);
3846}
3847
Douglas Gregord2d8be62011-07-30 08:36:53 +00003848void Sema::CodeCompleteAfterIf(Scope *S) {
3849 typedef CodeCompletionResult Result;
3850 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3851 mapCodeCompletionContext(*this, PCC_Statement));
3852 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3853 Results.EnterNewScope();
3854
3855 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3856 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3857 CodeCompleter->includeGlobals());
3858
3859 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3860
3861 // "else" block
3862 CodeCompletionBuilder Builder(Results.getAllocator());
3863 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00003864 if (Results.includeCodePatterns()) {
3865 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3866 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3867 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3868 Builder.AddPlaceholderChunk("statements");
3869 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3870 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3871 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003872 Results.AddResult(Builder.TakeString());
3873
3874 // "else if" block
3875 Builder.AddTypedTextChunk("else");
3876 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3877 Builder.AddTextChunk("if");
3878 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3879 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00003880 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00003881 Builder.AddPlaceholderChunk("condition");
3882 else
3883 Builder.AddPlaceholderChunk("expression");
3884 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00003885 if (Results.includeCodePatterns()) {
3886 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3887 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3888 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3889 Builder.AddPlaceholderChunk("statements");
3890 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3891 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3892 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003893 Results.AddResult(Builder.TakeString());
3894
3895 Results.ExitScope();
3896
3897 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003898 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003899
3900 if (CodeCompleter->includeMacros())
3901 AddMacroResults(PP, Results);
3902
3903 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3904 Results.data(),Results.size());
3905}
3906
Richard Trieuf81e5a92011-09-09 02:00:50 +00003907void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003908 if (LHS)
3909 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3910 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003911 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003912}
3913
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003914void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003915 bool EnteringContext) {
3916 if (!SS.getScopeRep() || !CodeCompleter)
3917 return;
3918
Douglas Gregor86d9a522009-09-21 16:56:56 +00003919 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3920 if (!Ctx)
3921 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003922
3923 // Try to instantiate any non-dependent declaration contexts before
3924 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003925 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003926 return;
3927
Douglas Gregor218937c2011-02-01 19:23:04 +00003928 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3929 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003930 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003931
Douglas Gregor86d9a522009-09-21 16:56:56 +00003932 // The "template" keyword can follow "::" in the grammar, but only
3933 // put it into the grammar if the nested-name-specifier is dependent.
3934 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3935 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003936 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003937
3938 // Add calls to overridden virtual functions, if there are any.
3939 //
3940 // FIXME: This isn't wonderful, because we don't know whether we're actually
3941 // in a context that permits expressions. This is a general issue with
3942 // qualified-id completions.
3943 if (!EnteringContext)
3944 MaybeAddOverrideCalls(*this, Ctx, Results);
3945 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003946
Douglas Gregorf6961522010-08-27 21:18:54 +00003947 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3948 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3949
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003950 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00003951 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003952 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003953}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003954
3955void Sema::CodeCompleteUsing(Scope *S) {
3956 if (!CodeCompleter)
3957 return;
3958
Douglas Gregor218937c2011-02-01 19:23:04 +00003959 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003960 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3961 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003962 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003963
3964 // If we aren't in class scope, we could see the "namespace" keyword.
3965 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00003966 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003967
3968 // After "using", we can see anything that would start a
3969 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003970 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003971 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3972 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003973 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003974
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003975 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003976 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003977 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003978}
3979
3980void Sema::CodeCompleteUsingDirective(Scope *S) {
3981 if (!CodeCompleter)
3982 return;
3983
Douglas Gregor86d9a522009-09-21 16:56:56 +00003984 // After "using namespace", we expect to see a namespace name or namespace
3985 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003986 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3987 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003988 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003989 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003990 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003991 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3992 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003993 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003994 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003995 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003996 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003997}
3998
3999void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4000 if (!CodeCompleter)
4001 return;
4002
Douglas Gregor86d9a522009-09-21 16:56:56 +00004003 DeclContext *Ctx = (DeclContext *)S->getEntity();
4004 if (!S->getParent())
4005 Ctx = Context.getTranslationUnitDecl();
4006
Douglas Gregor52779fb2010-09-23 23:01:17 +00004007 bool SuppressedGlobalResults
4008 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4009
Douglas Gregor218937c2011-02-01 19:23:04 +00004010 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004011 SuppressedGlobalResults
4012 ? CodeCompletionContext::CCC_Namespace
4013 : CodeCompletionContext::CCC_Other,
4014 &ResultBuilder::IsNamespace);
4015
4016 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004017 // We only want to see those namespaces that have already been defined
4018 // within this scope, because its likely that the user is creating an
4019 // extended namespace declaration. Keep track of the most recent
4020 // definition of each namespace.
4021 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4022 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4023 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4024 NS != NSEnd; ++NS)
4025 OrigToLatest[NS->getOriginalNamespace()] = *NS;
4026
4027 // Add the most recent definition (or extended definition) of each
4028 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004029 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004030 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
4031 NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
4032 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004033 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004034 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004035 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004036 }
4037
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004038 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004039 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004040 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004041}
4042
4043void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4044 if (!CodeCompleter)
4045 return;
4046
Douglas Gregor86d9a522009-09-21 16:56:56 +00004047 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004048 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4049 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004050 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004051 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004052 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4053 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004054 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004055 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004056 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004057}
4058
Douglas Gregored8d3222009-09-18 20:05:18 +00004059void Sema::CodeCompleteOperatorName(Scope *S) {
4060 if (!CodeCompleter)
4061 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004062
John McCall0a2c5e22010-08-25 06:19:51 +00004063 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004064 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4065 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004066 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004067 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004068
Douglas Gregor86d9a522009-09-21 16:56:56 +00004069 // Add the names of overloadable operators.
4070#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4071 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004072 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004073#include "clang/Basic/OperatorKinds.def"
4074
4075 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004076 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004077 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004078 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4079 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004080
4081 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004082 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004083 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004084
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004085 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004086 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004087 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004088}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004089
Douglas Gregor0133f522010-08-28 00:00:50 +00004090void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004091 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004092 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004093 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004094 CXXConstructorDecl *Constructor
4095 = static_cast<CXXConstructorDecl *>(ConstructorD);
4096 if (!Constructor)
4097 return;
4098
Douglas Gregor218937c2011-02-01 19:23:04 +00004099 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004100 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004101 Results.EnterNewScope();
4102
4103 // Fill in any already-initialized fields or base classes.
4104 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4105 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4106 for (unsigned I = 0; I != NumInitializers; ++I) {
4107 if (Initializers[I]->isBaseInitializer())
4108 InitializedBases.insert(
4109 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4110 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004111 InitializedFields.insert(cast<FieldDecl>(
4112 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004113 }
4114
4115 // Add completions for base classes.
Douglas Gregor218937c2011-02-01 19:23:04 +00004116 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004117 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004118 CXXRecordDecl *ClassDecl = Constructor->getParent();
4119 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4120 BaseEnd = ClassDecl->bases_end();
4121 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004122 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4123 SawLastInitializer
4124 = NumInitializers > 0 &&
4125 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4126 Context.hasSameUnqualifiedType(Base->getType(),
4127 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004128 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004129 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004130
Douglas Gregor218937c2011-02-01 19:23:04 +00004131 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004132 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004133 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004134 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4135 Builder.AddPlaceholderChunk("args");
4136 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4137 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004138 SawLastInitializer? CCP_NextInitializer
4139 : CCP_MemberDeclaration));
4140 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004141 }
4142
4143 // Add completions for virtual base classes.
4144 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4145 BaseEnd = ClassDecl->vbases_end();
4146 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004147 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4148 SawLastInitializer
4149 = NumInitializers > 0 &&
4150 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4151 Context.hasSameUnqualifiedType(Base->getType(),
4152 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004153 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004154 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004155
Douglas Gregor218937c2011-02-01 19:23:04 +00004156 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004157 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004158 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004159 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4160 Builder.AddPlaceholderChunk("args");
4161 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4162 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004163 SawLastInitializer? CCP_NextInitializer
4164 : CCP_MemberDeclaration));
4165 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004166 }
4167
4168 // Add completions for members.
4169 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4170 FieldEnd = ClassDecl->field_end();
4171 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004172 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4173 SawLastInitializer
4174 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004175 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
4176 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004177 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004178 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004179
4180 if (!Field->getDeclName())
4181 continue;
4182
Douglas Gregordae68752011-02-01 22:57:45 +00004183 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004184 Field->getIdentifier()->getName()));
4185 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4186 Builder.AddPlaceholderChunk("args");
4187 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4188 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004189 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004190 : CCP_MemberDeclaration,
4191 CXCursor_MemberRef));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004192 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004193 }
4194 Results.ExitScope();
4195
Douglas Gregor52779fb2010-09-23 23:01:17 +00004196 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004197 Results.data(), Results.size());
4198}
4199
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004200/// \brief Determine whether this scope denotes a namespace.
4201static bool isNamespaceScope(Scope *S) {
4202 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4203 if (!DC)
4204 return false;
4205
4206 return DC->isFileContext();
4207}
4208
4209void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4210 bool AfterAmpersand) {
4211 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4212 CodeCompletionContext::CCC_Other);
4213 Results.EnterNewScope();
4214
4215 // Note what has already been captured.
4216 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4217 bool IncludedThis = false;
4218 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4219 CEnd = Intro.Captures.end();
4220 C != CEnd; ++C) {
4221 if (C->Kind == LCK_This) {
4222 IncludedThis = true;
4223 continue;
4224 }
4225
4226 Known.insert(C->Id);
4227 }
4228
4229 // Look for other capturable variables.
4230 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4231 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4232 D != DEnd; ++D) {
4233 VarDecl *Var = dyn_cast<VarDecl>(*D);
4234 if (!Var ||
4235 !Var->hasLocalStorage() ||
4236 Var->hasAttr<BlocksAttr>())
4237 continue;
4238
4239 if (Known.insert(Var->getIdentifier()))
4240 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4241 }
4242 }
4243
4244 // Add 'this', if it would be valid.
4245 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4246 addThisCompletion(*this, Results);
4247
4248 Results.ExitScope();
4249
4250 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4251 Results.data(), Results.size());
4252}
4253
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004254// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
4255// true or false.
4256#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorbca403c2010-01-13 23:51:12 +00004257static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004258 ResultBuilder &Results,
4259 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004260 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004261 // Since we have an implementation, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004262 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004263
Douglas Gregor218937c2011-02-01 19:23:04 +00004264 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004265 if (LangOpts.ObjC2) {
4266 // @dynamic
Douglas Gregor218937c2011-02-01 19:23:04 +00004267 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
4268 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4269 Builder.AddPlaceholderChunk("property");
4270 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004271
4272 // @synthesize
Douglas Gregor218937c2011-02-01 19:23:04 +00004273 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
4274 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4275 Builder.AddPlaceholderChunk("property");
4276 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004277 }
4278}
4279
Douglas Gregorbca403c2010-01-13 23:51:12 +00004280static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004281 ResultBuilder &Results,
4282 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004283 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004284
4285 // Since we have an interface or protocol, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004286 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004287
4288 if (LangOpts.ObjC2) {
4289 // @property
Douglas Gregora4477812010-01-14 16:01:26 +00004290 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004291
4292 // @required
Douglas Gregora4477812010-01-14 16:01:26 +00004293 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004294
4295 // @optional
Douglas Gregora4477812010-01-14 16:01:26 +00004296 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004297 }
4298}
4299
Douglas Gregorbca403c2010-01-13 23:51:12 +00004300static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004301 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004302 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004303
4304 // @class name ;
Douglas Gregor218937c2011-02-01 19:23:04 +00004305 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
4306 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4307 Builder.AddPlaceholderChunk("name");
4308 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004309
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004310 if (Results.includeCodePatterns()) {
4311 // @interface name
4312 // FIXME: Could introduce the whole pattern, including superclasses and
4313 // such.
Douglas Gregor218937c2011-02-01 19:23:04 +00004314 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
4315 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4316 Builder.AddPlaceholderChunk("class");
4317 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004318
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004319 // @protocol name
Douglas Gregor218937c2011-02-01 19:23:04 +00004320 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4321 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4322 Builder.AddPlaceholderChunk("protocol");
4323 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004324
4325 // @implementation name
Douglas Gregor218937c2011-02-01 19:23:04 +00004326 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
4327 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4328 Builder.AddPlaceholderChunk("class");
4329 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004330 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004331
4332 // @compatibility_alias name
Douglas Gregor218937c2011-02-01 19:23:04 +00004333 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
4334 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4335 Builder.AddPlaceholderChunk("alias");
4336 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4337 Builder.AddPlaceholderChunk("class");
4338 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004339}
4340
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004341void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004342 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004343 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4344 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004345 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004346 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004347 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004348 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004349 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004350 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004351 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004352 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004353 HandleCodeCompleteResults(this, CodeCompleter,
4354 CodeCompletionContext::CCC_Other,
4355 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004356}
4357
Douglas Gregorbca403c2010-01-13 23:51:12 +00004358static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004359 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004360 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004361
4362 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004363 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004364 if (Results.getSema().getLangOpts().CPlusPlus ||
4365 Results.getSema().getLangOpts().ConstStrings)
Douglas Gregor8ca72082011-10-18 21:20:17 +00004366 EncodeType = " const char[]";
4367 Builder.AddResultTypeChunk(EncodeType);
Douglas Gregor218937c2011-02-01 19:23:04 +00004368 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
4369 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4370 Builder.AddPlaceholderChunk("type-name");
4371 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4372 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004373
4374 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004375 Builder.AddResultTypeChunk("Protocol *");
Douglas Gregor218937c2011-02-01 19:23:04 +00004376 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4377 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4378 Builder.AddPlaceholderChunk("protocol-name");
4379 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4380 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004381
4382 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004383 Builder.AddResultTypeChunk("SEL");
Douglas Gregor218937c2011-02-01 19:23:04 +00004384 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
4385 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4386 Builder.AddPlaceholderChunk("selector");
4387 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4388 Results.AddResult(Result(Builder.TakeString()));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004389
4390 // @[ objects, ... ]
4391 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,[));
4392 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4393 Builder.AddPlaceholderChunk("objects, ...");
4394 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4395 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4396 Results.AddResult(Result(Builder.TakeString()));
4397
4398 // @{ key : object, ... }
4399 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,{));
4400 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4401 Builder.AddPlaceholderChunk("key");
4402 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4403 Builder.AddChunk(CodeCompletionString::CK_Colon);
4404 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4405 Builder.AddPlaceholderChunk("object, ...");
4406 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4407 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4408 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004409}
4410
Douglas Gregorbca403c2010-01-13 23:51:12 +00004411static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004412 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004413 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004414
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004415 if (Results.includeCodePatterns()) {
4416 // @try { statements } @catch ( declaration ) { statements } @finally
4417 // { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004418 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
4419 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4420 Builder.AddPlaceholderChunk("statements");
4421 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4422 Builder.AddTextChunk("@catch");
4423 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4424 Builder.AddPlaceholderChunk("parameter");
4425 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4426 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4427 Builder.AddPlaceholderChunk("statements");
4428 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4429 Builder.AddTextChunk("@finally");
4430 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4431 Builder.AddPlaceholderChunk("statements");
4432 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4433 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004434 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004435
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004436 // @throw
Douglas Gregor218937c2011-02-01 19:23:04 +00004437 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
4438 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4439 Builder.AddPlaceholderChunk("expression");
4440 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004441
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004442 if (Results.includeCodePatterns()) {
4443 // @synchronized ( expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004444 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
4445 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4446 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4447 Builder.AddPlaceholderChunk("expression");
4448 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4449 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4450 Builder.AddPlaceholderChunk("statements");
4451 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4452 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004453 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004454}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004455
Douglas Gregorbca403c2010-01-13 23:51:12 +00004456static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004457 ResultBuilder &Results,
4458 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004459 typedef CodeCompletionResult Result;
Douglas Gregora4477812010-01-14 16:01:26 +00004460 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
4461 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
4462 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004463 if (LangOpts.ObjC2)
Douglas Gregora4477812010-01-14 16:01:26 +00004464 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004465}
4466
4467void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004468 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4469 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004470 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004471 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004472 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004473 HandleCodeCompleteResults(this, CodeCompleter,
4474 CodeCompletionContext::CCC_Other,
4475 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004476}
4477
4478void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004479 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4480 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004481 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004482 AddObjCStatementResults(Results, false);
4483 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004484 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004485 HandleCodeCompleteResults(this, CodeCompleter,
4486 CodeCompletionContext::CCC_Other,
4487 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004488}
4489
4490void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004491 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4492 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004493 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004494 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004495 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004496 HandleCodeCompleteResults(this, CodeCompleter,
4497 CodeCompletionContext::CCC_Other,
4498 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004499}
4500
Douglas Gregor988358f2009-11-19 00:14:45 +00004501/// \brief Determine whether the addition of the given flag to an Objective-C
4502/// property's attributes will cause a conflict.
4503static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4504 // Check if we've already added this flag.
4505 if (Attributes & NewFlag)
4506 return true;
4507
4508 Attributes |= NewFlag;
4509
4510 // Check for collisions with "readonly".
4511 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4512 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4513 ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004514 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004515 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004516 ObjCDeclSpec::DQ_PR_retain |
4517 ObjCDeclSpec::DQ_PR_strong)))
Douglas Gregor988358f2009-11-19 00:14:45 +00004518 return true;
4519
John McCallf85e1932011-06-15 23:02:42 +00004520 // Check for more than one of { assign, copy, retain, strong }.
Douglas Gregor988358f2009-11-19 00:14:45 +00004521 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004522 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004523 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004524 ObjCDeclSpec::DQ_PR_retain|
4525 ObjCDeclSpec::DQ_PR_strong);
Douglas Gregor988358f2009-11-19 00:14:45 +00004526 if (AssignCopyRetMask &&
4527 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004528 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004529 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004530 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
4531 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
Douglas Gregor988358f2009-11-19 00:14:45 +00004532 return true;
4533
4534 return false;
4535}
4536
Douglas Gregora93b1082009-11-18 23:08:07 +00004537void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004538 if (!CodeCompleter)
4539 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004540
Steve Naroffece8e712009-10-08 21:55:05 +00004541 unsigned Attributes = ODS.getPropertyAttributes();
4542
John McCall0a2c5e22010-08-25 06:19:51 +00004543 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004544 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4545 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004546 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004547 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004548 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004549 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004550 Results.AddResult(CodeCompletionResult("assign"));
John McCallf85e1932011-06-15 23:02:42 +00004551 if (!ObjCPropertyFlagConflicts(Attributes,
4552 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4553 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004554 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004555 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004556 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004557 Results.AddResult(CodeCompletionResult("retain"));
John McCallf85e1932011-06-15 23:02:42 +00004558 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4559 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004560 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004561 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004562 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004563 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004564 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4565 Results.AddResult(CodeCompletionResult("atomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004566 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004567 CodeCompletionBuilder Setter(Results.getAllocator());
4568 Setter.AddTypedTextChunk("setter");
4569 Setter.AddTextChunk(" = ");
4570 Setter.AddPlaceholderChunk("method");
4571 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004572 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004573 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004574 CodeCompletionBuilder Getter(Results.getAllocator());
4575 Getter.AddTypedTextChunk("getter");
4576 Getter.AddTextChunk(" = ");
4577 Getter.AddPlaceholderChunk("method");
4578 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004579 }
Steve Naroffece8e712009-10-08 21:55:05 +00004580 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004581 HandleCodeCompleteResults(this, CodeCompleter,
4582 CodeCompletionContext::CCC_Other,
4583 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004584}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004585
Douglas Gregor4ad96852009-11-19 07:41:15 +00004586/// \brief Descripts the kind of Objective-C method that we want to find
4587/// via code completion.
4588enum ObjCMethodKind {
4589 MK_Any, //< Any kind of method, provided it means other specified criteria.
4590 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4591 MK_OneArgSelector //< One-argument selector.
4592};
4593
Douglas Gregor458433d2010-08-26 15:07:07 +00004594static bool isAcceptableObjCSelector(Selector Sel,
4595 ObjCMethodKind WantKind,
4596 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004597 unsigned NumSelIdents,
4598 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004599 if (NumSelIdents > Sel.getNumArgs())
4600 return false;
4601
4602 switch (WantKind) {
4603 case MK_Any: break;
4604 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4605 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4606 }
4607
Douglas Gregorcf544262010-11-17 21:36:08 +00004608 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4609 return false;
4610
Douglas Gregor458433d2010-08-26 15:07:07 +00004611 for (unsigned I = 0; I != NumSelIdents; ++I)
4612 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4613 return false;
4614
4615 return true;
4616}
4617
Douglas Gregor4ad96852009-11-19 07:41:15 +00004618static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4619 ObjCMethodKind WantKind,
4620 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004621 unsigned NumSelIdents,
4622 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004623 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004624 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004625}
Douglas Gregord36adf52010-09-16 16:06:31 +00004626
4627namespace {
4628 /// \brief A set of selectors, which is used to avoid introducing multiple
4629 /// completions with the same selector into the result set.
4630 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4631}
4632
Douglas Gregor36ecb042009-11-17 23:22:23 +00004633/// \brief Add all of the Objective-C methods in the given Objective-C
4634/// container to the set of results.
4635///
4636/// The container will be a class, protocol, category, or implementation of
4637/// any of the above. This mether will recurse to include methods from
4638/// the superclasses of classes along with their categories, protocols, and
4639/// implementations.
4640///
4641/// \param Container the container in which we'll look to find methods.
4642///
4643/// \param WantInstance whether to add instance methods (only); if false, this
4644/// routine will add factory methods (only).
4645///
4646/// \param CurContext the context in which we're performing the lookup that
4647/// finds methods.
4648///
Douglas Gregorcf544262010-11-17 21:36:08 +00004649/// \param AllowSameLength Whether we allow a method to be added to the list
4650/// when it has the same number of parameters as we have selector identifiers.
4651///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004652/// \param Results the structure into which we'll add results.
4653static void AddObjCMethods(ObjCContainerDecl *Container,
4654 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004655 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004656 IdentifierInfo **SelIdents,
4657 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004658 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004659 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004660 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004661 ResultBuilder &Results,
4662 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004663 typedef CodeCompletionResult Result;
Douglas Gregor36ecb042009-11-17 23:22:23 +00004664 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4665 MEnd = Container->meth_end();
4666 M != MEnd; ++M) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004667 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4668 // Check whether the selector identifiers we've been given are a
4669 // subset of the identifiers for this particular method.
Douglas Gregorcf544262010-11-17 21:36:08 +00004670 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4671 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004672 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004673
Douglas Gregord36adf52010-09-16 16:06:31 +00004674 if (!Selectors.insert((*M)->getSelector()))
4675 continue;
4676
Douglas Gregord3c68542009-11-19 01:08:35 +00004677 Result R = Result(*M, 0);
4678 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004679 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004680 if (!InOriginalClass)
4681 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004682 Results.MaybeAddResult(R, CurContext);
4683 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004684 }
4685
Douglas Gregore396c7b2010-09-16 15:34:59 +00004686 // Visit the protocols of protocols.
4687 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004688 if (Protocol->hasDefinition()) {
4689 const ObjCList<ObjCProtocolDecl> &Protocols
4690 = Protocol->getReferencedProtocols();
4691 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4692 E = Protocols.end();
4693 I != E; ++I)
4694 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4695 NumSelIdents, CurContext, Selectors, AllowSameLength,
4696 Results, false);
4697 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004698 }
4699
Douglas Gregor36ecb042009-11-17 23:22:23 +00004700 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004701 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004702 return;
4703
4704 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004705 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4706 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004707 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004708 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004709 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004710
4711 // Add methods in categories.
4712 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4713 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004714 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004715 NumSelIdents, CurContext, Selectors, AllowSameLength,
4716 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004717
4718 // Add a categories protocol methods.
4719 const ObjCList<ObjCProtocolDecl> &Protocols
4720 = CatDecl->getReferencedProtocols();
4721 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4722 E = Protocols.end();
4723 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004724 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004725 NumSelIdents, CurContext, Selectors, AllowSameLength,
4726 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004727
4728 // Add methods in category implementations.
4729 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004730 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004731 NumSelIdents, CurContext, Selectors, AllowSameLength,
4732 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004733 }
4734
4735 // Add methods in superclass.
4736 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004737 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004738 SelIdents, NumSelIdents, CurContext, Selectors,
4739 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004740
4741 // Add methods in our implementation, if any.
4742 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004743 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004744 NumSelIdents, CurContext, Selectors, AllowSameLength,
4745 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004746}
4747
4748
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004749void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004750 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004751
4752 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004753 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004754 if (!Class) {
4755 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004756 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004757 Class = Category->getClassInterface();
4758
4759 if (!Class)
4760 return;
4761 }
4762
4763 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004764 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4765 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004766 Results.EnterNewScope();
4767
Douglas Gregord36adf52010-09-16 16:06:31 +00004768 VisitedSelectorSet Selectors;
4769 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004770 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004771 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004772 HandleCodeCompleteResults(this, CodeCompleter,
4773 CodeCompletionContext::CCC_Other,
4774 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004775}
4776
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004777void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004778 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004779
4780 // Try to find the interface where setters might live.
4781 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004782 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004783 if (!Class) {
4784 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004785 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004786 Class = Category->getClassInterface();
4787
4788 if (!Class)
4789 return;
4790 }
4791
4792 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004793 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4794 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004795 Results.EnterNewScope();
4796
Douglas Gregord36adf52010-09-16 16:06:31 +00004797 VisitedSelectorSet Selectors;
4798 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004799 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004800
4801 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004802 HandleCodeCompleteResults(this, CodeCompleter,
4803 CodeCompletionContext::CCC_Other,
4804 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004805}
4806
Douglas Gregorafc45782011-02-15 22:19:42 +00004807void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4808 bool IsParameter) {
John McCall0a2c5e22010-08-25 06:19:51 +00004809 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004810 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4811 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004812 Results.EnterNewScope();
4813
4814 // Add context-sensitive, Objective-C parameter-passing keywords.
4815 bool AddedInOut = false;
4816 if ((DS.getObjCDeclQualifier() &
4817 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4818 Results.AddResult("in");
4819 Results.AddResult("inout");
4820 AddedInOut = true;
4821 }
4822 if ((DS.getObjCDeclQualifier() &
4823 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4824 Results.AddResult("out");
4825 if (!AddedInOut)
4826 Results.AddResult("inout");
4827 }
4828 if ((DS.getObjCDeclQualifier() &
4829 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4830 ObjCDeclSpec::DQ_Oneway)) == 0) {
4831 Results.AddResult("bycopy");
4832 Results.AddResult("byref");
4833 Results.AddResult("oneway");
4834 }
4835
Douglas Gregorafc45782011-02-15 22:19:42 +00004836 // If we're completing the return type of an Objective-C method and the
4837 // identifier IBAction refers to a macro, provide a completion item for
4838 // an action, e.g.,
4839 // IBAction)<#selector#>:(id)sender
4840 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4841 Context.Idents.get("IBAction").hasMacroDefinition()) {
Douglas Gregorafc45782011-02-15 22:19:42 +00004842 CodeCompletionBuilder Builder(Results.getAllocator(), CCP_CodePattern,
4843 CXAvailability_Available);
4844 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004845 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004846 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004847 Builder.AddChunk(CodeCompletionString::CK_Colon);
4848 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004849 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004850 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004851 Builder.AddTextChunk("sender");
4852 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4853 }
4854
Douglas Gregord32b0222010-08-24 01:06:58 +00004855 // Add various builtin type names and specifiers.
4856 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4857 Results.ExitScope();
4858
4859 // Add the various type names
4860 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4861 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4862 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4863 CodeCompleter->includeGlobals());
4864
4865 if (CodeCompleter->includeMacros())
4866 AddMacroResults(PP, Results);
4867
4868 HandleCodeCompleteResults(this, CodeCompleter,
4869 CodeCompletionContext::CCC_Type,
4870 Results.data(), Results.size());
4871}
4872
Douglas Gregor22f56992010-04-06 19:22:33 +00004873/// \brief When we have an expression with type "id", we may assume
4874/// that it has some more-specific class type based on knowledge of
4875/// common uses of Objective-C. This routine returns that class type,
4876/// or NULL if no better result could be determined.
4877static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004878 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004879 if (!Msg)
4880 return 0;
4881
4882 Selector Sel = Msg->getSelector();
4883 if (Sel.isNull())
4884 return 0;
4885
4886 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4887 if (!Id)
4888 return 0;
4889
4890 ObjCMethodDecl *Method = Msg->getMethodDecl();
4891 if (!Method)
4892 return 0;
4893
4894 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004895 ObjCInterfaceDecl *IFace = 0;
4896 switch (Msg->getReceiverKind()) {
4897 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004898 if (const ObjCObjectType *ObjType
4899 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4900 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004901 break;
4902
4903 case ObjCMessageExpr::Instance: {
4904 QualType T = Msg->getInstanceReceiver()->getType();
4905 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4906 IFace = Ptr->getInterfaceDecl();
4907 break;
4908 }
4909
4910 case ObjCMessageExpr::SuperInstance:
4911 case ObjCMessageExpr::SuperClass:
4912 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00004913 }
4914
4915 if (!IFace)
4916 return 0;
4917
4918 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4919 if (Method->isInstanceMethod())
4920 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4921 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00004922 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00004923 .Case("autorelease", IFace)
4924 .Case("copy", IFace)
4925 .Case("copyWithZone", IFace)
4926 .Case("mutableCopy", IFace)
4927 .Case("mutableCopyWithZone", IFace)
4928 .Case("awakeFromCoder", IFace)
4929 .Case("replacementObjectFromCoder", IFace)
4930 .Case("class", IFace)
4931 .Case("classForCoder", IFace)
4932 .Case("superclass", Super)
4933 .Default(0);
4934
4935 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4936 .Case("new", IFace)
4937 .Case("alloc", IFace)
4938 .Case("allocWithZone", IFace)
4939 .Case("class", IFace)
4940 .Case("superclass", Super)
4941 .Default(0);
4942}
4943
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004944// Add a special completion for a message send to "super", which fills in the
4945// most likely case of forwarding all of our arguments to the superclass
4946// function.
4947///
4948/// \param S The semantic analysis object.
4949///
4950/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4951/// the "super" keyword. Otherwise, we just need to provide the arguments.
4952///
4953/// \param SelIdents The identifiers in the selector that have already been
4954/// provided as arguments for a send to "super".
4955///
4956/// \param NumSelIdents The number of identifiers in \p SelIdents.
4957///
4958/// \param Results The set of results to augment.
4959///
4960/// \returns the Objective-C method declaration that would be invoked by
4961/// this "super" completion. If NULL, no completion was added.
4962static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4963 IdentifierInfo **SelIdents,
4964 unsigned NumSelIdents,
4965 ResultBuilder &Results) {
4966 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
4967 if (!CurMethod)
4968 return 0;
4969
4970 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
4971 if (!Class)
4972 return 0;
4973
4974 // Try to find a superclass method with the same selector.
4975 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00004976 while ((Class = Class->getSuperClass()) && !SuperMethod) {
4977 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004978 SuperMethod = Class->getMethod(CurMethod->getSelector(),
4979 CurMethod->isInstanceMethod());
4980
Douglas Gregor78bcd912011-02-16 00:51:18 +00004981 // Check in categories or class extensions.
4982 if (!SuperMethod) {
4983 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
4984 Category = Category->getNextClassCategory())
4985 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
4986 CurMethod->isInstanceMethod())))
4987 break;
4988 }
4989 }
4990
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004991 if (!SuperMethod)
4992 return 0;
4993
4994 // Check whether the superclass method has the same signature.
4995 if (CurMethod->param_size() != SuperMethod->param_size() ||
4996 CurMethod->isVariadic() != SuperMethod->isVariadic())
4997 return 0;
4998
4999 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5000 CurPEnd = CurMethod->param_end(),
5001 SuperP = SuperMethod->param_begin();
5002 CurP != CurPEnd; ++CurP, ++SuperP) {
5003 // Make sure the parameter types are compatible.
5004 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5005 (*SuperP)->getType()))
5006 return 0;
5007
5008 // Make sure we have a parameter name to forward!
5009 if (!(*CurP)->getIdentifier())
5010 return 0;
5011 }
5012
5013 // We have a superclass method. Now, form the send-to-super completion.
Douglas Gregor218937c2011-02-01 19:23:04 +00005014 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005015
5016 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005017 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5018 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005019
5020 // If we need the "super" keyword, add it (plus some spacing).
5021 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005022 Builder.AddTypedTextChunk("super");
5023 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005024 }
5025
5026 Selector Sel = CurMethod->getSelector();
5027 if (Sel.isUnarySelector()) {
5028 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005029 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005030 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005031 else
Douglas Gregordae68752011-02-01 22:57:45 +00005032 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005033 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005034 } else {
5035 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5036 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5037 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005038 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005039
5040 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005041 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005042 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005043 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005044 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005045 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005046 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005047 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005048 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005049 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005050 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005051 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005052 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005053 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005054 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005055 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005056 }
5057 }
5058 }
5059
Douglas Gregor218937c2011-02-01 19:23:04 +00005060 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005061 SuperMethod->isInstanceMethod()
5062 ? CXCursor_ObjCInstanceMethodDecl
5063 : CXCursor_ObjCClassMethodDecl));
5064 return SuperMethod;
5065}
5066
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005067void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005068 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005069 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5070 CodeCompletionContext::CCC_ObjCMessageReceiver,
David Blaikie4e4d0842012-03-11 07:00:24 +00005071 getLangOpts().CPlusPlus0x
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005072 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5073 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005074
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005075 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5076 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005077 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5078 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005079
5080 // If we are in an Objective-C method inside a class that has a superclass,
5081 // add "super" as an option.
5082 if (ObjCMethodDecl *Method = getCurMethodDecl())
5083 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005084 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005085 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005086
5087 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5088 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005089
David Blaikie4e4d0842012-03-11 07:00:24 +00005090 if (getLangOpts().CPlusPlus0x)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005091 addThisCompletion(*this, Results);
5092
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005093 Results.ExitScope();
5094
5095 if (CodeCompleter->includeMacros())
5096 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005097 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005098 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005099
5100}
5101
Douglas Gregor2725ca82010-04-21 19:57:20 +00005102void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5103 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005104 unsigned NumSelIdents,
5105 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005106 ObjCInterfaceDecl *CDecl = 0;
5107 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5108 // Figure out which interface we're in.
5109 CDecl = CurMethod->getClassInterface();
5110 if (!CDecl)
5111 return;
5112
5113 // Find the superclass of this class.
5114 CDecl = CDecl->getSuperClass();
5115 if (!CDecl)
5116 return;
5117
5118 if (CurMethod->isInstanceMethod()) {
5119 // We are inside an instance method, which means that the message
5120 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005121 // current object.
5122 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005123 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005124 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005125 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005126 }
5127
5128 // Fall through to send to the superclass in CDecl.
5129 } else {
5130 // "super" may be the name of a type or variable. Figure out which
5131 // it is.
5132 IdentifierInfo *Super = &Context.Idents.get("super");
5133 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5134 LookupOrdinaryName);
5135 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5136 // "super" names an interface. Use it.
5137 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005138 if (const ObjCObjectType *Iface
5139 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5140 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005141 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5142 // "super" names an unresolved type; we can't be more specific.
5143 } else {
5144 // Assume that "super" names some kind of value and parse that way.
5145 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005146 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005147 UnqualifiedId id;
5148 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005149 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5150 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005151 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005152 SelIdents, NumSelIdents,
5153 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005154 }
5155
5156 // Fall through
5157 }
5158
John McCallb3d87482010-08-24 05:47:05 +00005159 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005160 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005161 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005162 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005163 NumSelIdents, AtArgumentExpression,
5164 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005165}
5166
Douglas Gregorb9d77572010-09-21 00:03:25 +00005167/// \brief Given a set of code-completion results for the argument of a message
5168/// send, determine the preferred type (if any) for that argument expression.
5169static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5170 unsigned NumSelIdents) {
5171 typedef CodeCompletionResult Result;
5172 ASTContext &Context = Results.getSema().Context;
5173
5174 QualType PreferredType;
5175 unsigned BestPriority = CCP_Unlikely * 2;
5176 Result *ResultsData = Results.data();
5177 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5178 Result &R = ResultsData[I];
5179 if (R.Kind == Result::RK_Declaration &&
5180 isa<ObjCMethodDecl>(R.Declaration)) {
5181 if (R.Priority <= BestPriority) {
5182 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5183 if (NumSelIdents <= Method->param_size()) {
5184 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5185 ->getType();
5186 if (R.Priority < BestPriority || PreferredType.isNull()) {
5187 BestPriority = R.Priority;
5188 PreferredType = MyPreferredType;
5189 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5190 MyPreferredType)) {
5191 PreferredType = QualType();
5192 }
5193 }
5194 }
5195 }
5196 }
5197
5198 return PreferredType;
5199}
5200
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005201static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5202 ParsedType Receiver,
5203 IdentifierInfo **SelIdents,
5204 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005205 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005206 bool IsSuper,
5207 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005208 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005209 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005210
Douglas Gregor24a069f2009-11-17 17:59:40 +00005211 // If the given name refers to an interface type, retrieve the
5212 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005213 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005214 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005215 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005216 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5217 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005218 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005219
Douglas Gregor36ecb042009-11-17 23:22:23 +00005220 // Add all of the factory methods in this Objective-C class, its protocols,
5221 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005222 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005223
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005224 // If this is a send-to-super, try to add the special "super" send
5225 // completion.
5226 if (IsSuper) {
5227 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005228 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5229 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005230 Results.Ignore(SuperMethod);
5231 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005232
Douglas Gregor265f7492010-08-27 15:29:55 +00005233 // If we're inside an Objective-C method definition, prefer its selector to
5234 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005235 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005236 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005237
Douglas Gregord36adf52010-09-16 16:06:31 +00005238 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005239 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005240 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005241 SemaRef.CurContext, Selectors, AtArgumentExpression,
5242 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005243 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005244 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005245
Douglas Gregor719770d2010-04-06 17:30:22 +00005246 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005247 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005248 if (SemaRef.ExternalSource) {
5249 for (uint32_t I = 0,
5250 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005251 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005252 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5253 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005254 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005255
5256 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005257 }
5258 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005259
5260 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5261 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005262 M != MEnd; ++M) {
5263 for (ObjCMethodList *MethList = &M->second.second;
5264 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005265 MethList = MethList->Next) {
5266 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5267 NumSelIdents))
5268 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005269
Douglas Gregor13438f92010-04-06 16:40:00 +00005270 Result R(MethList->Method, 0);
5271 R.StartParameter = NumSelIdents;
5272 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005273 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005274 }
5275 }
5276 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005277
5278 Results.ExitScope();
5279}
Douglas Gregor13438f92010-04-06 16:40:00 +00005280
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005281void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5282 IdentifierInfo **SelIdents,
5283 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005284 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005285 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005286
5287 QualType T = this->GetTypeFromParser(Receiver);
5288
Douglas Gregor218937c2011-02-01 19:23:04 +00005289 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005290 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005291 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005292
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005293 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5294 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005295
5296 // If we're actually at the argument expression (rather than prior to the
5297 // selector), we're actually performing code completion for an expression.
5298 // Determine whether we have a single, best method. If so, we can
5299 // code-complete the expression using the corresponding parameter type as
5300 // our preferred type, improving completion results.
5301 if (AtArgumentExpression) {
5302 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005303 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005304 if (PreferredType.isNull())
5305 CodeCompleteOrdinaryName(S, PCC_Expression);
5306 else
5307 CodeCompleteExpression(S, PreferredType);
5308 return;
5309 }
5310
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005311 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005312 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005313 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005314}
5315
Richard Trieuf81e5a92011-09-09 02:00:50 +00005316void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005317 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005318 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005319 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005320 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005321 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005322
5323 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005324
Douglas Gregor36ecb042009-11-17 23:22:23 +00005325 // If necessary, apply function/array conversion to the receiver.
5326 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005327 if (RecExpr) {
5328 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5329 if (Conv.isInvalid()) // conversion failed. bail.
5330 return;
5331 RecExpr = Conv.take();
5332 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005333 QualType ReceiverType = RecExpr? RecExpr->getType()
5334 : Super? Context.getObjCObjectPointerType(
5335 Context.getObjCInterfaceType(Super))
5336 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005337
Douglas Gregorda892642010-11-08 21:12:30 +00005338 // If we're messaging an expression with type "id" or "Class", check
5339 // whether we know something special about the receiver that allows
5340 // us to assume a more-specific receiver type.
5341 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5342 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5343 if (ReceiverType->isObjCClassType())
5344 return CodeCompleteObjCClassMessage(S,
5345 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5346 SelIdents, NumSelIdents,
5347 AtArgumentExpression, Super);
5348
5349 ReceiverType = Context.getObjCObjectPointerType(
5350 Context.getObjCInterfaceType(IFace));
5351 }
5352
Douglas Gregor36ecb042009-11-17 23:22:23 +00005353 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005354 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005355 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005356 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005357
Douglas Gregor36ecb042009-11-17 23:22:23 +00005358 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005359
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005360 // If this is a send-to-super, try to add the special "super" send
5361 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005362 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005363 if (ObjCMethodDecl *SuperMethod
5364 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5365 Results))
5366 Results.Ignore(SuperMethod);
5367 }
5368
Douglas Gregor265f7492010-08-27 15:29:55 +00005369 // If we're inside an Objective-C method definition, prefer its selector to
5370 // others.
5371 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5372 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005373
Douglas Gregord36adf52010-09-16 16:06:31 +00005374 // Keep track of the selectors we've already added.
5375 VisitedSelectorSet Selectors;
5376
Douglas Gregorf74a4192009-11-18 00:06:18 +00005377 // Handle messages to Class. This really isn't a message to an instance
5378 // method, so we treat it the same way we would treat a message send to a
5379 // class method.
5380 if (ReceiverType->isObjCClassType() ||
5381 ReceiverType->isObjCQualifiedClassType()) {
5382 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5383 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005384 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005385 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005386 }
5387 }
5388 // Handle messages to a qualified ID ("id<foo>").
5389 else if (const ObjCObjectPointerType *QualID
5390 = ReceiverType->getAsObjCQualifiedIdType()) {
5391 // Search protocols for instance methods.
5392 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5393 E = QualID->qual_end();
5394 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005395 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005396 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005397 }
5398 // Handle messages to a pointer to interface type.
5399 else if (const ObjCObjectPointerType *IFacePtr
5400 = ReceiverType->getAsObjCInterfacePointerType()) {
5401 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005402 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005403 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5404 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005405
5406 // Search protocols for instance methods.
5407 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5408 E = IFacePtr->qual_end();
5409 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005410 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005411 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005412 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005413 // Handle messages to "id".
5414 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005415 // We're messaging "id", so provide all instance methods we know
5416 // about as code-completion results.
5417
5418 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005419 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005420 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005421 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5422 I != N; ++I) {
5423 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005424 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005425 continue;
5426
Sebastian Redldb9d2142010-08-02 23:18:59 +00005427 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005428 }
5429 }
5430
Sebastian Redldb9d2142010-08-02 23:18:59 +00005431 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5432 MEnd = MethodPool.end();
5433 M != MEnd; ++M) {
5434 for (ObjCMethodList *MethList = &M->second.first;
5435 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005436 MethList = MethList->Next) {
5437 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5438 NumSelIdents))
5439 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005440
5441 if (!Selectors.insert(MethList->Method->getSelector()))
5442 continue;
5443
Douglas Gregor13438f92010-04-06 16:40:00 +00005444 Result R(MethList->Method, 0);
5445 R.StartParameter = NumSelIdents;
5446 R.AllParametersAreInformative = false;
5447 Results.MaybeAddResult(R, CurContext);
5448 }
5449 }
5450 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005451 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005452
5453
5454 // If we're actually at the argument expression (rather than prior to the
5455 // selector), we're actually performing code completion for an expression.
5456 // Determine whether we have a single, best method. If so, we can
5457 // code-complete the expression using the corresponding parameter type as
5458 // our preferred type, improving completion results.
5459 if (AtArgumentExpression) {
5460 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5461 NumSelIdents);
5462 if (PreferredType.isNull())
5463 CodeCompleteOrdinaryName(S, PCC_Expression);
5464 else
5465 CodeCompleteExpression(S, PreferredType);
5466 return;
5467 }
5468
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005469 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005470 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005471 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005472}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005473
Douglas Gregorfb629412010-08-23 21:17:50 +00005474void Sema::CodeCompleteObjCForCollection(Scope *S,
5475 DeclGroupPtrTy IterationVar) {
5476 CodeCompleteExpressionData Data;
5477 Data.ObjCCollection = true;
5478
5479 if (IterationVar.getAsOpaquePtr()) {
5480 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5481 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5482 if (*I)
5483 Data.IgnoreDecls.push_back(*I);
5484 }
5485 }
5486
5487 CodeCompleteExpression(S, Data);
5488}
5489
Douglas Gregor458433d2010-08-26 15:07:07 +00005490void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5491 unsigned NumSelIdents) {
5492 // If we have an external source, load the entire class method
5493 // pool from the AST file.
5494 if (ExternalSource) {
5495 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5496 I != N; ++I) {
5497 Selector Sel = ExternalSource->GetExternalSelector(I);
5498 if (Sel.isNull() || MethodPool.count(Sel))
5499 continue;
5500
5501 ReadMethodPool(Sel);
5502 }
5503 }
5504
Douglas Gregor218937c2011-02-01 19:23:04 +00005505 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5506 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005507 Results.EnterNewScope();
5508 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5509 MEnd = MethodPool.end();
5510 M != MEnd; ++M) {
5511
5512 Selector Sel = M->first;
5513 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5514 continue;
5515
Douglas Gregor218937c2011-02-01 19:23:04 +00005516 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor458433d2010-08-26 15:07:07 +00005517 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005518 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005519 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005520 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005521 continue;
5522 }
5523
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005524 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005525 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005526 if (I == NumSelIdents) {
5527 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005528 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005529 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005530 Accumulator.clear();
5531 }
5532 }
5533
Benjamin Kramera0651c52011-07-26 16:59:25 +00005534 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005535 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005536 }
Douglas Gregordae68752011-02-01 22:57:45 +00005537 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005538 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005539 }
5540 Results.ExitScope();
5541
5542 HandleCodeCompleteResults(this, CodeCompleter,
5543 CodeCompletionContext::CCC_SelectorName,
5544 Results.data(), Results.size());
5545}
5546
Douglas Gregor55385fe2009-11-18 04:19:12 +00005547/// \brief Add all of the protocol declarations that we find in the given
5548/// (translation unit) context.
5549static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005550 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005551 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005552 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005553
5554 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5555 DEnd = Ctx->decls_end();
5556 D != DEnd; ++D) {
5557 // Record any protocols we find.
5558 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005559 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005560 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005561 }
5562}
5563
5564void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5565 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005566 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5567 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005568
Douglas Gregor70c23352010-12-09 21:44:02 +00005569 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5570 Results.EnterNewScope();
5571
5572 // Tell the result set to ignore all of the protocols we have
5573 // already seen.
5574 // FIXME: This doesn't work when caching code-completion results.
5575 for (unsigned I = 0; I != NumProtocols; ++I)
5576 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5577 Protocols[I].second))
5578 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005579
Douglas Gregor70c23352010-12-09 21:44:02 +00005580 // Add all protocols.
5581 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5582 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005583
Douglas Gregor70c23352010-12-09 21:44:02 +00005584 Results.ExitScope();
5585 }
5586
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005587 HandleCodeCompleteResults(this, CodeCompleter,
5588 CodeCompletionContext::CCC_ObjCProtocolName,
5589 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005590}
5591
5592void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005593 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5594 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005595
Douglas Gregor70c23352010-12-09 21:44:02 +00005596 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5597 Results.EnterNewScope();
5598
5599 // Add all protocols.
5600 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5601 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005602
Douglas Gregor70c23352010-12-09 21:44:02 +00005603 Results.ExitScope();
5604 }
5605
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005606 HandleCodeCompleteResults(this, CodeCompleter,
5607 CodeCompletionContext::CCC_ObjCProtocolName,
5608 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005609}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005610
5611/// \brief Add all of the Objective-C interface declarations that we find in
5612/// the given (translation unit) context.
5613static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5614 bool OnlyForwardDeclarations,
5615 bool OnlyUnimplemented,
5616 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005617 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005618
5619 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5620 DEnd = Ctx->decls_end();
5621 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005622 // Record any interfaces we find.
5623 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005624 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005625 (!OnlyUnimplemented || !Class->getImplementation()))
5626 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005627 }
5628}
5629
5630void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005631 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5632 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005633 Results.EnterNewScope();
5634
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005635 if (CodeCompleter->includeGlobals()) {
5636 // Add all classes.
5637 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5638 false, Results);
5639 }
5640
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005641 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005642
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005643 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005644 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005645 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005646}
5647
Douglas Gregorc83c6872010-04-15 22:33:43 +00005648void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5649 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005650 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005651 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005652 Results.EnterNewScope();
5653
5654 // Make sure that we ignore the class we're currently defining.
5655 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005656 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005657 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005658 Results.Ignore(CurClass);
5659
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005660 if (CodeCompleter->includeGlobals()) {
5661 // Add all classes.
5662 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5663 false, Results);
5664 }
5665
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005666 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005667
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005668 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005669 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005670 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005671}
5672
5673void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005674 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5675 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005676 Results.EnterNewScope();
5677
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005678 if (CodeCompleter->includeGlobals()) {
5679 // Add all unimplemented classes.
5680 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5681 true, Results);
5682 }
5683
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005684 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005685
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005686 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005687 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005688 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005689}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005690
5691void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005692 IdentifierInfo *ClassName,
5693 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005694 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005695
Douglas Gregor218937c2011-02-01 19:23:04 +00005696 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005697 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005698
5699 // Ignore any categories we find that have already been implemented by this
5700 // interface.
5701 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5702 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005703 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005704 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5705 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5706 Category = Category->getNextClassCategory())
5707 CategoryNames.insert(Category->getIdentifier());
5708
5709 // Add all of the categories we know about.
5710 Results.EnterNewScope();
5711 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5712 for (DeclContext::decl_iterator D = TU->decls_begin(),
5713 DEnd = TU->decls_end();
5714 D != DEnd; ++D)
5715 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5716 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005717 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005718 Results.ExitScope();
5719
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005720 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005721 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005722 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005723}
5724
5725void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005726 IdentifierInfo *ClassName,
5727 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005728 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005729
5730 // Find the corresponding interface. If we couldn't find the interface, the
5731 // program itself is ill-formed. However, we'll try to be helpful still by
5732 // providing the list of all of the categories we know about.
5733 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005734 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005735 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5736 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005737 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005738
Douglas Gregor218937c2011-02-01 19:23:04 +00005739 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005740 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005741
5742 // Add all of the categories that have have corresponding interface
5743 // declarations in this class and any of its superclasses, except for
5744 // already-implemented categories in the class itself.
5745 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5746 Results.EnterNewScope();
5747 bool IgnoreImplemented = true;
5748 while (Class) {
5749 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5750 Category = Category->getNextClassCategory())
5751 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5752 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005753 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005754
5755 Class = Class->getSuperClass();
5756 IgnoreImplemented = false;
5757 }
5758 Results.ExitScope();
5759
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005760 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005761 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005762 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005763}
Douglas Gregor322328b2009-11-18 22:32:06 +00005764
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005765void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005766 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005767 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5768 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005769
5770 // Figure out where this @synthesize lives.
5771 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005772 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005773 if (!Container ||
5774 (!isa<ObjCImplementationDecl>(Container) &&
5775 !isa<ObjCCategoryImplDecl>(Container)))
5776 return;
5777
5778 // Ignore any properties that have already been implemented.
5779 for (DeclContext::decl_iterator D = Container->decls_begin(),
5780 DEnd = Container->decls_end();
5781 D != DEnd; ++D)
5782 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5783 Results.Ignore(PropertyImpl->getPropertyDecl());
5784
5785 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005786 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005787 Results.EnterNewScope();
5788 if (ObjCImplementationDecl *ClassImpl
5789 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005790 AddObjCProperties(ClassImpl->getClassInterface(), false,
5791 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005792 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005793 else
5794 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005795 false, /*AllowNullaryMethods=*/false, CurContext,
5796 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005797 Results.ExitScope();
5798
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005799 HandleCodeCompleteResults(this, CodeCompleter,
5800 CodeCompletionContext::CCC_Other,
5801 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005802}
5803
5804void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005805 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005806 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005807 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5808 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005809
5810 // Figure out where this @synthesize lives.
5811 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005812 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005813 if (!Container ||
5814 (!isa<ObjCImplementationDecl>(Container) &&
5815 !isa<ObjCCategoryImplDecl>(Container)))
5816 return;
5817
5818 // Figure out which interface we're looking into.
5819 ObjCInterfaceDecl *Class = 0;
5820 if (ObjCImplementationDecl *ClassImpl
5821 = dyn_cast<ObjCImplementationDecl>(Container))
5822 Class = ClassImpl->getClassInterface();
5823 else
5824 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5825 ->getClassInterface();
5826
Douglas Gregore8426052011-04-18 14:40:46 +00005827 // Determine the type of the property we're synthesizing.
5828 QualType PropertyType = Context.getObjCIdType();
5829 if (Class) {
5830 if (ObjCPropertyDecl *Property
5831 = Class->FindPropertyDeclaration(PropertyName)) {
5832 PropertyType
5833 = Property->getType().getNonReferenceType().getUnqualifiedType();
5834
5835 // Give preference to ivars
5836 Results.setPreferredType(PropertyType);
5837 }
5838 }
5839
Douglas Gregor322328b2009-11-18 22:32:06 +00005840 // Add all of the instance variables in this class and its superclasses.
5841 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005842 bool SawSimilarlyNamedIvar = false;
5843 std::string NameWithPrefix;
5844 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005845 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005846 std::string NameWithSuffix = PropertyName->getName().str();
5847 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005848 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005849 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5850 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005851 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5852
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005853 // Determine whether we've seen an ivar with a name similar to the
5854 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005855 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005856 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005857 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005858 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005859
5860 // Reduce the priority of this result by one, to give it a slight
5861 // advantage over other results whose names don't match so closely.
5862 if (Results.size() &&
5863 Results.data()[Results.size() - 1].Kind
5864 == CodeCompletionResult::RK_Declaration &&
5865 Results.data()[Results.size() - 1].Declaration == Ivar)
5866 Results.data()[Results.size() - 1].Priority--;
5867 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005868 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005869 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005870
5871 if (!SawSimilarlyNamedIvar) {
5872 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005873 // an ivar of the appropriate type.
5874 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005875 typedef CodeCompletionResult Result;
5876 CodeCompletionAllocator &Allocator = Results.getAllocator();
5877 CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available);
5878
Douglas Gregor8987b232011-09-27 23:30:47 +00005879 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00005880 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005881 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005882 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5883 Results.AddResult(Result(Builder.TakeString(), Priority,
5884 CXCursor_ObjCIvarDecl));
5885 }
5886
Douglas Gregor322328b2009-11-18 22:32:06 +00005887 Results.ExitScope();
5888
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005889 HandleCodeCompleteResults(this, CodeCompleter,
5890 CodeCompletionContext::CCC_Other,
5891 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005892}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005893
Douglas Gregor408be5a2010-08-25 01:08:01 +00005894// Mapping from selectors to the methods that implement that selector, along
5895// with the "in original class" flag.
5896typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5897 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005898
5899/// \brief Find all of the methods that reside in the given container
5900/// (and its superclasses, protocols, etc.) that meet the given
5901/// criteria. Insert those methods into the map of known methods,
5902/// indexed by selector so they can be easily found.
5903static void FindImplementableMethods(ASTContext &Context,
5904 ObjCContainerDecl *Container,
5905 bool WantInstanceMethods,
5906 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00005907 KnownMethodsMap &KnownMethods,
5908 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005909 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5910 // Recurse into protocols.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00005911 if (!IFace->hasDefinition())
5912 return;
5913
Douglas Gregore8f5a172010-04-07 00:21:17 +00005914 const ObjCList<ObjCProtocolDecl> &Protocols
5915 = IFace->getReferencedProtocols();
5916 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005917 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005918 I != E; ++I)
5919 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005920 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005921
Douglas Gregorea766182010-10-18 18:21:28 +00005922 // Add methods from any class extensions and categories.
5923 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5924 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00005925 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5926 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005927 KnownMethods, false);
5928
5929 // Visit the superclass.
5930 if (IFace->getSuperClass())
5931 FindImplementableMethods(Context, IFace->getSuperClass(),
5932 WantInstanceMethods, ReturnType,
5933 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005934 }
5935
5936 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5937 // Recurse into protocols.
5938 const ObjCList<ObjCProtocolDecl> &Protocols
5939 = Category->getReferencedProtocols();
5940 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005941 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005942 I != E; ++I)
5943 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005944 KnownMethods, InOriginalClass);
5945
5946 // If this category is the original class, jump to the interface.
5947 if (InOriginalClass && Category->getClassInterface())
5948 FindImplementableMethods(Context, Category->getClassInterface(),
5949 WantInstanceMethods, ReturnType, KnownMethods,
5950 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005951 }
5952
5953 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005954 if (Protocol->hasDefinition()) {
5955 // Recurse into protocols.
5956 const ObjCList<ObjCProtocolDecl> &Protocols
5957 = Protocol->getReferencedProtocols();
5958 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5959 E = Protocols.end();
5960 I != E; ++I)
5961 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
5962 KnownMethods, false);
5963 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00005964 }
5965
5966 // Add methods in this container. This operation occurs last because
5967 // we want the methods from this container to override any methods
5968 // we've previously seen with the same selector.
5969 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
5970 MEnd = Container->meth_end();
5971 M != MEnd; ++M) {
5972 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
5973 if (!ReturnType.isNull() &&
5974 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
5975 continue;
5976
Douglas Gregor408be5a2010-08-25 01:08:01 +00005977 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005978 }
5979 }
5980}
5981
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005982/// \brief Add the parenthesized return or parameter type chunk to a code
5983/// completion string.
5984static void AddObjCPassingTypeChunk(QualType Type,
5985 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005986 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005987 CodeCompletionBuilder &Builder) {
5988 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor8987b232011-09-27 23:30:47 +00005989 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005990 Builder.getAllocator()));
5991 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5992}
5993
5994/// \brief Determine whether the given class is or inherits from a class by
5995/// the given name.
5996static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00005997 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005998 if (!Class)
5999 return false;
6000
6001 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6002 return true;
6003
6004 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6005}
6006
6007/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6008/// Key-Value Observing (KVO).
6009static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6010 bool IsInstanceMethod,
6011 QualType ReturnType,
6012 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006013 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006014 ResultBuilder &Results) {
6015 IdentifierInfo *PropName = Property->getIdentifier();
6016 if (!PropName || PropName->getLength() == 0)
6017 return;
6018
Douglas Gregor8987b232011-09-27 23:30:47 +00006019 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6020
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006021 // Builder that will create each code completion.
6022 typedef CodeCompletionResult Result;
6023 CodeCompletionAllocator &Allocator = Results.getAllocator();
6024 CodeCompletionBuilder Builder(Allocator);
6025
6026 // The selector table.
6027 SelectorTable &Selectors = Context.Selectors;
6028
6029 // The property name, copied into the code completion allocation region
6030 // on demand.
6031 struct KeyHolder {
6032 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006033 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006034 const char *CopiedKey;
6035
Chris Lattner5f9e2722011-07-23 10:55:15 +00006036 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006037 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6038
6039 operator const char *() {
6040 if (CopiedKey)
6041 return CopiedKey;
6042
6043 return CopiedKey = Allocator.CopyString(Key);
6044 }
6045 } Key(Allocator, PropName->getName());
6046
6047 // The uppercased name of the property name.
6048 std::string UpperKey = PropName->getName();
6049 if (!UpperKey.empty())
6050 UpperKey[0] = toupper(UpperKey[0]);
6051
6052 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6053 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6054 Property->getType());
6055 bool ReturnTypeMatchesVoid
6056 = ReturnType.isNull() || ReturnType->isVoidType();
6057
6058 // Add the normal accessor -(type)key.
6059 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006060 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006061 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6062 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00006063 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006064
6065 Builder.AddTypedTextChunk(Key);
6066 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6067 CXCursor_ObjCInstanceMethodDecl));
6068 }
6069
6070 // If we have an integral or boolean property (or the user has provided
6071 // an integral or boolean return type), add the accessor -(type)isKey.
6072 if (IsInstanceMethod &&
6073 ((!ReturnType.isNull() &&
6074 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6075 (ReturnType.isNull() &&
6076 (Property->getType()->isIntegerType() ||
6077 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006078 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006079 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006080 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006081 if (ReturnType.isNull()) {
6082 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6083 Builder.AddTextChunk("BOOL");
6084 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6085 }
6086
6087 Builder.AddTypedTextChunk(
6088 Allocator.CopyString(SelectorId->getName()));
6089 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6090 CXCursor_ObjCInstanceMethodDecl));
6091 }
6092 }
6093
6094 // Add the normal mutator.
6095 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6096 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006097 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006098 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006099 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006100 if (ReturnType.isNull()) {
6101 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6102 Builder.AddTextChunk("void");
6103 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6104 }
6105
6106 Builder.AddTypedTextChunk(
6107 Allocator.CopyString(SelectorId->getName()));
6108 Builder.AddTypedTextChunk(":");
Douglas Gregor8987b232011-09-27 23:30:47 +00006109 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006110 Builder.AddTextChunk(Key);
6111 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6112 CXCursor_ObjCInstanceMethodDecl));
6113 }
6114 }
6115
6116 // Indexed and unordered accessors
6117 unsigned IndexedGetterPriority = CCP_CodePattern;
6118 unsigned IndexedSetterPriority = CCP_CodePattern;
6119 unsigned UnorderedGetterPriority = CCP_CodePattern;
6120 unsigned UnorderedSetterPriority = CCP_CodePattern;
6121 if (const ObjCObjectPointerType *ObjCPointer
6122 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6123 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6124 // If this interface type is not provably derived from a known
6125 // collection, penalize the corresponding completions.
6126 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6127 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6128 if (!InheritsFromClassNamed(IFace, "NSArray"))
6129 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6130 }
6131
6132 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6133 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6134 if (!InheritsFromClassNamed(IFace, "NSSet"))
6135 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6136 }
6137 }
6138 } else {
6139 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6140 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6141 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6142 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6143 }
6144
6145 // Add -(NSUInteger)countOf<key>
6146 if (IsInstanceMethod &&
6147 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006148 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006149 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006150 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006151 if (ReturnType.isNull()) {
6152 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6153 Builder.AddTextChunk("NSUInteger");
6154 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6155 }
6156
6157 Builder.AddTypedTextChunk(
6158 Allocator.CopyString(SelectorId->getName()));
6159 Results.AddResult(Result(Builder.TakeString(),
6160 std::min(IndexedGetterPriority,
6161 UnorderedGetterPriority),
6162 CXCursor_ObjCInstanceMethodDecl));
6163 }
6164 }
6165
6166 // Indexed getters
6167 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6168 if (IsInstanceMethod &&
6169 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006170 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006171 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006172 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006173 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006174 if (ReturnType.isNull()) {
6175 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6176 Builder.AddTextChunk("id");
6177 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6178 }
6179
6180 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6181 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6182 Builder.AddTextChunk("NSUInteger");
6183 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6184 Builder.AddTextChunk("index");
6185 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6186 CXCursor_ObjCInstanceMethodDecl));
6187 }
6188 }
6189
6190 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6191 if (IsInstanceMethod &&
6192 (ReturnType.isNull() ||
6193 (ReturnType->isObjCObjectPointerType() &&
6194 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6195 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6196 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006197 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006198 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006199 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006200 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006201 if (ReturnType.isNull()) {
6202 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6203 Builder.AddTextChunk("NSArray *");
6204 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6205 }
6206
6207 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6208 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6209 Builder.AddTextChunk("NSIndexSet *");
6210 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6211 Builder.AddTextChunk("indexes");
6212 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6213 CXCursor_ObjCInstanceMethodDecl));
6214 }
6215 }
6216
6217 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6218 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006219 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006220 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006221 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006222 &Context.Idents.get("range")
6223 };
6224
Douglas Gregore74c25c2011-05-04 23:50:46 +00006225 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006226 if (ReturnType.isNull()) {
6227 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6228 Builder.AddTextChunk("void");
6229 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6230 }
6231
6232 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6233 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6234 Builder.AddPlaceholderChunk("object-type");
6235 Builder.AddTextChunk(" **");
6236 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6237 Builder.AddTextChunk("buffer");
6238 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6239 Builder.AddTypedTextChunk("range:");
6240 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6241 Builder.AddTextChunk("NSRange");
6242 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6243 Builder.AddTextChunk("inRange");
6244 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6245 CXCursor_ObjCInstanceMethodDecl));
6246 }
6247 }
6248
6249 // Mutable indexed accessors
6250
6251 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6252 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006253 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006254 IdentifierInfo *SelectorIds[2] = {
6255 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006256 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006257 };
6258
Douglas Gregore74c25c2011-05-04 23:50:46 +00006259 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006260 if (ReturnType.isNull()) {
6261 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6262 Builder.AddTextChunk("void");
6263 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6264 }
6265
6266 Builder.AddTypedTextChunk("insertObject:");
6267 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6268 Builder.AddPlaceholderChunk("object-type");
6269 Builder.AddTextChunk(" *");
6270 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6271 Builder.AddTextChunk("object");
6272 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6273 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6274 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6275 Builder.AddPlaceholderChunk("NSUInteger");
6276 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6277 Builder.AddTextChunk("index");
6278 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6279 CXCursor_ObjCInstanceMethodDecl));
6280 }
6281 }
6282
6283 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6284 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006285 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006286 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006287 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006288 &Context.Idents.get("atIndexes")
6289 };
6290
Douglas Gregore74c25c2011-05-04 23:50:46 +00006291 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006292 if (ReturnType.isNull()) {
6293 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6294 Builder.AddTextChunk("void");
6295 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6296 }
6297
6298 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6299 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6300 Builder.AddTextChunk("NSArray *");
6301 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6302 Builder.AddTextChunk("array");
6303 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6304 Builder.AddTypedTextChunk("atIndexes:");
6305 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6306 Builder.AddPlaceholderChunk("NSIndexSet *");
6307 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6308 Builder.AddTextChunk("indexes");
6309 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6310 CXCursor_ObjCInstanceMethodDecl));
6311 }
6312 }
6313
6314 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6315 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006316 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006317 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006318 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006319 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006320 if (ReturnType.isNull()) {
6321 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6322 Builder.AddTextChunk("void");
6323 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6324 }
6325
6326 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6327 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6328 Builder.AddTextChunk("NSUInteger");
6329 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6330 Builder.AddTextChunk("index");
6331 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6332 CXCursor_ObjCInstanceMethodDecl));
6333 }
6334 }
6335
6336 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6337 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006338 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006339 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006340 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006341 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006342 if (ReturnType.isNull()) {
6343 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6344 Builder.AddTextChunk("void");
6345 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6346 }
6347
6348 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6349 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6350 Builder.AddTextChunk("NSIndexSet *");
6351 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6352 Builder.AddTextChunk("indexes");
6353 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6354 CXCursor_ObjCInstanceMethodDecl));
6355 }
6356 }
6357
6358 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6359 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006360 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006361 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006362 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006363 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006364 &Context.Idents.get("withObject")
6365 };
6366
Douglas Gregore74c25c2011-05-04 23:50:46 +00006367 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006368 if (ReturnType.isNull()) {
6369 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6370 Builder.AddTextChunk("void");
6371 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6372 }
6373
6374 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6375 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6376 Builder.AddPlaceholderChunk("NSUInteger");
6377 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6378 Builder.AddTextChunk("index");
6379 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6380 Builder.AddTypedTextChunk("withObject:");
6381 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6382 Builder.AddTextChunk("id");
6383 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6384 Builder.AddTextChunk("object");
6385 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6386 CXCursor_ObjCInstanceMethodDecl));
6387 }
6388 }
6389
6390 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6391 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006392 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006393 = (Twine("replace") + UpperKey + "AtIndexes").str();
6394 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006395 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006396 &Context.Idents.get(SelectorName1),
6397 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006398 };
6399
Douglas Gregore74c25c2011-05-04 23:50:46 +00006400 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006401 if (ReturnType.isNull()) {
6402 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6403 Builder.AddTextChunk("void");
6404 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6405 }
6406
6407 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6408 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6409 Builder.AddPlaceholderChunk("NSIndexSet *");
6410 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6411 Builder.AddTextChunk("indexes");
6412 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6413 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6414 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6415 Builder.AddTextChunk("NSArray *");
6416 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6417 Builder.AddTextChunk("array");
6418 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6419 CXCursor_ObjCInstanceMethodDecl));
6420 }
6421 }
6422
6423 // Unordered getters
6424 // - (NSEnumerator *)enumeratorOfKey
6425 if (IsInstanceMethod &&
6426 (ReturnType.isNull() ||
6427 (ReturnType->isObjCObjectPointerType() &&
6428 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6429 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6430 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006431 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006432 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006433 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006434 if (ReturnType.isNull()) {
6435 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6436 Builder.AddTextChunk("NSEnumerator *");
6437 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6438 }
6439
6440 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6441 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6442 CXCursor_ObjCInstanceMethodDecl));
6443 }
6444 }
6445
6446 // - (type *)memberOfKey:(type *)object
6447 if (IsInstanceMethod &&
6448 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006449 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006450 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006451 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006452 if (ReturnType.isNull()) {
6453 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6454 Builder.AddPlaceholderChunk("object-type");
6455 Builder.AddTextChunk(" *");
6456 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6457 }
6458
6459 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6460 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6461 if (ReturnType.isNull()) {
6462 Builder.AddPlaceholderChunk("object-type");
6463 Builder.AddTextChunk(" *");
6464 } else {
6465 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006466 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006467 Builder.getAllocator()));
6468 }
6469 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6470 Builder.AddTextChunk("object");
6471 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6472 CXCursor_ObjCInstanceMethodDecl));
6473 }
6474 }
6475
6476 // Mutable unordered accessors
6477 // - (void)addKeyObject:(type *)object
6478 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006479 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006480 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006481 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006482 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006483 if (ReturnType.isNull()) {
6484 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6485 Builder.AddTextChunk("void");
6486 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6487 }
6488
6489 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6490 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6491 Builder.AddPlaceholderChunk("object-type");
6492 Builder.AddTextChunk(" *");
6493 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6494 Builder.AddTextChunk("object");
6495 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6496 CXCursor_ObjCInstanceMethodDecl));
6497 }
6498 }
6499
6500 // - (void)addKey:(NSSet *)objects
6501 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006502 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006503 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006504 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006505 if (ReturnType.isNull()) {
6506 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6507 Builder.AddTextChunk("void");
6508 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6509 }
6510
6511 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6512 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6513 Builder.AddTextChunk("NSSet *");
6514 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6515 Builder.AddTextChunk("objects");
6516 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6517 CXCursor_ObjCInstanceMethodDecl));
6518 }
6519 }
6520
6521 // - (void)removeKeyObject:(type *)object
6522 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006523 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006524 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006525 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006526 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006527 if (ReturnType.isNull()) {
6528 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6529 Builder.AddTextChunk("void");
6530 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6531 }
6532
6533 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6534 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6535 Builder.AddPlaceholderChunk("object-type");
6536 Builder.AddTextChunk(" *");
6537 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6538 Builder.AddTextChunk("object");
6539 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6540 CXCursor_ObjCInstanceMethodDecl));
6541 }
6542 }
6543
6544 // - (void)removeKey:(NSSet *)objects
6545 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006546 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006547 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006548 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006549 if (ReturnType.isNull()) {
6550 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6551 Builder.AddTextChunk("void");
6552 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6553 }
6554
6555 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6556 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6557 Builder.AddTextChunk("NSSet *");
6558 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6559 Builder.AddTextChunk("objects");
6560 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6561 CXCursor_ObjCInstanceMethodDecl));
6562 }
6563 }
6564
6565 // - (void)intersectKey:(NSSet *)objects
6566 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006567 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006568 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006569 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006570 if (ReturnType.isNull()) {
6571 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6572 Builder.AddTextChunk("void");
6573 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6574 }
6575
6576 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6577 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6578 Builder.AddTextChunk("NSSet *");
6579 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6580 Builder.AddTextChunk("objects");
6581 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6582 CXCursor_ObjCInstanceMethodDecl));
6583 }
6584 }
6585
6586 // Key-Value Observing
6587 // + (NSSet *)keyPathsForValuesAffectingKey
6588 if (!IsInstanceMethod &&
6589 (ReturnType.isNull() ||
6590 (ReturnType->isObjCObjectPointerType() &&
6591 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6592 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6593 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006594 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006595 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006596 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006597 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006598 if (ReturnType.isNull()) {
6599 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6600 Builder.AddTextChunk("NSSet *");
6601 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6602 }
6603
6604 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6605 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006606 CXCursor_ObjCClassMethodDecl));
6607 }
6608 }
6609
6610 // + (BOOL)automaticallyNotifiesObserversForKey
6611 if (!IsInstanceMethod &&
6612 (ReturnType.isNull() ||
6613 ReturnType->isIntegerType() ||
6614 ReturnType->isBooleanType())) {
6615 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006616 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006617 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6618 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6619 if (ReturnType.isNull()) {
6620 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6621 Builder.AddTextChunk("BOOL");
6622 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6623 }
6624
6625 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6626 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6627 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006628 }
6629 }
6630}
6631
Douglas Gregore8f5a172010-04-07 00:21:17 +00006632void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6633 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006634 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006635 // Determine the return type of the method we're declaring, if
6636 // provided.
6637 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006638 Decl *IDecl = 0;
6639 if (CurContext->isObjCContainer()) {
6640 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6641 IDecl = cast<Decl>(OCD);
6642 }
Douglas Gregorea766182010-10-18 18:21:28 +00006643 // Determine where we should start searching for methods.
6644 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006645 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006646 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006647 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6648 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006649 IsInImplementation = true;
6650 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006651 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006652 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006653 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006654 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006655 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006656 }
6657
6658 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006659 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006660 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006661 }
6662
Douglas Gregorea766182010-10-18 18:21:28 +00006663 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006664 HandleCodeCompleteResults(this, CodeCompleter,
6665 CodeCompletionContext::CCC_Other,
6666 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006667 return;
6668 }
6669
6670 // Find all of the methods that we could declare/implement here.
6671 KnownMethodsMap KnownMethods;
6672 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006673 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006674
Douglas Gregore8f5a172010-04-07 00:21:17 +00006675 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006676 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006677 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6678 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006679 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006680 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006681 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6682 MEnd = KnownMethods.end();
6683 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006684 ObjCMethodDecl *Method = M->second.first;
Douglas Gregor218937c2011-02-01 19:23:04 +00006685 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006686
6687 // If the result type was not already provided, add it to the
6688 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006689 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00006690 AddObjCPassingTypeChunk(Method->getResultType(), Context, Policy,
6691 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006692
6693 Selector Sel = Method->getSelector();
6694
6695 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006696 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006697 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006698
6699 // Add parameters to the pattern.
6700 unsigned I = 0;
6701 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6702 PEnd = Method->param_end();
6703 P != PEnd; (void)++P, ++I) {
6704 // Add the part of the selector name.
6705 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006706 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006707 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006708 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6709 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006710 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006711 } else
6712 break;
6713
6714 // Add the parameter type.
Douglas Gregor8987b232011-09-27 23:30:47 +00006715 AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Policy,
6716 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006717
6718 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006719 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006720 }
6721
6722 if (Method->isVariadic()) {
6723 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006724 Builder.AddChunk(CodeCompletionString::CK_Comma);
6725 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006726 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006727
Douglas Gregor447107d2010-05-28 00:57:46 +00006728 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006729 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006730 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6731 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6732 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006733 if (!Method->getResultType()->isVoidType()) {
6734 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006735 Builder.AddTextChunk("return");
6736 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6737 Builder.AddPlaceholderChunk("expression");
6738 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006739 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006740 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006741
Douglas Gregor218937c2011-02-01 19:23:04 +00006742 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6743 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006744 }
6745
Douglas Gregor408be5a2010-08-25 01:08:01 +00006746 unsigned Priority = CCP_CodePattern;
6747 if (!M->second.second)
6748 Priority += CCD_InBaseClass;
6749
Douglas Gregor218937c2011-02-01 19:23:04 +00006750 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor16ed9ad2010-08-17 16:06:07 +00006751 Method->isInstanceMethod()
6752 ? CXCursor_ObjCInstanceMethodDecl
6753 : CXCursor_ObjCClassMethodDecl));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006754 }
6755
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006756 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6757 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006758 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006759 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006760 Containers.push_back(SearchDecl);
6761
Douglas Gregore74c25c2011-05-04 23:50:46 +00006762 VisitedSelectorSet KnownSelectors;
6763 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6764 MEnd = KnownMethods.end();
6765 M != MEnd; ++M)
6766 KnownSelectors.insert(M->first);
6767
6768
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006769 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6770 if (!IFace)
6771 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6772 IFace = Category->getClassInterface();
6773
6774 if (IFace) {
6775 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6776 Category = Category->getNextClassCategory())
6777 Containers.push_back(Category);
6778 }
6779
6780 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6781 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6782 PEnd = Containers[I]->prop_end();
6783 P != PEnd; ++P) {
6784 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006785 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006786 }
6787 }
6788 }
6789
Douglas Gregore8f5a172010-04-07 00:21:17 +00006790 Results.ExitScope();
6791
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006792 HandleCodeCompleteResults(this, CodeCompleter,
6793 CodeCompletionContext::CCC_Other,
6794 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006795}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006796
6797void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6798 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006799 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006800 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006801 IdentifierInfo **SelIdents,
6802 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006803 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006804 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006805 if (ExternalSource) {
6806 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6807 I != N; ++I) {
6808 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006809 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006810 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006811
6812 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006813 }
6814 }
6815
6816 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006817 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006818 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6819 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006820
6821 if (ReturnTy)
6822 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006823
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006824 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006825 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6826 MEnd = MethodPool.end();
6827 M != MEnd; ++M) {
6828 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6829 &M->second.second;
6830 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006831 MethList = MethList->Next) {
6832 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6833 NumSelIdents))
6834 continue;
6835
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006836 if (AtParameterName) {
6837 // Suggest parameter names we've seen before.
6838 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6839 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6840 if (Param->getIdentifier()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006841 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregordae68752011-02-01 22:57:45 +00006842 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006843 Param->getIdentifier()->getName()));
6844 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006845 }
6846 }
6847
6848 continue;
6849 }
6850
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006851 Result R(MethList->Method, 0);
6852 R.StartParameter = NumSelIdents;
6853 R.AllParametersAreInformative = false;
6854 R.DeclaringEntity = true;
6855 Results.MaybeAddResult(R, CurContext);
6856 }
6857 }
6858
6859 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006860 HandleCodeCompleteResults(this, CodeCompleter,
6861 CodeCompletionContext::CCC_Other,
6862 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006863}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006864
Douglas Gregorf29c5232010-08-24 22:20:20 +00006865void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006866 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006867 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006868 Results.EnterNewScope();
6869
6870 // #if <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006871 CodeCompletionBuilder Builder(Results.getAllocator());
6872 Builder.AddTypedTextChunk("if");
6873 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6874 Builder.AddPlaceholderChunk("condition");
6875 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006876
6877 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006878 Builder.AddTypedTextChunk("ifdef");
6879 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6880 Builder.AddPlaceholderChunk("macro");
6881 Results.AddResult(Builder.TakeString());
6882
Douglas Gregorf44e8542010-08-24 19:08:16 +00006883 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006884 Builder.AddTypedTextChunk("ifndef");
6885 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6886 Builder.AddPlaceholderChunk("macro");
6887 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006888
6889 if (InConditional) {
6890 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006891 Builder.AddTypedTextChunk("elif");
6892 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6893 Builder.AddPlaceholderChunk("condition");
6894 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006895
6896 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00006897 Builder.AddTypedTextChunk("else");
6898 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006899
6900 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00006901 Builder.AddTypedTextChunk("endif");
6902 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006903 }
6904
6905 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006906 Builder.AddTypedTextChunk("include");
6907 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6908 Builder.AddTextChunk("\"");
6909 Builder.AddPlaceholderChunk("header");
6910 Builder.AddTextChunk("\"");
6911 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006912
6913 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006914 Builder.AddTypedTextChunk("include");
6915 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6916 Builder.AddTextChunk("<");
6917 Builder.AddPlaceholderChunk("header");
6918 Builder.AddTextChunk(">");
6919 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006920
6921 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006922 Builder.AddTypedTextChunk("define");
6923 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6924 Builder.AddPlaceholderChunk("macro");
6925 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006926
6927 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00006928 Builder.AddTypedTextChunk("define");
6929 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6930 Builder.AddPlaceholderChunk("macro");
6931 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6932 Builder.AddPlaceholderChunk("args");
6933 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6934 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006935
6936 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006937 Builder.AddTypedTextChunk("undef");
6938 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6939 Builder.AddPlaceholderChunk("macro");
6940 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006941
6942 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00006943 Builder.AddTypedTextChunk("line");
6944 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6945 Builder.AddPlaceholderChunk("number");
6946 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006947
6948 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00006949 Builder.AddTypedTextChunk("line");
6950 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6951 Builder.AddPlaceholderChunk("number");
6952 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6953 Builder.AddTextChunk("\"");
6954 Builder.AddPlaceholderChunk("filename");
6955 Builder.AddTextChunk("\"");
6956 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006957
6958 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006959 Builder.AddTypedTextChunk("error");
6960 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6961 Builder.AddPlaceholderChunk("message");
6962 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006963
6964 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00006965 Builder.AddTypedTextChunk("pragma");
6966 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6967 Builder.AddPlaceholderChunk("arguments");
6968 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006969
David Blaikie4e4d0842012-03-11 07:00:24 +00006970 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00006971 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006972 Builder.AddTypedTextChunk("import");
6973 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6974 Builder.AddTextChunk("\"");
6975 Builder.AddPlaceholderChunk("header");
6976 Builder.AddTextChunk("\"");
6977 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006978
6979 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006980 Builder.AddTypedTextChunk("import");
6981 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6982 Builder.AddTextChunk("<");
6983 Builder.AddPlaceholderChunk("header");
6984 Builder.AddTextChunk(">");
6985 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006986 }
6987
6988 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006989 Builder.AddTypedTextChunk("include_next");
6990 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6991 Builder.AddTextChunk("\"");
6992 Builder.AddPlaceholderChunk("header");
6993 Builder.AddTextChunk("\"");
6994 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006995
6996 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006997 Builder.AddTypedTextChunk("include_next");
6998 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6999 Builder.AddTextChunk("<");
7000 Builder.AddPlaceholderChunk("header");
7001 Builder.AddTextChunk(">");
7002 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007003
7004 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007005 Builder.AddTypedTextChunk("warning");
7006 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7007 Builder.AddPlaceholderChunk("message");
7008 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007009
7010 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7011 // completions for them. And __include_macros is a Clang-internal extension
7012 // that we don't want to encourage anyone to use.
7013
7014 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7015 Results.ExitScope();
7016
Douglas Gregorf44e8542010-08-24 19:08:16 +00007017 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00007018 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00007019 Results.data(), Results.size());
7020}
7021
7022void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007023 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007024 S->getFnParent()? Sema::PCC_RecoveryInFunction
7025 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007026}
7027
Douglas Gregorf29c5232010-08-24 22:20:20 +00007028void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007029 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007030 IsDefinition? CodeCompletionContext::CCC_MacroName
7031 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007032 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7033 // Add just the names of macros, not their arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00007034 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007035 Results.EnterNewScope();
7036 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7037 MEnd = PP.macro_end();
7038 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007039 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007040 M->first->getName()));
7041 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007042 }
7043 Results.ExitScope();
7044 } else if (IsDefinition) {
7045 // FIXME: Can we detect when the user just wrote an include guard above?
7046 }
7047
Douglas Gregor52779fb2010-09-23 23:01:17 +00007048 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007049 Results.data(), Results.size());
7050}
7051
Douglas Gregorf29c5232010-08-24 22:20:20 +00007052void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007053 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007054 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007055
7056 if (!CodeCompleter || CodeCompleter->includeMacros())
7057 AddMacroResults(PP, Results);
7058
7059 // defined (<macro>)
7060 Results.EnterNewScope();
Douglas Gregor218937c2011-02-01 19:23:04 +00007061 CodeCompletionBuilder Builder(Results.getAllocator());
7062 Builder.AddTypedTextChunk("defined");
7063 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7064 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7065 Builder.AddPlaceholderChunk("macro");
7066 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7067 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007068 Results.ExitScope();
7069
7070 HandleCodeCompleteResults(this, CodeCompleter,
7071 CodeCompletionContext::CCC_PreprocessorExpression,
7072 Results.data(), Results.size());
7073}
7074
7075void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7076 IdentifierInfo *Macro,
7077 MacroInfo *MacroInfo,
7078 unsigned Argument) {
7079 // FIXME: In the future, we could provide "overload" results, much like we
7080 // do for function calls.
7081
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007082 // Now just ignore this. There will be another code-completion callback
7083 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007084}
7085
Douglas Gregor55817af2010-08-25 17:04:25 +00007086void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007087 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007088 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007089 0, 0);
7090}
7091
Douglas Gregordae68752011-02-01 22:57:45 +00007092void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007093 SmallVectorImpl<CodeCompletionResult> &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007094 ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007095 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7096 CodeCompletionDeclConsumer Consumer(Builder,
7097 Context.getTranslationUnitDecl());
7098 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7099 Consumer);
7100 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007101
7102 if (!CodeCompleter || CodeCompleter->includeMacros())
7103 AddMacroResults(PP, Builder);
7104
7105 Results.clear();
7106 Results.insert(Results.end(),
7107 Builder.data(), Builder.data() + Builder.size());
7108}