blob: 0d5413a936b6512cc769dbf9ea91d4e789cf6851 [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"
Douglas Gregor6a684032009-09-28 03:51:44 +000029#include "llvm/ADT/StringExtras.h"
Douglas Gregor22f56992010-04-06 19:22:33 +000030#include "llvm/ADT/StringSwitch.h"
Douglas Gregor458433d2010-08-26 15:07:07 +000031#include "llvm/ADT/Twine.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000032#include <list>
33#include <map>
34#include <vector>
Douglas Gregor81b747b2009-09-17 21:32:03 +000035
36using namespace clang;
John McCall781472f2010-08-25 08:40:02 +000037using namespace sema;
Douglas Gregor81b747b2009-09-17 21:32:03 +000038
Douglas Gregor86d9a522009-09-21 16:56:56 +000039namespace {
40 /// \brief A container of code-completion results.
41 class ResultBuilder {
42 public:
43 /// \brief The type of a name-lookup filter, which can be provided to the
44 /// name-lookup routines to specify which declarations should be included in
45 /// the result set (when it returns true) and which declarations should be
46 /// filtered out (returns false).
47 typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
48
John McCall0a2c5e22010-08-25 06:19:51 +000049 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +000050
51 private:
52 /// \brief The actual results we have found.
53 std::vector<Result> Results;
54
55 /// \brief A record of all of the declarations we have found and placed
56 /// into the result set, used to ensure that no declaration ever gets into
57 /// the result set twice.
58 llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
59
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000060 typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
61
62 /// \brief An entry in the shadow map, which is optimized to store
63 /// a single (declaration, index) mapping (the common case) but
64 /// can also store a list of (declaration, index) mappings.
65 class ShadowMapEntry {
Chris Lattner5f9e2722011-07-23 10:55:15 +000066 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000067
68 /// \brief Contains either the solitary NamedDecl * or a vector
69 /// of (declaration, index) pairs.
70 llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
71
72 /// \brief When the entry contains a single declaration, this is
73 /// the index associated with that entry.
74 unsigned SingleDeclIndex;
75
76 public:
77 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
78
79 void Add(NamedDecl *ND, unsigned Index) {
80 if (DeclOrVector.isNull()) {
81 // 0 - > 1 elements: just set the single element information.
82 DeclOrVector = ND;
83 SingleDeclIndex = Index;
84 return;
85 }
86
87 if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
88 // 1 -> 2 elements: create the vector of results and push in the
89 // existing declaration.
90 DeclIndexPairVector *Vec = new DeclIndexPairVector;
91 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
92 DeclOrVector = Vec;
93 }
94
95 // Add the new element to the end of the vector.
96 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
97 DeclIndexPair(ND, Index));
98 }
99
100 void Destroy() {
101 if (DeclIndexPairVector *Vec
102 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
103 delete Vec;
104 DeclOrVector = ((NamedDecl *)0);
105 }
106 }
107
108 // Iteration.
109 class iterator;
110 iterator begin() const;
111 iterator end() const;
112 };
113
Douglas Gregor86d9a522009-09-21 16:56:56 +0000114 /// \brief A mapping from declaration names to the declarations that have
115 /// this name within a particular scope and their index within the list of
116 /// results.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000117 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000118
119 /// \brief The semantic analysis object for which results are being
120 /// produced.
121 Sema &SemaRef;
Douglas Gregor218937c2011-02-01 19:23:04 +0000122
123 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000124 CodeCompletionAllocator &Allocator;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000125
126 /// \brief If non-NULL, a filter function used to remove any code-completion
127 /// results that are not desirable.
128 LookupFilter Filter;
Douglas Gregor45bcd432010-01-14 03:21:49 +0000129
130 /// \brief Whether we should allow declarations as
131 /// nested-name-specifiers that would otherwise be filtered out.
132 bool AllowNestedNameSpecifiers;
133
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000134 /// \brief If set, the type that we would prefer our resulting value
135 /// declarations to have.
136 ///
137 /// Closely matching the preferred type gives a boost to a result's
138 /// priority.
139 CanQualType PreferredType;
140
Douglas Gregor86d9a522009-09-21 16:56:56 +0000141 /// \brief A list of shadow maps, which is used to model name hiding at
142 /// different levels of, e.g., the inheritance hierarchy.
143 std::list<ShadowMap> ShadowMaps;
144
Douglas Gregor3cdee122010-08-26 16:36:48 +0000145 /// \brief If we're potentially referring to a C++ member function, the set
146 /// of qualifiers applied to the object type.
147 Qualifiers ObjectTypeQualifiers;
148
149 /// \brief Whether the \p ObjectTypeQualifiers field is active.
150 bool HasObjectTypeQualifiers;
151
Douglas Gregor265f7492010-08-27 15:29:55 +0000152 /// \brief The selector that we prefer.
153 Selector PreferredSelector;
154
Douglas Gregorca45da02010-11-02 20:36:02 +0000155 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000156 CodeCompletionContext CompletionContext;
157
Douglas Gregorca45da02010-11-02 20:36:02 +0000158 /// \brief If we are in an instance method definition, the @implementation
159 /// object.
160 ObjCImplementationDecl *ObjCImplementation;
161
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000162 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000163
Douglas Gregor6f942b22010-09-21 16:06:22 +0000164 void MaybeAddConstructorResults(Result R);
165
Douglas Gregor86d9a522009-09-21 16:56:56 +0000166 public:
Douglas Gregordae68752011-02-01 22:57:45 +0000167 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000168 const CodeCompletionContext &CompletionContext,
169 LookupFilter Filter = 0)
Douglas Gregor218937c2011-02-01 19:23:04 +0000170 : SemaRef(SemaRef), Allocator(Allocator), Filter(Filter),
171 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-11-02 20:36:02 +0000172 CompletionContext(CompletionContext),
173 ObjCImplementation(0)
174 {
175 // If this is an Objective-C instance method definition, dig out the
176 // corresponding implementation.
177 switch (CompletionContext.getKind()) {
178 case CodeCompletionContext::CCC_Expression:
179 case CodeCompletionContext::CCC_ObjCMessageReceiver:
180 case CodeCompletionContext::CCC_ParenthesizedExpression:
181 case CodeCompletionContext::CCC_Statement:
182 case CodeCompletionContext::CCC_Recovery:
183 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
184 if (Method->isInstanceMethod())
185 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
186 ObjCImplementation = Interface->getImplementation();
187 break;
188
189 default:
190 break;
191 }
192 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000193
Douglas Gregord8e8a582010-05-25 21:41:55 +0000194 /// \brief Whether we should include code patterns in the completion
195 /// results.
196 bool includeCodePatterns() const {
197 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000198 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000199 }
200
Douglas Gregor86d9a522009-09-21 16:56:56 +0000201 /// \brief Set the filter used for code-completion results.
202 void setFilter(LookupFilter Filter) {
203 this->Filter = Filter;
204 }
205
Douglas Gregor86d9a522009-09-21 16:56:56 +0000206 Result *data() { return Results.empty()? 0 : &Results.front(); }
207 unsigned size() const { return Results.size(); }
208 bool empty() const { return Results.empty(); }
209
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000210 /// \brief Specify the preferred type.
211 void setPreferredType(QualType T) {
212 PreferredType = SemaRef.Context.getCanonicalType(T);
213 }
214
Douglas Gregor3cdee122010-08-26 16:36:48 +0000215 /// \brief Set the cv-qualifiers on the object type, for us in filtering
216 /// calls to member functions.
217 ///
218 /// When there are qualifiers in this set, they will be used to filter
219 /// out member functions that aren't available (because there will be a
220 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
221 /// match.
222 void setObjectTypeQualifiers(Qualifiers Quals) {
223 ObjectTypeQualifiers = Quals;
224 HasObjectTypeQualifiers = true;
225 }
226
Douglas Gregor265f7492010-08-27 15:29:55 +0000227 /// \brief Set the preferred selector.
228 ///
229 /// When an Objective-C method declaration result is added, and that
230 /// method's selector matches this preferred selector, we give that method
231 /// a slight priority boost.
232 void setPreferredSelector(Selector Sel) {
233 PreferredSelector = Sel;
234 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000235
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000236 /// \brief Retrieve the code-completion context for which results are
237 /// being collected.
238 const CodeCompletionContext &getCompletionContext() const {
239 return CompletionContext;
240 }
241
Douglas Gregor45bcd432010-01-14 03:21:49 +0000242 /// \brief Specify whether nested-name-specifiers are allowed.
243 void allowNestedNameSpecifiers(bool Allow = true) {
244 AllowNestedNameSpecifiers = Allow;
245 }
246
Douglas Gregorb9d77572010-09-21 00:03:25 +0000247 /// \brief Return the semantic analysis object for which we are collecting
248 /// code completion results.
249 Sema &getSema() const { return SemaRef; }
250
Douglas Gregor218937c2011-02-01 19:23:04 +0000251 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000252 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Douglas Gregor218937c2011-02-01 19:23:04 +0000253
Douglas Gregore495b7f2010-01-14 00:20:49 +0000254 /// \brief Determine whether the given declaration is at all interesting
255 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000256 ///
257 /// \param ND the declaration that we are inspecting.
258 ///
259 /// \param AsNestedNameSpecifier will be set true if this declaration is
260 /// only interesting when it is a nested-name-specifier.
261 bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000262
263 /// \brief Check whether the result is hidden by the Hiding declaration.
264 ///
265 /// \returns true if the result is hidden and cannot be found, false if
266 /// the hidden result could still be found. When false, \p R may be
267 /// modified to describe how the result can be found (e.g., via extra
268 /// qualification).
269 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
270 NamedDecl *Hiding);
271
Douglas Gregor86d9a522009-09-21 16:56:56 +0000272 /// \brief Add a new result to this result set (if it isn't already in one
273 /// of the shadow maps), or replace an existing result (for, e.g., a
274 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000275 ///
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000276 /// \param CurContext the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000277 ///
278 /// \param R the context in which this result will be named.
279 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000280
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000281 /// \brief Add a new result to this result set, where we already know
282 /// the hiding declation (if any).
283 ///
284 /// \param R the result to add (if it is unique).
285 ///
286 /// \param CurContext the context in which this result will be named.
287 ///
288 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000289 ///
290 /// \param InBaseClass whether the result was found in a base
291 /// class of the searched context.
292 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
293 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000294
Douglas Gregora4477812010-01-14 16:01:26 +0000295 /// \brief Add a new non-declaration result to this result set.
296 void AddResult(Result R);
297
Douglas Gregor86d9a522009-09-21 16:56:56 +0000298 /// \brief Enter into a new scope.
299 void EnterNewScope();
300
301 /// \brief Exit from the current scope.
302 void ExitScope();
303
Douglas Gregor55385fe2009-11-18 04:19:12 +0000304 /// \brief Ignore this declaration, if it is seen again.
305 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
306
Douglas Gregor86d9a522009-09-21 16:56:56 +0000307 /// \name Name lookup predicates
308 ///
309 /// These predicates can be passed to the name lookup functions to filter the
310 /// results of name lookup. All of the predicates have the same type, so that
311 ///
312 //@{
Douglas Gregor791215b2009-09-21 20:51:25 +0000313 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000314 bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
Douglas Gregorf9578432010-07-28 21:50:18 +0000315 bool IsIntegralConstantValue(NamedDecl *ND) const;
Douglas Gregor01dfea02010-01-10 23:08:15 +0000316 bool IsOrdinaryNonValueName(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000317 bool IsNestedNameSpecifier(NamedDecl *ND) const;
318 bool IsEnum(NamedDecl *ND) const;
319 bool IsClassOrStruct(NamedDecl *ND) const;
320 bool IsUnion(NamedDecl *ND) const;
321 bool IsNamespace(NamedDecl *ND) const;
322 bool IsNamespaceOrAlias(NamedDecl *ND) const;
323 bool IsType(NamedDecl *ND) const;
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000324 bool IsMember(NamedDecl *ND) const;
Douglas Gregor80f4f4c2010-01-14 16:08:12 +0000325 bool IsObjCIvar(NamedDecl *ND) const;
Douglas Gregor8e254cf2010-05-27 23:06:34 +0000326 bool IsObjCMessageReceiver(NamedDecl *ND) const;
Douglas Gregorfb629412010-08-23 21:17:50 +0000327 bool IsObjCCollection(NamedDecl *ND) const;
Douglas Gregor52779fb2010-09-23 23:01:17 +0000328 bool IsImpossibleToSatisfy(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000329 //@}
330 };
331}
332
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000333class ResultBuilder::ShadowMapEntry::iterator {
334 llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
335 unsigned SingleDeclIndex;
336
337public:
338 typedef DeclIndexPair value_type;
339 typedef value_type reference;
340 typedef std::ptrdiff_t difference_type;
341 typedef std::input_iterator_tag iterator_category;
342
343 class pointer {
344 DeclIndexPair Value;
345
346 public:
347 pointer(const DeclIndexPair &Value) : Value(Value) { }
348
349 const DeclIndexPair *operator->() const {
350 return &Value;
351 }
352 };
353
354 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
355
356 iterator(NamedDecl *SingleDecl, unsigned Index)
357 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
358
359 iterator(const DeclIndexPair *Iterator)
360 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
361
362 iterator &operator++() {
363 if (DeclOrIterator.is<NamedDecl *>()) {
364 DeclOrIterator = (NamedDecl *)0;
365 SingleDeclIndex = 0;
366 return *this;
367 }
368
369 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
370 ++I;
371 DeclOrIterator = I;
372 return *this;
373 }
374
Chris Lattner66392d42010-09-04 18:12:20 +0000375 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000376 iterator tmp(*this);
377 ++(*this);
378 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000379 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000380
381 reference operator*() const {
382 if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
383 return reference(ND, SingleDeclIndex);
384
Douglas Gregord490f952009-12-06 21:27:58 +0000385 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000386 }
387
388 pointer operator->() const {
389 return pointer(**this);
390 }
391
392 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000393 return X.DeclOrIterator.getOpaqueValue()
394 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000395 X.SingleDeclIndex == Y.SingleDeclIndex;
396 }
397
398 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000399 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000400 }
401};
402
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000403ResultBuilder::ShadowMapEntry::iterator
404ResultBuilder::ShadowMapEntry::begin() const {
405 if (DeclOrVector.isNull())
406 return iterator();
407
408 if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
409 return iterator(ND, SingleDeclIndex);
410
411 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
412}
413
414ResultBuilder::ShadowMapEntry::iterator
415ResultBuilder::ShadowMapEntry::end() const {
416 if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
417 return iterator();
418
419 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
420}
421
Douglas Gregor456c4a12009-09-21 20:12:40 +0000422/// \brief Compute the qualification required to get from the current context
423/// (\p CurContext) to the target context (\p TargetContext).
424///
425/// \param Context the AST context in which the qualification will be used.
426///
427/// \param CurContext the context where an entity is being named, which is
428/// typically based on the current scope.
429///
430/// \param TargetContext the context in which the named entity actually
431/// resides.
432///
433/// \returns a nested name specifier that refers into the target context, or
434/// NULL if no qualification is needed.
435static NestedNameSpecifier *
436getRequiredQualification(ASTContext &Context,
437 DeclContext *CurContext,
438 DeclContext *TargetContext) {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000439 SmallVector<DeclContext *, 4> TargetParents;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000440
441 for (DeclContext *CommonAncestor = TargetContext;
442 CommonAncestor && !CommonAncestor->Encloses(CurContext);
443 CommonAncestor = CommonAncestor->getLookupParent()) {
444 if (CommonAncestor->isTransparentContext() ||
445 CommonAncestor->isFunctionOrMethod())
446 continue;
447
448 TargetParents.push_back(CommonAncestor);
449 }
450
451 NestedNameSpecifier *Result = 0;
452 while (!TargetParents.empty()) {
453 DeclContext *Parent = TargetParents.back();
454 TargetParents.pop_back();
455
Douglas Gregorfb629412010-08-23 21:17:50 +0000456 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
457 if (!Namespace->getIdentifier())
458 continue;
459
Douglas Gregor456c4a12009-09-21 20:12:40 +0000460 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000461 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000462 else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
463 Result = NestedNameSpecifier::Create(Context, Result,
464 false,
465 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000466 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000467 return Result;
468}
469
Douglas Gregor45bcd432010-01-14 03:21:49 +0000470bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
471 bool &AsNestedNameSpecifier) const {
472 AsNestedNameSpecifier = false;
473
Douglas Gregore495b7f2010-01-14 00:20:49 +0000474 ND = ND->getUnderlyingDecl();
475 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000476
477 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000478 if (!ND->getDeclName())
479 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000480
481 // Friend declarations and declarations introduced due to friends are never
482 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000483 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000484 return false;
485
Douglas Gregor76282942009-12-11 17:31:05 +0000486 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000487 if (isa<ClassTemplateSpecializationDecl>(ND) ||
488 isa<ClassTemplatePartialSpecializationDecl>(ND))
489 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000490
Douglas Gregor76282942009-12-11 17:31:05 +0000491 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000492 if (isa<UsingDecl>(ND))
493 return false;
494
495 // Some declarations have reserved names that we don't want to ever show.
496 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000497 // __va_list_tag is a freak of nature. Find it and skip it.
498 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000499 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000500
Douglas Gregorf52cede2009-10-09 22:16:47 +0000501 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000502 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000503 //
504 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000505 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000506 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000507 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000508 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
509 (ND->getLocation().isInvalid() ||
510 SemaRef.SourceMgr.isInSystemHeader(
511 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000512 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000513 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000514 }
Douglas Gregor6f942b22010-09-21 16:06:22 +0000515
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000516 // Skip out-of-line declarations and definitions.
517 // NOTE: Unless it's an Objective-C property, method, or ivar, where
518 // the contexts can be messy.
519 if (!ND->getDeclContext()->Equals(ND->getLexicalDeclContext()) &&
520 !(isa<ObjCPropertyDecl>(ND) || isa<ObjCIvarDecl>(ND) ||
521 isa<ObjCMethodDecl>(ND)))
522 return false;
523
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000524 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
525 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
526 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000527 Filter != &ResultBuilder::IsNamespaceOrAlias &&
528 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000529 AsNestedNameSpecifier = true;
530
Douglas Gregor86d9a522009-09-21 16:56:56 +0000531 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000532 if (Filter && !(this->*Filter)(ND)) {
533 // Check whether it is interesting as a nested-name-specifier.
534 if (AllowNestedNameSpecifiers && SemaRef.getLangOptions().CPlusPlus &&
535 IsNestedNameSpecifier(ND) &&
536 (Filter != &ResultBuilder::IsMember ||
537 (isa<CXXRecordDecl>(ND) &&
538 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
539 AsNestedNameSpecifier = true;
540 return true;
541 }
542
Douglas Gregore495b7f2010-01-14 00:20:49 +0000543 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000544 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000545 // ... then it must be interesting!
546 return true;
547}
548
Douglas Gregor6660d842010-01-14 00:41:07 +0000549bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
550 NamedDecl *Hiding) {
551 // In C, there is no way to refer to a hidden name.
552 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
553 // name if we introduce the tag type.
554 if (!SemaRef.getLangOptions().CPlusPlus)
555 return true;
556
Sebastian Redl7a126a42010-08-31 00:36:30 +0000557 DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000558
559 // There is no way to qualify a name declared in a function or method.
560 if (HiddenCtx->isFunctionOrMethod())
561 return true;
562
Sebastian Redl7a126a42010-08-31 00:36:30 +0000563 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000564 return true;
565
566 // We can refer to the result with the appropriate qualification. Do it.
567 R.Hidden = true;
568 R.QualifierIsInformative = false;
569
570 if (!R.Qualifier)
571 R.Qualifier = getRequiredQualification(SemaRef.Context,
572 CurContext,
573 R.Declaration->getDeclContext());
574 return false;
575}
576
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000577/// \brief A simplified classification of types used to determine whether two
578/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000579SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000580 switch (T->getTypeClass()) {
581 case Type::Builtin:
582 switch (cast<BuiltinType>(T)->getKind()) {
583 case BuiltinType::Void:
584 return STC_Void;
585
586 case BuiltinType::NullPtr:
587 return STC_Pointer;
588
589 case BuiltinType::Overload:
590 case BuiltinType::Dependent:
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000591 return STC_Other;
592
593 case BuiltinType::ObjCId:
594 case BuiltinType::ObjCClass:
595 case BuiltinType::ObjCSel:
596 return STC_ObjectiveC;
597
598 default:
599 return STC_Arithmetic;
600 }
David Blaikie7530c032012-01-17 06:56:22 +0000601
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000602 case Type::Complex:
603 return STC_Arithmetic;
604
605 case Type::Pointer:
606 return STC_Pointer;
607
608 case Type::BlockPointer:
609 return STC_Block;
610
611 case Type::LValueReference:
612 case Type::RValueReference:
613 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
614
615 case Type::ConstantArray:
616 case Type::IncompleteArray:
617 case Type::VariableArray:
618 case Type::DependentSizedArray:
619 return STC_Array;
620
621 case Type::DependentSizedExtVector:
622 case Type::Vector:
623 case Type::ExtVector:
624 return STC_Arithmetic;
625
626 case Type::FunctionProto:
627 case Type::FunctionNoProto:
628 return STC_Function;
629
630 case Type::Record:
631 return STC_Record;
632
633 case Type::Enum:
634 return STC_Arithmetic;
635
636 case Type::ObjCObject:
637 case Type::ObjCInterface:
638 case Type::ObjCObjectPointer:
639 return STC_ObjectiveC;
640
641 default:
642 return STC_Other;
643 }
644}
645
646/// \brief Get the type that a given expression will have if this declaration
647/// is used as an expression in its "typical" code-completion form.
Douglas Gregor1827e102010-08-16 16:18:59 +0000648QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000649 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
650
651 if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
652 return C.getTypeDeclType(Type);
653 if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
654 return C.getObjCInterfaceType(Iface);
655
656 QualType T;
657 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000658 T = Function->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000659 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000660 T = Method->getSendResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000661 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000662 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000663 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
664 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
665 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
666 T = Property->getType();
667 else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
668 T = Value->getType();
669 else
670 return QualType();
Douglas Gregor3e64d562011-04-14 20:33:34 +0000671
672 // Dig through references, function pointers, and block pointers to
673 // get down to the likely type of an expression when the entity is
674 // used.
675 do {
676 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
677 T = Ref->getPointeeType();
678 continue;
679 }
680
681 if (const PointerType *Pointer = T->getAs<PointerType>()) {
682 if (Pointer->getPointeeType()->isFunctionType()) {
683 T = Pointer->getPointeeType();
684 continue;
685 }
686
687 break;
688 }
689
690 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
691 T = Block->getPointeeType();
692 continue;
693 }
694
695 if (const FunctionType *Function = T->getAs<FunctionType>()) {
696 T = Function->getResultType();
697 continue;
698 }
699
700 break;
701 } while (true);
702
703 return T;
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000704}
705
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000706void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
707 // If this is an Objective-C method declaration whose selector matches our
708 // preferred selector, give it a priority boost.
709 if (!PreferredSelector.isNull())
710 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
711 if (PreferredSelector == Method->getSelector())
712 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000713
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000714 // If we have a preferred type, adjust the priority for results with exactly-
715 // matching or nearly-matching types.
716 if (!PreferredType.isNull()) {
717 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
718 if (!T.isNull()) {
719 CanQualType TC = SemaRef.Context.getCanonicalType(T);
720 // Check for exactly-matching types (modulo qualifiers).
721 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
722 R.Priority /= CCF_ExactTypeMatch;
723 // Check for nearly-matching types, based on classification of each.
724 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000725 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000726 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
727 R.Priority /= CCF_SimilarTypeMatch;
728 }
729 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000730}
731
Douglas Gregor6f942b22010-09-21 16:06:22 +0000732void ResultBuilder::MaybeAddConstructorResults(Result R) {
733 if (!SemaRef.getLangOptions().CPlusPlus || !R.Declaration ||
734 !CompletionContext.wantConstructorResults())
735 return;
736
737 ASTContext &Context = SemaRef.Context;
738 NamedDecl *D = R.Declaration;
739 CXXRecordDecl *Record = 0;
740 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
741 Record = ClassTemplate->getTemplatedDecl();
742 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
743 // Skip specializations and partial specializations.
744 if (isa<ClassTemplateSpecializationDecl>(Record))
745 return;
746 } else {
747 // There are no constructors here.
748 return;
749 }
750
751 Record = Record->getDefinition();
752 if (!Record)
753 return;
754
755
756 QualType RecordTy = Context.getTypeDeclType(Record);
757 DeclarationName ConstructorName
758 = Context.DeclarationNames.getCXXConstructorName(
759 Context.getCanonicalType(RecordTy));
760 for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
761 Ctors.first != Ctors.second; ++Ctors.first) {
762 R.Declaration = *Ctors.first;
763 R.CursorKind = getCursorKindForDecl(R.Declaration);
764 Results.push_back(R);
765 }
766}
767
Douglas Gregore495b7f2010-01-14 00:20:49 +0000768void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
769 assert(!ShadowMaps.empty() && "Must enter into a results scope");
770
771 if (R.Kind != Result::RK_Declaration) {
772 // For non-declaration results, just add the result.
773 Results.push_back(R);
774 return;
775 }
776
777 // Look through using declarations.
778 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
779 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
780 return;
781 }
782
783 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
784 unsigned IDNS = CanonDecl->getIdentifierNamespace();
785
Douglas Gregor45bcd432010-01-14 03:21:49 +0000786 bool AsNestedNameSpecifier = false;
787 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000788 return;
789
Douglas Gregor6f942b22010-09-21 16:06:22 +0000790 // C++ constructors are never found by name lookup.
791 if (isa<CXXConstructorDecl>(R.Declaration))
792 return;
793
Douglas Gregor86d9a522009-09-21 16:56:56 +0000794 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000795 ShadowMapEntry::iterator I, IEnd;
796 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
797 if (NamePos != SMap.end()) {
798 I = NamePos->second.begin();
799 IEnd = NamePos->second.end();
800 }
801
802 for (; I != IEnd; ++I) {
803 NamedDecl *ND = I->first;
804 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000805 if (ND->getCanonicalDecl() == CanonDecl) {
806 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000807 Results[Index].Declaration = R.Declaration;
808
Douglas Gregor86d9a522009-09-21 16:56:56 +0000809 // We're done.
810 return;
811 }
812 }
813
814 // This is a new declaration in this scope. However, check whether this
815 // declaration name is hidden by a similarly-named declaration in an outer
816 // scope.
817 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
818 --SMEnd;
819 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000820 ShadowMapEntry::iterator I, IEnd;
821 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
822 if (NamePos != SM->end()) {
823 I = NamePos->second.begin();
824 IEnd = NamePos->second.end();
825 }
826 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000827 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000828 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000829 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
830 Decl::IDNS_ObjCProtocol)))
831 continue;
832
833 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000834 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000835 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000836 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000837 continue;
838
839 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000840 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000841 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000842
843 break;
844 }
845 }
846
847 // Make sure that any given declaration only shows up in the result set once.
848 if (!AllDeclsFound.insert(CanonDecl))
849 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000850
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000851 // If the filter is for nested-name-specifiers, then this result starts a
852 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000853 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000854 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000855 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000856 } else
857 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000858
Douglas Gregor0563c262009-09-22 23:15:58 +0000859 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000860 if (R.QualifierIsInformative && !R.Qualifier &&
861 !R.StartsNestedNameSpecifier) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000862 DeclContext *Ctx = R.Declaration->getDeclContext();
863 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
864 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
865 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
866 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
867 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
868 else
869 R.QualifierIsInformative = false;
870 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000871
Douglas Gregor86d9a522009-09-21 16:56:56 +0000872 // Insert this result into the set of results and into the current shadow
873 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000874 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000875 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000876
877 if (!AsNestedNameSpecifier)
878 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000879}
880
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000881void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000882 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000883 if (R.Kind != Result::RK_Declaration) {
884 // For non-declaration results, just add the result.
885 Results.push_back(R);
886 return;
887 }
888
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000889 // Look through using declarations.
890 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
891 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
892 return;
893 }
894
Douglas Gregor45bcd432010-01-14 03:21:49 +0000895 bool AsNestedNameSpecifier = false;
896 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000897 return;
898
Douglas Gregor6f942b22010-09-21 16:06:22 +0000899 // C++ constructors are never found by name lookup.
900 if (isa<CXXConstructorDecl>(R.Declaration))
901 return;
902
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000903 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
904 return;
905
906 // Make sure that any given declaration only shows up in the result set once.
907 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
908 return;
909
910 // If the filter is for nested-name-specifiers, then this result starts a
911 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000912 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000913 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000914 R.Priority = CCP_NestedNameSpecifier;
915 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000916 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
917 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000918 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000919 R.QualifierIsInformative = true;
920
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000921 // If this result is supposed to have an informative qualifier, add one.
922 if (R.QualifierIsInformative && !R.Qualifier &&
923 !R.StartsNestedNameSpecifier) {
924 DeclContext *Ctx = R.Declaration->getDeclContext();
925 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
926 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
927 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
928 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000929 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000930 else
931 R.QualifierIsInformative = false;
932 }
933
Douglas Gregor12e13132010-05-26 22:00:08 +0000934 // Adjust the priority if this result comes from a base class.
935 if (InBaseClass)
936 R.Priority += CCD_InBaseClass;
937
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000938 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000939
Douglas Gregor3cdee122010-08-26 16:36:48 +0000940 if (HasObjectTypeQualifiers)
941 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
942 if (Method->isInstance()) {
943 Qualifiers MethodQuals
944 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
945 if (ObjectTypeQualifiers == MethodQuals)
946 R.Priority += CCD_ObjectQualifierMatch;
947 else if (ObjectTypeQualifiers - MethodQuals) {
948 // The method cannot be invoked, because doing so would drop
949 // qualifiers.
950 return;
951 }
952 }
953
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000954 // Insert this result into the set of results.
955 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000956
957 if (!AsNestedNameSpecifier)
958 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000959}
960
Douglas Gregora4477812010-01-14 16:01:26 +0000961void ResultBuilder::AddResult(Result R) {
962 assert(R.Kind != Result::RK_Declaration &&
963 "Declaration results need more context");
964 Results.push_back(R);
965}
966
Douglas Gregor86d9a522009-09-21 16:56:56 +0000967/// \brief Enter into a new scope.
968void ResultBuilder::EnterNewScope() {
969 ShadowMaps.push_back(ShadowMap());
970}
971
972/// \brief Exit from the current scope.
973void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000974 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
975 EEnd = ShadowMaps.back().end();
976 E != EEnd;
977 ++E)
978 E->second.Destroy();
979
Douglas Gregor86d9a522009-09-21 16:56:56 +0000980 ShadowMaps.pop_back();
981}
982
Douglas Gregor791215b2009-09-21 20:51:25 +0000983/// \brief Determines whether this given declaration will be found by
984/// ordinary name lookup.
985bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000986 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
987
Douglas Gregor791215b2009-09-21 20:51:25 +0000988 unsigned IDNS = Decl::IDNS_Ordinary;
989 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000990 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Douglas Gregorca45da02010-11-02 20:36:02 +0000991 else if (SemaRef.getLangOptions().ObjC1) {
992 if (isa<ObjCIvarDecl>(ND))
993 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +0000994 }
995
Douglas Gregor791215b2009-09-21 20:51:25 +0000996 return ND->getIdentifierNamespace() & IDNS;
997}
998
Douglas Gregor01dfea02010-01-10 23:08:15 +0000999/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001000/// ordinary name lookup but is not a type name.
1001bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
1002 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1003 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1004 return false;
1005
1006 unsigned IDNS = Decl::IDNS_Ordinary;
1007 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +00001008 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Douglas Gregorca45da02010-11-02 20:36:02 +00001009 else if (SemaRef.getLangOptions().ObjC1) {
1010 if (isa<ObjCIvarDecl>(ND))
1011 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001012 }
1013
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001014 return ND->getIdentifierNamespace() & IDNS;
1015}
1016
Douglas Gregorf9578432010-07-28 21:50:18 +00001017bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
1018 if (!IsOrdinaryNonTypeName(ND))
1019 return 0;
1020
1021 if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
1022 if (VD->getType()->isIntegralOrEnumerationType())
1023 return true;
1024
1025 return false;
1026}
1027
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001028/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001029/// ordinary name lookup.
1030bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001031 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1032
Douglas Gregor01dfea02010-01-10 23:08:15 +00001033 unsigned IDNS = Decl::IDNS_Ordinary;
1034 if (SemaRef.getLangOptions().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001035 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001036
1037 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001038 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1039 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001040}
1041
Douglas Gregor86d9a522009-09-21 16:56:56 +00001042/// \brief Determines whether the given declaration is suitable as the
1043/// start of a C++ nested-name-specifier, e.g., a class or namespace.
1044bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
1045 // Allow us to find class templates, too.
1046 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1047 ND = ClassTemplate->getTemplatedDecl();
1048
1049 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1050}
1051
1052/// \brief Determines whether the given declaration is an enumeration.
1053bool ResultBuilder::IsEnum(NamedDecl *ND) const {
1054 return isa<EnumDecl>(ND);
1055}
1056
1057/// \brief Determines whether the given declaration is a class or struct.
1058bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
1059 // Allow us to find class templates, too.
1060 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1061 ND = ClassTemplate->getTemplatedDecl();
1062
1063 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001064 return RD->getTagKind() == TTK_Class ||
1065 RD->getTagKind() == TTK_Struct;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001066
1067 return false;
1068}
1069
1070/// \brief Determines whether the given declaration is a union.
1071bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1072 // Allow us to find class templates, too.
1073 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1074 ND = ClassTemplate->getTemplatedDecl();
1075
1076 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001077 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001078
1079 return false;
1080}
1081
1082/// \brief Determines whether the given declaration is a namespace.
1083bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1084 return isa<NamespaceDecl>(ND);
1085}
1086
1087/// \brief Determines whether the given declaration is a namespace or
1088/// namespace alias.
1089bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1090 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1091}
1092
Douglas Gregor76282942009-12-11 17:31:05 +00001093/// \brief Determines whether the given declaration is a type.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001094bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregord32b0222010-08-24 01:06:58 +00001095 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1096 ND = Using->getTargetDecl();
1097
1098 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001099}
1100
Douglas Gregor76282942009-12-11 17:31:05 +00001101/// \brief Determines which members of a class should be visible via
1102/// "." or "->". Only value declarations, nested name specifiers, and
1103/// using declarations thereof should show up.
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001104bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor76282942009-12-11 17:31:05 +00001105 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1106 ND = Using->getTargetDecl();
1107
Douglas Gregorce821962009-12-11 18:14:22 +00001108 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1109 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001110}
1111
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001112static bool isObjCReceiverType(ASTContext &C, QualType T) {
1113 T = C.getCanonicalType(T);
1114 switch (T->getTypeClass()) {
1115 case Type::ObjCObject:
1116 case Type::ObjCInterface:
1117 case Type::ObjCObjectPointer:
1118 return true;
1119
1120 case Type::Builtin:
1121 switch (cast<BuiltinType>(T)->getKind()) {
1122 case BuiltinType::ObjCId:
1123 case BuiltinType::ObjCClass:
1124 case BuiltinType::ObjCSel:
1125 return true;
1126
1127 default:
1128 break;
1129 }
1130 return false;
1131
1132 default:
1133 break;
1134 }
1135
1136 if (!C.getLangOptions().CPlusPlus)
1137 return false;
1138
1139 // FIXME: We could perform more analysis here to determine whether a
1140 // particular class type has any conversions to Objective-C types. For now,
1141 // just accept all class types.
1142 return T->isDependentType() || T->isRecordType();
1143}
1144
1145bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1146 QualType T = getDeclUsageType(SemaRef.Context, ND);
1147 if (T.isNull())
1148 return false;
1149
1150 T = SemaRef.Context.getBaseElementType(T);
1151 return isObjCReceiverType(SemaRef.Context, T);
1152}
1153
Douglas Gregorfb629412010-08-23 21:17:50 +00001154bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
1155 if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) ||
1156 (!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
1157 return false;
1158
1159 QualType T = getDeclUsageType(SemaRef.Context, ND);
1160 if (T.isNull())
1161 return false;
1162
1163 T = SemaRef.Context.getBaseElementType(T);
1164 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1165 T->isObjCIdType() ||
1166 (SemaRef.getLangOptions().CPlusPlus && T->isRecordType());
1167}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001168
Douglas Gregor52779fb2010-09-23 23:01:17 +00001169bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1170 return false;
1171}
1172
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001173/// \rief Determines whether the given declaration is an Objective-C
1174/// instance variable.
1175bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1176 return isa<ObjCIvarDecl>(ND);
1177}
1178
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001179namespace {
1180 /// \brief Visible declaration consumer that adds a code-completion result
1181 /// for each visible declaration.
1182 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1183 ResultBuilder &Results;
1184 DeclContext *CurContext;
1185
1186 public:
1187 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1188 : Results(Results), CurContext(CurContext) { }
1189
Erik Verbruggend1205962011-10-06 07:27:49 +00001190 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1191 bool InBaseClass) {
1192 bool Accessible = true;
Douglas Gregor17015ef2011-11-03 16:51:37 +00001193 if (Ctx)
1194 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1195
Erik Verbruggend1205962011-10-06 07:27:49 +00001196 ResultBuilder::Result Result(ND, 0, false, Accessible);
1197 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001198 }
1199 };
1200}
1201
Douglas Gregor86d9a522009-09-21 16:56:56 +00001202/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001203static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001204 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001205 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001206 Results.AddResult(Result("short", CCP_Type));
1207 Results.AddResult(Result("long", CCP_Type));
1208 Results.AddResult(Result("signed", CCP_Type));
1209 Results.AddResult(Result("unsigned", CCP_Type));
1210 Results.AddResult(Result("void", CCP_Type));
1211 Results.AddResult(Result("char", CCP_Type));
1212 Results.AddResult(Result("int", CCP_Type));
1213 Results.AddResult(Result("float", CCP_Type));
1214 Results.AddResult(Result("double", CCP_Type));
1215 Results.AddResult(Result("enum", CCP_Type));
1216 Results.AddResult(Result("struct", CCP_Type));
1217 Results.AddResult(Result("union", CCP_Type));
1218 Results.AddResult(Result("const", CCP_Type));
1219 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001220
Douglas Gregor86d9a522009-09-21 16:56:56 +00001221 if (LangOpts.C99) {
1222 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001223 Results.AddResult(Result("_Complex", CCP_Type));
1224 Results.AddResult(Result("_Imaginary", CCP_Type));
1225 Results.AddResult(Result("_Bool", CCP_Type));
1226 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001227 }
1228
Douglas Gregor218937c2011-02-01 19:23:04 +00001229 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001230 if (LangOpts.CPlusPlus) {
1231 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001232 Results.AddResult(Result("bool", CCP_Type +
1233 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001234 Results.AddResult(Result("class", CCP_Type));
1235 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001236
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001237 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001238 Builder.AddTypedTextChunk("typename");
1239 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1240 Builder.AddPlaceholderChunk("qualifier");
1241 Builder.AddTextChunk("::");
1242 Builder.AddPlaceholderChunk("name");
1243 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001244
Douglas Gregor86d9a522009-09-21 16:56:56 +00001245 if (LangOpts.CPlusPlus0x) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001246 Results.AddResult(Result("auto", CCP_Type));
1247 Results.AddResult(Result("char16_t", CCP_Type));
1248 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001249
Douglas Gregor218937c2011-02-01 19:23:04 +00001250 Builder.AddTypedTextChunk("decltype");
1251 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1252 Builder.AddPlaceholderChunk("expression");
1253 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1254 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001255 }
1256 }
1257
1258 // GNU extensions
1259 if (LangOpts.GNUMode) {
1260 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001261 // Results.AddResult(Result("_Decimal32"));
1262 // Results.AddResult(Result("_Decimal64"));
1263 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001264
Douglas Gregor218937c2011-02-01 19:23:04 +00001265 Builder.AddTypedTextChunk("typeof");
1266 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1267 Builder.AddPlaceholderChunk("expression");
1268 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001269
Douglas Gregor218937c2011-02-01 19:23:04 +00001270 Builder.AddTypedTextChunk("typeof");
1271 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1272 Builder.AddPlaceholderChunk("type");
1273 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1274 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001275 }
1276}
1277
John McCallf312b1e2010-08-26 23:41:50 +00001278static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001279 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001280 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001281 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001282 // Note: we don't suggest either "auto" or "register", because both
1283 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1284 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001285 Results.AddResult(Result("extern"));
1286 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001287}
1288
John McCallf312b1e2010-08-26 23:41:50 +00001289static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001290 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001291 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001292 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001293 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001294 case Sema::PCC_Class:
1295 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001296 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001297 Results.AddResult(Result("explicit"));
1298 Results.AddResult(Result("friend"));
1299 Results.AddResult(Result("mutable"));
1300 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001301 }
1302 // Fall through
1303
John McCallf312b1e2010-08-26 23:41:50 +00001304 case Sema::PCC_ObjCInterface:
1305 case Sema::PCC_ObjCImplementation:
1306 case Sema::PCC_Namespace:
1307 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001308 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001309 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001310 break;
1311
John McCallf312b1e2010-08-26 23:41:50 +00001312 case Sema::PCC_ObjCInstanceVariableList:
1313 case Sema::PCC_Expression:
1314 case Sema::PCC_Statement:
1315 case Sema::PCC_ForInit:
1316 case Sema::PCC_Condition:
1317 case Sema::PCC_RecoveryInFunction:
1318 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001319 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001320 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001321 break;
1322 }
1323}
1324
Douglas Gregorbca403c2010-01-13 23:51:12 +00001325static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1326static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1327static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001328 ResultBuilder &Results,
1329 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001330static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001331 ResultBuilder &Results,
1332 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001333static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001334 ResultBuilder &Results,
1335 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001336static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001337
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001338static void AddTypedefResult(ResultBuilder &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001339 CodeCompletionBuilder Builder(Results.getAllocator());
1340 Builder.AddTypedTextChunk("typedef");
1341 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1342 Builder.AddPlaceholderChunk("type");
1343 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1344 Builder.AddPlaceholderChunk("name");
1345 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001346}
1347
John McCallf312b1e2010-08-26 23:41:50 +00001348static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001349 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001350 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001351 case Sema::PCC_Namespace:
1352 case Sema::PCC_Class:
1353 case Sema::PCC_ObjCInstanceVariableList:
1354 case Sema::PCC_Template:
1355 case Sema::PCC_MemberTemplate:
1356 case Sema::PCC_Statement:
1357 case Sema::PCC_RecoveryInFunction:
1358 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001359 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001360 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001361 return true;
1362
John McCallf312b1e2010-08-26 23:41:50 +00001363 case Sema::PCC_Expression:
1364 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001365 return LangOpts.CPlusPlus;
1366
1367 case Sema::PCC_ObjCInterface:
1368 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001369 return false;
1370
John McCallf312b1e2010-08-26 23:41:50 +00001371 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001372 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001373 }
David Blaikie7530c032012-01-17 06:56:22 +00001374
1375 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001376}
1377
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001378static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1379 const Preprocessor &PP) {
1380 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001381 Policy.AnonymousTagLocations = false;
1382 Policy.SuppressStrongLifetime = true;
Douglas Gregor25270b62011-11-03 00:16:13 +00001383 Policy.SuppressUnwrittenScope = true;
Douglas Gregor8ca72082011-10-18 21:20:17 +00001384 return Policy;
1385}
1386
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001387/// \brief Retrieve a printing policy suitable for code completion.
1388static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1389 return getCompletionPrintingPolicy(S.Context, S.PP);
1390}
1391
Douglas Gregor8ca72082011-10-18 21:20:17 +00001392/// \brief Retrieve the string representation of the given type as a string
1393/// that has the appropriate lifetime for code completion.
1394///
1395/// This routine provides a fast path where we provide constant strings for
1396/// common type names.
1397static const char *GetCompletionTypeString(QualType T,
1398 ASTContext &Context,
1399 const PrintingPolicy &Policy,
1400 CodeCompletionAllocator &Allocator) {
1401 if (!T.getLocalQualifiers()) {
1402 // Built-in type names are constant strings.
1403 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
1404 return BT->getName(Policy);
1405
1406 // Anonymous tag types are constant strings.
1407 if (const TagType *TagT = dyn_cast<TagType>(T))
1408 if (TagDecl *Tag = TagT->getDecl())
1409 if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
1410 switch (Tag->getTagKind()) {
1411 case TTK_Struct: return "struct <anonymous>";
1412 case TTK_Class: return "class <anonymous>";
1413 case TTK_Union: return "union <anonymous>";
1414 case TTK_Enum: return "enum <anonymous>";
1415 }
1416 }
1417 }
1418
1419 // Slow path: format the type as a string.
1420 std::string Result;
1421 T.getAsStringInternal(Result, Policy);
1422 return Allocator.CopyString(Result);
1423}
1424
Douglas Gregor01dfea02010-01-10 23:08:15 +00001425/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001426static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001427 Scope *S,
1428 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001429 ResultBuilder &Results) {
Douglas Gregor8ca72082011-10-18 21:20:17 +00001430 CodeCompletionAllocator &Allocator = Results.getAllocator();
1431 CodeCompletionBuilder Builder(Allocator);
1432 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregor218937c2011-02-01 19:23:04 +00001433
John McCall0a2c5e22010-08-25 06:19:51 +00001434 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001435 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001436 case Sema::PCC_Namespace:
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001437 if (SemaRef.getLangOptions().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001438 if (Results.includeCodePatterns()) {
1439 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001440 Builder.AddTypedTextChunk("namespace");
1441 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1442 Builder.AddPlaceholderChunk("identifier");
1443 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1444 Builder.AddPlaceholderChunk("declarations");
1445 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1446 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1447 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001448 }
1449
Douglas Gregor01dfea02010-01-10 23:08:15 +00001450 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001451 Builder.AddTypedTextChunk("namespace");
1452 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1453 Builder.AddPlaceholderChunk("name");
1454 Builder.AddChunk(CodeCompletionString::CK_Equal);
1455 Builder.AddPlaceholderChunk("namespace");
1456 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001457
1458 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001459 Builder.AddTypedTextChunk("using");
1460 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1461 Builder.AddTextChunk("namespace");
1462 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1463 Builder.AddPlaceholderChunk("identifier");
1464 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001465
1466 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001467 Builder.AddTypedTextChunk("asm");
1468 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1469 Builder.AddPlaceholderChunk("string-literal");
1470 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1471 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001472
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001473 if (Results.includeCodePatterns()) {
1474 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001475 Builder.AddTypedTextChunk("template");
1476 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1477 Builder.AddPlaceholderChunk("declaration");
1478 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001479 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001480 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001481
1482 if (SemaRef.getLangOptions().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001483 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001484
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001485 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001486 // Fall through
1487
John McCallf312b1e2010-08-26 23:41:50 +00001488 case Sema::PCC_Class:
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001489 if (SemaRef.getLangOptions().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001490 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001491 Builder.AddTypedTextChunk("using");
1492 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1493 Builder.AddPlaceholderChunk("qualifier");
1494 Builder.AddTextChunk("::");
1495 Builder.AddPlaceholderChunk("name");
1496 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001497
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001498 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001499 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001500 Builder.AddTypedTextChunk("using");
1501 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1502 Builder.AddTextChunk("typename");
1503 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1504 Builder.AddPlaceholderChunk("qualifier");
1505 Builder.AddTextChunk("::");
1506 Builder.AddPlaceholderChunk("name");
1507 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001508 }
1509
John McCallf312b1e2010-08-26 23:41:50 +00001510 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001511 AddTypedefResult(Results);
1512
Douglas Gregor01dfea02010-01-10 23:08:15 +00001513 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001514 Builder.AddTypedTextChunk("public");
1515 Builder.AddChunk(CodeCompletionString::CK_Colon);
1516 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001517
1518 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001519 Builder.AddTypedTextChunk("protected");
1520 Builder.AddChunk(CodeCompletionString::CK_Colon);
1521 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001522
1523 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001524 Builder.AddTypedTextChunk("private");
1525 Builder.AddChunk(CodeCompletionString::CK_Colon);
1526 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001527 }
1528 }
1529 // Fall through
1530
John McCallf312b1e2010-08-26 23:41:50 +00001531 case Sema::PCC_Template:
1532 case Sema::PCC_MemberTemplate:
Douglas Gregord8e8a582010-05-25 21:41:55 +00001533 if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001534 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001535 Builder.AddTypedTextChunk("template");
1536 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1537 Builder.AddPlaceholderChunk("parameters");
1538 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1539 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001540 }
1541
Douglas Gregorbca403c2010-01-13 23:51:12 +00001542 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1543 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001544 break;
1545
John McCallf312b1e2010-08-26 23:41:50 +00001546 case Sema::PCC_ObjCInterface:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001547 AddObjCInterfaceResults(SemaRef.getLangOptions(), Results, true);
1548 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1549 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001550 break;
1551
John McCallf312b1e2010-08-26 23:41:50 +00001552 case Sema::PCC_ObjCImplementation:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001553 AddObjCImplementationResults(SemaRef.getLangOptions(), Results, true);
1554 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1555 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001556 break;
1557
John McCallf312b1e2010-08-26 23:41:50 +00001558 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001559 AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001560 break;
1561
John McCallf312b1e2010-08-26 23:41:50 +00001562 case Sema::PCC_RecoveryInFunction:
1563 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001564 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001565
Douglas Gregorec3310a2011-04-12 02:47:21 +00001566 if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns() &&
1567 SemaRef.getLangOptions().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001568 Builder.AddTypedTextChunk("try");
1569 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1570 Builder.AddPlaceholderChunk("statements");
1571 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1572 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1573 Builder.AddTextChunk("catch");
1574 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1575 Builder.AddPlaceholderChunk("declaration");
1576 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1577 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1578 Builder.AddPlaceholderChunk("statements");
1579 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1580 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1581 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001582 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001583 if (SemaRef.getLangOptions().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001584 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001585
Douglas Gregord8e8a582010-05-25 21:41:55 +00001586 if (Results.includeCodePatterns()) {
1587 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001588 Builder.AddTypedTextChunk("if");
1589 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001590 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001591 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001592 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001593 Builder.AddPlaceholderChunk("expression");
1594 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1595 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1596 Builder.AddPlaceholderChunk("statements");
1597 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1598 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1599 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001600
Douglas Gregord8e8a582010-05-25 21:41:55 +00001601 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001602 Builder.AddTypedTextChunk("switch");
1603 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001604 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001605 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001606 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001607 Builder.AddPlaceholderChunk("expression");
1608 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1609 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1610 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1611 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1612 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001613 }
1614
Douglas Gregor01dfea02010-01-10 23:08:15 +00001615 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001616 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001617 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001618 Builder.AddTypedTextChunk("case");
1619 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1620 Builder.AddPlaceholderChunk("expression");
1621 Builder.AddChunk(CodeCompletionString::CK_Colon);
1622 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001623
1624 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001625 Builder.AddTypedTextChunk("default");
1626 Builder.AddChunk(CodeCompletionString::CK_Colon);
1627 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001628 }
1629
Douglas Gregord8e8a582010-05-25 21:41:55 +00001630 if (Results.includeCodePatterns()) {
1631 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001632 Builder.AddTypedTextChunk("while");
1633 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001634 if (SemaRef.getLangOptions().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.AddPlaceholderChunk("statements");
1641 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1642 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1643 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001644
1645 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001646 Builder.AddTypedTextChunk("do");
1647 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1648 Builder.AddPlaceholderChunk("statements");
1649 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1650 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1651 Builder.AddTextChunk("while");
1652 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1653 Builder.AddPlaceholderChunk("expression");
1654 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1655 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001656
Douglas Gregord8e8a582010-05-25 21:41:55 +00001657 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001658 Builder.AddTypedTextChunk("for");
1659 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001660 if (SemaRef.getLangOptions().CPlusPlus || SemaRef.getLangOptions().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001661 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001662 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001663 Builder.AddPlaceholderChunk("init-expression");
1664 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1665 Builder.AddPlaceholderChunk("condition");
1666 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1667 Builder.AddPlaceholderChunk("inc-expression");
1668 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1669 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1670 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1671 Builder.AddPlaceholderChunk("statements");
1672 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1673 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1674 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001675 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001676
1677 if (S->getContinueParent()) {
1678 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001679 Builder.AddTypedTextChunk("continue");
1680 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001681 }
1682
1683 if (S->getBreakParent()) {
1684 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001685 Builder.AddTypedTextChunk("break");
1686 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001687 }
1688
1689 // "return expression ;" or "return ;", depending on whether we
1690 // know the function is void or not.
1691 bool isVoid = false;
1692 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1693 isVoid = Function->getResultType()->isVoidType();
1694 else if (ObjCMethodDecl *Method
1695 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1696 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001697 else if (SemaRef.getCurBlock() &&
1698 !SemaRef.getCurBlock()->ReturnType.isNull())
1699 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001700 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001701 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001702 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1703 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001704 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001705 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001706
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001707 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001708 Builder.AddTypedTextChunk("goto");
1709 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1710 Builder.AddPlaceholderChunk("label");
1711 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001712
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001713 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001714 Builder.AddTypedTextChunk("using");
1715 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1716 Builder.AddTextChunk("namespace");
1717 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1718 Builder.AddPlaceholderChunk("identifier");
1719 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001720 }
1721
1722 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001723 case Sema::PCC_ForInit:
1724 case Sema::PCC_Condition:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001725 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001726 // Fall through: conditions and statements can have expressions.
1727
Douglas Gregor02688102010-09-14 23:59:36 +00001728 case Sema::PCC_ParenthesizedExpression:
John McCallf85e1932011-06-15 23:02:42 +00001729 if (SemaRef.getLangOptions().ObjCAutoRefCount &&
1730 CCC == Sema::PCC_ParenthesizedExpression) {
1731 // (__bridge <type>)<expression>
1732 Builder.AddTypedTextChunk("__bridge");
1733 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1734 Builder.AddPlaceholderChunk("type");
1735 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1736 Builder.AddPlaceholderChunk("expression");
1737 Results.AddResult(Result(Builder.TakeString()));
1738
1739 // (__bridge_transfer <Objective-C type>)<expression>
1740 Builder.AddTypedTextChunk("__bridge_transfer");
1741 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1742 Builder.AddPlaceholderChunk("Objective-C type");
1743 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1744 Builder.AddPlaceholderChunk("expression");
1745 Results.AddResult(Result(Builder.TakeString()));
1746
1747 // (__bridge_retained <CF type>)<expression>
1748 Builder.AddTypedTextChunk("__bridge_retained");
1749 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1750 Builder.AddPlaceholderChunk("CF type");
1751 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1752 Builder.AddPlaceholderChunk("expression");
1753 Results.AddResult(Result(Builder.TakeString()));
1754 }
1755 // Fall through
1756
John McCallf312b1e2010-08-26 23:41:50 +00001757 case Sema::PCC_Expression: {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001758 if (SemaRef.getLangOptions().CPlusPlus) {
1759 // 'this', if we're in a non-static member function.
Eli Friedman72899c32012-01-07 04:59:52 +00001760 QualType ThisTy = SemaRef.getCurrentThisType();
Douglas Gregor8ca72082011-10-18 21:20:17 +00001761 if (!ThisTy.isNull()) {
1762 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1763 SemaRef.Context,
1764 Policy,
1765 Allocator));
1766 Builder.AddTypedTextChunk("this");
1767 Results.AddResult(Result(Builder.TakeString()));
1768 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001769
Douglas Gregor8ca72082011-10-18 21:20:17 +00001770 // true
1771 Builder.AddResultTypeChunk("bool");
1772 Builder.AddTypedTextChunk("true");
1773 Results.AddResult(Result(Builder.TakeString()));
1774
1775 // false
1776 Builder.AddResultTypeChunk("bool");
1777 Builder.AddTypedTextChunk("false");
1778 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001779
Douglas Gregorec3310a2011-04-12 02:47:21 +00001780 if (SemaRef.getLangOptions().RTTI) {
1781 // dynamic_cast < type-id > ( expression )
1782 Builder.AddTypedTextChunk("dynamic_cast");
1783 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1784 Builder.AddPlaceholderChunk("type");
1785 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1786 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1787 Builder.AddPlaceholderChunk("expression");
1788 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1789 Results.AddResult(Result(Builder.TakeString()));
1790 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001791
1792 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001793 Builder.AddTypedTextChunk("static_cast");
1794 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1795 Builder.AddPlaceholderChunk("type");
1796 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1797 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1798 Builder.AddPlaceholderChunk("expression");
1799 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1800 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001801
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001802 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001803 Builder.AddTypedTextChunk("reinterpret_cast");
1804 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1805 Builder.AddPlaceholderChunk("type");
1806 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1807 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1808 Builder.AddPlaceholderChunk("expression");
1809 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1810 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001811
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001812 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001813 Builder.AddTypedTextChunk("const_cast");
1814 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1815 Builder.AddPlaceholderChunk("type");
1816 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1817 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1818 Builder.AddPlaceholderChunk("expression");
1819 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1820 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001821
Douglas Gregorec3310a2011-04-12 02:47:21 +00001822 if (SemaRef.getLangOptions().RTTI) {
1823 // typeid ( expression-or-type )
Douglas Gregor8ca72082011-10-18 21:20:17 +00001824 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001825 Builder.AddTypedTextChunk("typeid");
1826 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1827 Builder.AddPlaceholderChunk("expression-or-type");
1828 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1829 Results.AddResult(Result(Builder.TakeString()));
1830 }
1831
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001832 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001833 Builder.AddTypedTextChunk("new");
1834 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1835 Builder.AddPlaceholderChunk("type");
1836 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1837 Builder.AddPlaceholderChunk("expressions");
1838 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1839 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001840
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001841 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001842 Builder.AddTypedTextChunk("new");
1843 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1844 Builder.AddPlaceholderChunk("type");
1845 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1846 Builder.AddPlaceholderChunk("size");
1847 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1848 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1849 Builder.AddPlaceholderChunk("expressions");
1850 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1851 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001852
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001853 // delete expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001854 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001855 Builder.AddTypedTextChunk("delete");
1856 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1857 Builder.AddPlaceholderChunk("expression");
1858 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001859
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001860 // delete [] expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001861 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001862 Builder.AddTypedTextChunk("delete");
1863 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1864 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1865 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1866 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1867 Builder.AddPlaceholderChunk("expression");
1868 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001869
Douglas Gregorec3310a2011-04-12 02:47:21 +00001870 if (SemaRef.getLangOptions().CXXExceptions) {
1871 // throw expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001872 Builder.AddResultTypeChunk("void");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001873 Builder.AddTypedTextChunk("throw");
1874 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1875 Builder.AddPlaceholderChunk("expression");
1876 Results.AddResult(Result(Builder.TakeString()));
1877 }
Douglas Gregora50216c2011-10-18 16:29:03 +00001878
Douglas Gregor12e13132010-05-26 22:00:08 +00001879 // FIXME: Rethrow?
Douglas Gregora50216c2011-10-18 16:29:03 +00001880
1881 if (SemaRef.getLangOptions().CPlusPlus0x) {
1882 // nullptr
Douglas Gregor8ca72082011-10-18 21:20:17 +00001883 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001884 Builder.AddTypedTextChunk("nullptr");
1885 Results.AddResult(Result(Builder.TakeString()));
1886
1887 // alignof
Douglas Gregor8ca72082011-10-18 21:20:17 +00001888 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001889 Builder.AddTypedTextChunk("alignof");
1890 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1891 Builder.AddPlaceholderChunk("type");
1892 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1893 Results.AddResult(Result(Builder.TakeString()));
1894
1895 // noexcept
Douglas Gregor8ca72082011-10-18 21:20:17 +00001896 Builder.AddResultTypeChunk("bool");
Douglas Gregora50216c2011-10-18 16:29:03 +00001897 Builder.AddTypedTextChunk("noexcept");
1898 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1899 Builder.AddPlaceholderChunk("expression");
1900 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1901 Results.AddResult(Result(Builder.TakeString()));
1902
1903 // sizeof... expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001904 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001905 Builder.AddTypedTextChunk("sizeof...");
1906 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1907 Builder.AddPlaceholderChunk("parameter-pack");
1908 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1909 Results.AddResult(Result(Builder.TakeString()));
1910 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001911 }
1912
1913 if (SemaRef.getLangOptions().ObjC1) {
1914 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001915 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1916 // The interface can be NULL.
1917 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregor8ca72082011-10-18 21:20:17 +00001918 if (ID->getSuperClass()) {
1919 std::string SuperType;
1920 SuperType = ID->getSuperClass()->getNameAsString();
1921 if (Method->isInstanceMethod())
1922 SuperType += " *";
1923
1924 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1925 Builder.AddTypedTextChunk("super");
1926 Results.AddResult(Result(Builder.TakeString()));
1927 }
Ted Kremenek681e2562010-05-31 21:43:10 +00001928 }
1929
Douglas Gregorbca403c2010-01-13 23:51:12 +00001930 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001931 }
1932
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001933 // sizeof expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001934 Builder.AddResultTypeChunk("size_t");
Douglas Gregor218937c2011-02-01 19:23:04 +00001935 Builder.AddTypedTextChunk("sizeof");
1936 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1937 Builder.AddPlaceholderChunk("expression-or-type");
1938 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1939 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001940 break;
1941 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001942
John McCallf312b1e2010-08-26 23:41:50 +00001943 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001944 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00001945 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001946 }
1947
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001948 if (WantTypesInContext(CCC, SemaRef.getLangOptions()))
1949 AddTypeSpecifierResults(SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001950
John McCallf312b1e2010-08-26 23:41:50 +00001951 if (SemaRef.getLangOptions().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00001952 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001953}
1954
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001955/// \brief If the given declaration has an associated type, add it as a result
1956/// type chunk.
1957static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00001958 const PrintingPolicy &Policy,
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001959 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00001960 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001961 if (!ND)
1962 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00001963
1964 // Skip constructors and conversion functions, which have their return types
1965 // built into their names.
1966 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
1967 return;
1968
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001969 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00001970 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001971 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
1972 T = Function->getResultType();
1973 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
1974 T = Method->getResultType();
1975 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
1976 T = FunTmpl->getTemplatedDecl()->getResultType();
1977 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
1978 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
1979 else if (isa<UnresolvedUsingValueDecl>(ND)) {
1980 /* Do nothing: ignore unresolved using declarations*/
John McCallf85e1932011-06-15 23:02:42 +00001981 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001982 T = Value->getType();
John McCallf85e1932011-06-15 23:02:42 +00001983 } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001984 T = Property->getType();
1985
1986 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
1987 return;
1988
Douglas Gregor8987b232011-09-27 23:30:47 +00001989 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00001990 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001991}
1992
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001993static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00001994 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001995 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
1996 if (Sentinel->getSentinel() == 0) {
1997 if (Context.getLangOptions().ObjC1 &&
1998 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00001999 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002000 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002001 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002002 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002003 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002004 }
2005}
2006
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002007static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2008 std::string Result;
2009 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002010 Result += "in ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002011 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002012 Result += "inout ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002013 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002014 Result += "out ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002015 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002016 Result += "bycopy ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002017 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002018 Result += "byref ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002019 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002020 Result += "oneway ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002021 return Result;
2022}
2023
Douglas Gregor83482d12010-08-24 16:15:59 +00002024static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002025 const PrintingPolicy &Policy,
Douglas Gregoraba48082010-08-29 19:47:46 +00002026 ParmVarDecl *Param,
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002027 bool SuppressName = false,
2028 bool SuppressBlock = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00002029 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2030 if (Param->getType()->isDependentType() ||
2031 !Param->getType()->isBlockPointerType()) {
2032 // The argument for a dependent or non-block parameter is a placeholder
2033 // containing that parameter's type.
2034 std::string Result;
2035
Douglas Gregoraba48082010-08-29 19:47:46 +00002036 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002037 Result = Param->getIdentifier()->getName();
2038
John McCallf85e1932011-06-15 23:02:42 +00002039 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002040
2041 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002042 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2043 + Result + ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00002044 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002045 Result += Param->getIdentifier()->getName();
2046 }
2047 return Result;
2048 }
2049
2050 // The argument for a block pointer parameter is a block literal with
2051 // the appropriate type.
Douglas Gregor830072c2011-02-15 22:37:09 +00002052 FunctionTypeLoc *Block = 0;
2053 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregor83482d12010-08-24 16:15:59 +00002054 TypeLoc TL;
2055 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2056 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2057 while (true) {
2058 // Look through typedefs.
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002059 if (!SuppressBlock) {
2060 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2061 if (TypeSourceInfo *InnerTSInfo
2062 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2063 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2064 continue;
2065 }
2066 }
2067
2068 // Look through qualified types
2069 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2070 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregor83482d12010-08-24 16:15:59 +00002071 continue;
2072 }
2073 }
2074
Douglas Gregor83482d12010-08-24 16:15:59 +00002075 // Try to get the function prototype behind the block pointer type,
2076 // then we're done.
2077 if (BlockPointerTypeLoc *BlockPtr
2078 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00002079 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor830072c2011-02-15 22:37:09 +00002080 Block = dyn_cast<FunctionTypeLoc>(&TL);
2081 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregor83482d12010-08-24 16:15:59 +00002082 }
2083 break;
2084 }
2085 }
2086
2087 if (!Block) {
2088 // We were unable to find a FunctionProtoTypeLoc with parameter names
2089 // for the block; just use the parameter type as a placeholder.
2090 std::string Result;
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002091 if (!ObjCMethodParam && Param->getIdentifier())
2092 Result = Param->getIdentifier()->getName();
2093
John McCallf85e1932011-06-15 23:02:42 +00002094 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002095
2096 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002097 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2098 + Result + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002099 if (Param->getIdentifier())
2100 Result += Param->getIdentifier()->getName();
2101 }
2102
2103 return Result;
2104 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002105
Douglas Gregor83482d12010-08-24 16:15:59 +00002106 // We have the function prototype behind the block pointer type, as it was
2107 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00002108 std::string Result;
2109 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002110 if (!ResultType->isVoidType() || SuppressBlock)
John McCallf85e1932011-06-15 23:02:42 +00002111 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002112
2113 // Format the parameter list.
2114 std::string Params;
Douglas Gregor830072c2011-02-15 22:37:09 +00002115 if (!BlockProto || Block->getNumArgs() == 0) {
2116 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002117 Params = "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00002118 else
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002119 Params = "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00002120 } else {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002121 Params += "(";
Douglas Gregor38276252010-09-08 22:47:51 +00002122 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2123 if (I)
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002124 Params += ", ";
2125 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2126 /*SuppressName=*/false,
2127 /*SuppressBlock=*/true);
Douglas Gregor38276252010-09-08 22:47:51 +00002128
Douglas Gregor830072c2011-02-15 22:37:09 +00002129 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002130 Params += ", ...";
Douglas Gregor38276252010-09-08 22:47:51 +00002131 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002132 Params += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00002133 }
Douglas Gregor38276252010-09-08 22:47:51 +00002134
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002135 if (SuppressBlock) {
2136 // Format as a parameter.
2137 Result = Result + " (^";
2138 if (Param->getIdentifier())
2139 Result += Param->getIdentifier()->getName();
2140 Result += ")";
2141 Result += Params;
2142 } else {
2143 // Format as a block literal argument.
2144 Result = '^' + Result;
2145 Result += Params;
2146
2147 if (Param->getIdentifier())
2148 Result += Param->getIdentifier()->getName();
2149 }
2150
Douglas Gregor83482d12010-08-24 16:15:59 +00002151 return Result;
2152}
2153
Douglas Gregor86d9a522009-09-21 16:56:56 +00002154/// \brief Add function parameter chunks to the given code completion string.
2155static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002156 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002157 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00002158 CodeCompletionBuilder &Result,
2159 unsigned Start = 0,
2160 bool InOptional = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002161 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00002162 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002163
Douglas Gregor218937c2011-02-01 19:23:04 +00002164 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002165 ParmVarDecl *Param = Function->getParamDecl(P);
2166
Douglas Gregor218937c2011-02-01 19:23:04 +00002167 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002168 // When we see an optional default argument, put that argument and
2169 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002170 CodeCompletionBuilder Opt(Result.getAllocator());
2171 if (!FirstParameter)
2172 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor8987b232011-09-27 23:30:47 +00002173 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregor218937c2011-02-01 19:23:04 +00002174 Result.AddOptionalChunk(Opt.TakeString());
2175 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002176 }
2177
Douglas Gregor218937c2011-02-01 19:23:04 +00002178 if (FirstParameter)
2179 FirstParameter = false;
2180 else
2181 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
2182
2183 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002184
2185 // Format the placeholder string.
Douglas Gregor8987b232011-09-27 23:30:47 +00002186 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2187 Param);
Douglas Gregor83482d12010-08-24 16:15:59 +00002188
Douglas Gregore17794f2010-08-31 05:13:43 +00002189 if (Function->isVariadic() && P == N - 1)
2190 PlaceholderStr += ", ...";
2191
Douglas Gregor86d9a522009-09-21 16:56:56 +00002192 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002193 Result.AddPlaceholderChunk(
2194 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002195 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002196
2197 if (const FunctionProtoType *Proto
2198 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002199 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002200 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002201 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002202
Douglas Gregor218937c2011-02-01 19:23:04 +00002203 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002204 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002205}
2206
2207/// \brief Add template parameter chunks to the given code completion string.
2208static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002209 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002210 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002211 CodeCompletionBuilder &Result,
2212 unsigned MaxParameters = 0,
2213 unsigned Start = 0,
2214 bool InDefaultArg = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002215 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002216 bool FirstParameter = true;
2217
2218 TemplateParameterList *Params = Template->getTemplateParameters();
2219 TemplateParameterList::iterator PEnd = Params->end();
2220 if (MaxParameters)
2221 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002222 for (TemplateParameterList::iterator P = Params->begin() + Start;
2223 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002224 bool HasDefaultArg = false;
2225 std::string PlaceholderStr;
2226 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2227 if (TTP->wasDeclaredWithTypename())
2228 PlaceholderStr = "typename";
2229 else
2230 PlaceholderStr = "class";
2231
2232 if (TTP->getIdentifier()) {
2233 PlaceholderStr += ' ';
2234 PlaceholderStr += TTP->getIdentifier()->getName();
2235 }
2236
2237 HasDefaultArg = TTP->hasDefaultArgument();
2238 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002239 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002240 if (NTTP->getIdentifier())
2241 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCallf85e1932011-06-15 23:02:42 +00002242 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002243 HasDefaultArg = NTTP->hasDefaultArgument();
2244 } else {
2245 assert(isa<TemplateTemplateParmDecl>(*P));
2246 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2247
2248 // Since putting the template argument list into the placeholder would
2249 // be very, very long, we just use an abbreviation.
2250 PlaceholderStr = "template<...> class";
2251 if (TTP->getIdentifier()) {
2252 PlaceholderStr += ' ';
2253 PlaceholderStr += TTP->getIdentifier()->getName();
2254 }
2255
2256 HasDefaultArg = TTP->hasDefaultArgument();
2257 }
2258
Douglas Gregor218937c2011-02-01 19:23:04 +00002259 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002260 // When we see an optional default argument, put that argument and
2261 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002262 CodeCompletionBuilder Opt(Result.getAllocator());
2263 if (!FirstParameter)
2264 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor8987b232011-09-27 23:30:47 +00002265 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregor218937c2011-02-01 19:23:04 +00002266 P - Params->begin(), true);
2267 Result.AddOptionalChunk(Opt.TakeString());
2268 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002269 }
2270
Douglas Gregor218937c2011-02-01 19:23:04 +00002271 InDefaultArg = false;
2272
Douglas Gregor86d9a522009-09-21 16:56:56 +00002273 if (FirstParameter)
2274 FirstParameter = false;
2275 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002276 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002277
2278 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002279 Result.AddPlaceholderChunk(
2280 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002281 }
2282}
2283
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002284/// \brief Add a qualifier to the given code-completion string, if the
2285/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002286static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002287AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002288 NestedNameSpecifier *Qualifier,
2289 bool QualifierIsInformative,
Douglas Gregor8987b232011-09-27 23:30:47 +00002290 ASTContext &Context,
2291 const PrintingPolicy &Policy) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002292 if (!Qualifier)
2293 return;
2294
2295 std::string PrintedNNS;
2296 {
2297 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor8987b232011-09-27 23:30:47 +00002298 Qualifier->print(OS, Policy);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002299 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002300 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002301 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002302 else
Douglas Gregordae68752011-02-01 22:57:45 +00002303 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002304}
2305
Douglas Gregor218937c2011-02-01 19:23:04 +00002306static void
2307AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2308 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002309 const FunctionProtoType *Proto
2310 = Function->getType()->getAs<FunctionProtoType>();
2311 if (!Proto || !Proto->getTypeQuals())
2312 return;
2313
Douglas Gregora63f6de2011-02-01 21:15:40 +00002314 // FIXME: Add ref-qualifier!
2315
2316 // Handle single qualifiers without copying
2317 if (Proto->getTypeQuals() == Qualifiers::Const) {
2318 Result.AddInformativeChunk(" const");
2319 return;
2320 }
2321
2322 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2323 Result.AddInformativeChunk(" volatile");
2324 return;
2325 }
2326
2327 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2328 Result.AddInformativeChunk(" restrict");
2329 return;
2330 }
2331
2332 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002333 std::string QualsStr;
2334 if (Proto->getTypeQuals() & Qualifiers::Const)
2335 QualsStr += " const";
2336 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2337 QualsStr += " volatile";
2338 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2339 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002340 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002341}
2342
Douglas Gregor6f942b22010-09-21 16:06:22 +00002343/// \brief Add the name of the given declaration
Douglas Gregor8987b232011-09-27 23:30:47 +00002344static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
2345 NamedDecl *ND, CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002346 typedef CodeCompletionString::Chunk Chunk;
2347
2348 DeclarationName Name = ND->getDeclName();
2349 if (!Name)
2350 return;
2351
2352 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002353 case DeclarationName::CXXOperatorName: {
2354 const char *OperatorName = 0;
2355 switch (Name.getCXXOverloadedOperator()) {
2356 case OO_None:
2357 case OO_Conditional:
2358 case NUM_OVERLOADED_OPERATORS:
2359 OperatorName = "operator";
2360 break;
2361
2362#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2363 case OO_##Name: OperatorName = "operator" Spelling; break;
2364#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2365#include "clang/Basic/OperatorKinds.def"
2366
2367 case OO_New: OperatorName = "operator new"; break;
2368 case OO_Delete: OperatorName = "operator delete"; break;
2369 case OO_Array_New: OperatorName = "operator new[]"; break;
2370 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2371 case OO_Call: OperatorName = "operator()"; break;
2372 case OO_Subscript: OperatorName = "operator[]"; break;
2373 }
2374 Result.AddTypedTextChunk(OperatorName);
2375 break;
2376 }
2377
Douglas Gregor6f942b22010-09-21 16:06:22 +00002378 case DeclarationName::Identifier:
2379 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002380 case DeclarationName::CXXDestructorName:
2381 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002382 Result.AddTypedTextChunk(
2383 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002384 break;
2385
2386 case DeclarationName::CXXUsingDirective:
2387 case DeclarationName::ObjCZeroArgSelector:
2388 case DeclarationName::ObjCOneArgSelector:
2389 case DeclarationName::ObjCMultiArgSelector:
2390 break;
2391
2392 case DeclarationName::CXXConstructorName: {
2393 CXXRecordDecl *Record = 0;
2394 QualType Ty = Name.getCXXNameType();
2395 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2396 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2397 else if (const InjectedClassNameType *InjectedTy
2398 = Ty->getAs<InjectedClassNameType>())
2399 Record = InjectedTy->getDecl();
2400 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002401 Result.AddTypedTextChunk(
2402 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002403 break;
2404 }
2405
Douglas Gregordae68752011-02-01 22:57:45 +00002406 Result.AddTypedTextChunk(
2407 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002408 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002409 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor8987b232011-09-27 23:30:47 +00002410 AddTemplateParameterChunks(Context, Policy, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002411 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002412 }
2413 break;
2414 }
2415 }
2416}
2417
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002418CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
2419 CodeCompletionAllocator &Allocator) {
2420 return CreateCodeCompletionString(S.Context, S.PP, Allocator);
2421}
2422
Douglas Gregor86d9a522009-09-21 16:56:56 +00002423/// \brief If possible, create a new code completion string for the given
2424/// result.
2425///
2426/// \returns Either a new, heap-allocated code completion string describing
2427/// how to use this result, or NULL to indicate that the string or name of the
2428/// result is all that is needed.
2429CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002430CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2431 Preprocessor &PP,
Douglas Gregordae68752011-02-01 22:57:45 +00002432 CodeCompletionAllocator &Allocator) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002433 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00002434 CodeCompletionBuilder Result(Allocator, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002435
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002436 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002437 if (Kind == RK_Pattern) {
2438 Pattern->Priority = Priority;
2439 Pattern->Availability = Availability;
2440 return Pattern;
2441 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002442
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002443 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002444 Result.AddTypedTextChunk(Keyword);
2445 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002446 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002447
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002448 if (Kind == RK_Macro) {
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002449 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002450 assert(MI && "Not a macro?");
2451
Douglas Gregordae68752011-02-01 22:57:45 +00002452 Result.AddTypedTextChunk(
2453 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002454
2455 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002456 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002457
2458 // Format a function-like macro with placeholders for the arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00002459 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregore4244702011-07-30 08:17:44 +00002460 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002461
2462 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2463 if (MI->isC99Varargs()) {
2464 --AEnd;
2465
2466 if (A == AEnd) {
2467 Result.AddPlaceholderChunk("...");
2468 }
Douglas Gregore4244702011-07-30 08:17:44 +00002469 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002470
Douglas Gregore4244702011-07-30 08:17:44 +00002471 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002472 if (A != MI->arg_begin())
Douglas Gregor218937c2011-02-01 19:23:04 +00002473 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002474
2475 if (MI->isVariadic() && (A+1) == AEnd) {
2476 llvm::SmallString<32> Arg = (*A)->getName();
2477 if (MI->isC99Varargs())
2478 Arg += ", ...";
2479 else
2480 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002481 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002482 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002483 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002484
2485 // Non-variadic macros are simple.
2486 Result.AddPlaceholderChunk(
2487 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002488 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002489 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2490 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002491 }
2492
Douglas Gregord8e8a582010-05-25 21:41:55 +00002493 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002494 NamedDecl *ND = Declaration;
2495
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002496 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002497 Result.AddTypedTextChunk(
2498 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002499 Result.AddTextChunk("::");
2500 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002501 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002502
2503 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2504 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2505 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2506 }
2507 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002508
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002509 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002510
Douglas Gregor86d9a522009-09-21 16:56:56 +00002511 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002512 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002513 Ctx, Policy);
2514 AddTypedNameChunk(Ctx, Policy, ND, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002515 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002516 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002517 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002518 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002519 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002520 }
2521
2522 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002523 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002524 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002525 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002526 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002527
Douglas Gregor86d9a522009-09-21 16:56:56 +00002528 // Figure out which template parameters are deduced (or have default
2529 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002530 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002531 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002532 unsigned LastDeducibleArgument;
2533 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2534 --LastDeducibleArgument) {
2535 if (!Deduced[LastDeducibleArgument - 1]) {
2536 // C++0x: Figure out if the template argument has a default. If so,
2537 // the user doesn't need to type this argument.
2538 // FIXME: We need to abstract template parameters better!
2539 bool HasDefaultArg = false;
2540 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002541 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002542 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2543 HasDefaultArg = TTP->hasDefaultArgument();
2544 else if (NonTypeTemplateParmDecl *NTTP
2545 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2546 HasDefaultArg = NTTP->hasDefaultArgument();
2547 else {
2548 assert(isa<TemplateTemplateParmDecl>(Param));
2549 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002550 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002551 }
2552
2553 if (!HasDefaultArg)
2554 break;
2555 }
2556 }
2557
2558 if (LastDeducibleArgument) {
2559 // Some of the function template arguments cannot be deduced from a
2560 // function call, so we introduce an explicit template argument list
2561 // containing all of the arguments up to the first deducible argument.
Douglas Gregor218937c2011-02-01 19:23:04 +00002562 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002563 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002564 LastDeducibleArgument);
Douglas Gregor218937c2011-02-01 19:23:04 +00002565 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002566 }
2567
2568 // Add the function parameters
Douglas Gregor218937c2011-02-01 19:23:04 +00002569 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002570 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002571 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002572 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002573 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002574 }
2575
2576 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002577 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002578 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002579 Result.AddTypedTextChunk(
2580 Result.getAllocator().CopyString(Template->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002581 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002582 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002583 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
2584 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002585 }
2586
Douglas Gregor9630eb62009-11-17 16:44:22 +00002587 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002588 Selector Sel = Method->getSelector();
2589 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002590 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002591 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002592 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002593 }
2594
Douglas Gregor813d8342011-02-18 22:29:55 +00002595 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002596 SelName += ':';
2597 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002598 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002599 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002600 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002601
2602 // If there is only one parameter, and we're past it, add an empty
2603 // typed-text chunk since there is nothing to type.
2604 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002605 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002606 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002607 unsigned Idx = 0;
2608 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2609 PEnd = Method->param_end();
2610 P != PEnd; (void)++P, ++Idx) {
2611 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002612 std::string Keyword;
2613 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002614 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002615 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002616 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002617 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002618 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002619 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002620 else
Douglas Gregordae68752011-02-01 22:57:45 +00002621 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002622 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002623
2624 // If we're before the starting parameter, skip the placeholder.
2625 if (Idx < StartParameter)
2626 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002627
2628 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002629
2630 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002631 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002632 else {
John McCallf85e1932011-06-15 23:02:42 +00002633 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002634 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2635 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002636 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002637 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002638 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002639 }
2640
Douglas Gregore17794f2010-08-31 05:13:43 +00002641 if (Method->isVariadic() && (P + 1) == PEnd)
2642 Arg += ", ...";
2643
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002644 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002645 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002646 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002647 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002648 else
Douglas Gregordae68752011-02-01 22:57:45 +00002649 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002650 }
2651
Douglas Gregor2a17af02009-12-23 00:21:46 +00002652 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002653 if (Method->param_size() == 0) {
2654 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002655 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002656 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002657 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002658 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002659 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002660 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002661
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002662 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002663 }
2664
Douglas Gregor218937c2011-02-01 19:23:04 +00002665 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002666 }
2667
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002668 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002669 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002670 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002671
Douglas Gregordae68752011-02-01 22:57:45 +00002672 Result.AddTypedTextChunk(
2673 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002674 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002675}
2676
Douglas Gregor86d802e2009-09-23 00:34:09 +00002677CodeCompletionString *
2678CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2679 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002680 Sema &S,
Douglas Gregordae68752011-02-01 22:57:45 +00002681 CodeCompletionAllocator &Allocator) const {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002682 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor8987b232011-09-27 23:30:47 +00002683 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002684
Douglas Gregor218937c2011-02-01 19:23:04 +00002685 // FIXME: Set priority, availability appropriately.
2686 CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002687 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002688 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002689 const FunctionProtoType *Proto
2690 = dyn_cast<FunctionProtoType>(getFunctionType());
2691 if (!FDecl && !Proto) {
2692 // Function without a prototype. Just give the return type and a
2693 // highlighted ellipsis.
2694 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002695 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002696 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002697 Result.getAllocator()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002698 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
2699 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
2700 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2701 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002702 }
2703
2704 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002705 Result.AddTextChunk(
2706 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002707 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002708 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002709 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002710 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002711
Douglas Gregor218937c2011-02-01 19:23:04 +00002712 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002713 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2714 for (unsigned I = 0; I != NumParams; ++I) {
2715 if (I)
Douglas Gregor218937c2011-02-01 19:23:04 +00002716 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002717
2718 std::string ArgString;
2719 QualType ArgType;
2720
2721 if (FDecl) {
2722 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2723 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2724 } else {
2725 ArgType = Proto->getArgType(I);
2726 }
2727
John McCallf85e1932011-06-15 23:02:42 +00002728 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002729
2730 if (I == CurrentArg)
Douglas Gregor218937c2011-02-01 19:23:04 +00002731 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter,
Douglas Gregordae68752011-02-01 22:57:45 +00002732 Result.getAllocator().CopyString(ArgString)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002733 else
Douglas Gregordae68752011-02-01 22:57:45 +00002734 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002735 }
2736
2737 if (Proto && Proto->isVariadic()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002738 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002739 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002740 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002741 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002742 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002743 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002744 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002745
Douglas Gregor218937c2011-02-01 19:23:04 +00002746 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002747}
2748
Chris Lattner5f9e2722011-07-23 10:55:15 +00002749unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002750 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002751 bool PreferredTypeIsPointer) {
2752 unsigned Priority = CCP_Macro;
2753
Douglas Gregorb05496d2010-09-20 21:11:48 +00002754 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2755 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2756 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002757 Priority = CCP_Constant;
2758 if (PreferredTypeIsPointer)
2759 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002760 }
2761 // Treat "YES", "NO", "true", and "false" as constants.
2762 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2763 MacroName.equals("true") || MacroName.equals("false"))
2764 Priority = CCP_Constant;
2765 // Treat "bool" as a type.
2766 else if (MacroName.equals("bool"))
2767 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2768
Douglas Gregor1827e102010-08-16 16:18:59 +00002769
2770 return Priority;
2771}
2772
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002773CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2774 if (!D)
2775 return CXCursor_UnexposedDecl;
2776
2777 switch (D->getKind()) {
2778 case Decl::Enum: return CXCursor_EnumDecl;
2779 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2780 case Decl::Field: return CXCursor_FieldDecl;
2781 case Decl::Function:
2782 return CXCursor_FunctionDecl;
2783 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2784 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002785 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002786
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002787 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002788 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2789 case Decl::ObjCMethod:
2790 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2791 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2792 case Decl::CXXMethod: return CXCursor_CXXMethod;
2793 case Decl::CXXConstructor: return CXCursor_Constructor;
2794 case Decl::CXXDestructor: return CXCursor_Destructor;
2795 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2796 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002797 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002798 case Decl::ParmVar: return CXCursor_ParmDecl;
2799 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002800 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002801 case Decl::Var: return CXCursor_VarDecl;
2802 case Decl::Namespace: return CXCursor_Namespace;
2803 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2804 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2805 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2806 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2807 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2808 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002809 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002810 case Decl::ClassTemplatePartialSpecialization:
2811 return CXCursor_ClassTemplatePartialSpecialization;
2812 case Decl::UsingDirective: return CXCursor_UsingDirective;
2813
2814 case Decl::Using:
2815 case Decl::UnresolvedUsingValue:
2816 case Decl::UnresolvedUsingTypename:
2817 return CXCursor_UsingDeclaration;
2818
Douglas Gregor352697a2011-06-03 23:08:58 +00002819 case Decl::ObjCPropertyImpl:
2820 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2821 case ObjCPropertyImplDecl::Dynamic:
2822 return CXCursor_ObjCDynamicDecl;
2823
2824 case ObjCPropertyImplDecl::Synthesize:
2825 return CXCursor_ObjCSynthesizeDecl;
2826 }
Douglas Gregor352697a2011-06-03 23:08:58 +00002827
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002828 default:
2829 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2830 switch (TD->getTagKind()) {
2831 case TTK_Struct: return CXCursor_StructDecl;
2832 case TTK_Class: return CXCursor_ClassDecl;
2833 case TTK_Union: return CXCursor_UnionDecl;
2834 case TTK_Enum: return CXCursor_EnumDecl;
2835 }
2836 }
2837 }
2838
2839 return CXCursor_UnexposedDecl;
2840}
2841
Douglas Gregor590c7d52010-07-08 20:55:51 +00002842static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2843 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002844 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002845
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002846 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002847
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002848 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2849 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002850 M != MEnd; ++M) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002851 Results.AddResult(Result(M->first,
2852 getMacroUsagePriority(M->first->getName(),
Douglas Gregorb05496d2010-09-20 21:11:48 +00002853 PP.getLangOptions(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002854 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002855 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002856
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002857 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002858
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002859}
2860
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002861static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2862 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002863 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002864
2865 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002866
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002867 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2868 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2869 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2870 Results.AddResult(Result("__func__", CCP_Constant));
2871 Results.ExitScope();
2872}
2873
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002874static void HandleCodeCompleteResults(Sema *S,
2875 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002876 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002877 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002878 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002879 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002880 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002881}
2882
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002883static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2884 Sema::ParserCompletionContext PCC) {
2885 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002886 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002887 return CodeCompletionContext::CCC_TopLevel;
2888
John McCallf312b1e2010-08-26 23:41:50 +00002889 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002890 return CodeCompletionContext::CCC_ClassStructUnion;
2891
John McCallf312b1e2010-08-26 23:41:50 +00002892 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002893 return CodeCompletionContext::CCC_ObjCInterface;
2894
John McCallf312b1e2010-08-26 23:41:50 +00002895 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002896 return CodeCompletionContext::CCC_ObjCImplementation;
2897
John McCallf312b1e2010-08-26 23:41:50 +00002898 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002899 return CodeCompletionContext::CCC_ObjCIvarList;
2900
John McCallf312b1e2010-08-26 23:41:50 +00002901 case Sema::PCC_Template:
2902 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002903 if (S.CurContext->isFileContext())
2904 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002905 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002906 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002907 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002908
John McCallf312b1e2010-08-26 23:41:50 +00002909 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002910 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002911
John McCallf312b1e2010-08-26 23:41:50 +00002912 case Sema::PCC_ForInit:
Douglas Gregora5450a02010-10-18 22:01:46 +00002913 if (S.getLangOptions().CPlusPlus || S.getLangOptions().C99 ||
2914 S.getLangOptions().ObjC1)
2915 return CodeCompletionContext::CCC_ParenthesizedExpression;
2916 else
2917 return CodeCompletionContext::CCC_Expression;
2918
2919 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002920 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002921 return CodeCompletionContext::CCC_Expression;
2922
John McCallf312b1e2010-08-26 23:41:50 +00002923 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002924 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002925
John McCallf312b1e2010-08-26 23:41:50 +00002926 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002927 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002928
2929 case Sema::PCC_ParenthesizedExpression:
2930 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002931
2932 case Sema::PCC_LocalDeclarationSpecifiers:
2933 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002934 }
David Blaikie7530c032012-01-17 06:56:22 +00002935
2936 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002937}
2938
Douglas Gregorf6961522010-08-27 21:18:54 +00002939/// \brief If we're in a C++ virtual member function, add completion results
2940/// that invoke the functions we override, since it's common to invoke the
2941/// overridden function as well as adding new functionality.
2942///
2943/// \param S The semantic analysis object for which we are generating results.
2944///
2945/// \param InContext This context in which the nested-name-specifier preceding
2946/// the code-completion point
2947static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2948 ResultBuilder &Results) {
2949 // Look through blocks.
2950 DeclContext *CurContext = S.CurContext;
2951 while (isa<BlockDecl>(CurContext))
2952 CurContext = CurContext->getParent();
2953
2954
2955 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2956 if (!Method || !Method->isVirtual())
2957 return;
2958
2959 // We need to have names for all of the parameters, if we're going to
2960 // generate a forwarding call.
2961 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2962 PEnd = Method->param_end();
2963 P != PEnd;
2964 ++P) {
2965 if (!(*P)->getDeclName())
2966 return;
2967 }
2968
Douglas Gregor8987b232011-09-27 23:30:47 +00002969 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00002970 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
2971 MEnd = Method->end_overridden_methods();
2972 M != MEnd; ++M) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002973 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf6961522010-08-27 21:18:54 +00002974 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
2975 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
2976 continue;
2977
2978 // If we need a nested-name-specifier, add one now.
2979 if (!InContext) {
2980 NestedNameSpecifier *NNS
2981 = getRequiredQualification(S.Context, CurContext,
2982 Overridden->getDeclContext());
2983 if (NNS) {
2984 std::string Str;
2985 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00002986 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002987 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00002988 }
2989 } else if (!InContext->Equals(Overridden->getDeclContext()))
2990 continue;
2991
Douglas Gregordae68752011-02-01 22:57:45 +00002992 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00002993 Overridden->getNameAsString()));
2994 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00002995 bool FirstParam = true;
2996 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2997 PEnd = Method->param_end();
2998 P != PEnd; ++P) {
2999 if (FirstParam)
3000 FirstParam = false;
3001 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003002 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003003
Douglas Gregordae68752011-02-01 22:57:45 +00003004 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003005 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003006 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003007 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3008 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003009 CCP_SuperCompletion,
3010 CXCursor_CXXMethod));
3011 Results.Ignore(Overridden);
3012 }
3013}
3014
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003015void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3016 ModuleIdPath Path) {
3017 typedef CodeCompletionResult Result;
3018 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3019 CodeCompletionContext::CCC_Other);
3020 Results.EnterNewScope();
3021
3022 CodeCompletionAllocator &Allocator = Results.getAllocator();
3023 CodeCompletionBuilder Builder(Allocator);
3024 typedef CodeCompletionResult Result;
3025 if (Path.empty()) {
3026 // Enumerate all top-level modules.
3027 llvm::SmallVector<Module *, 8> Modules;
3028 PP.getHeaderSearchInfo().collectAllModules(Modules);
3029 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3030 Builder.AddTypedTextChunk(
3031 Builder.getAllocator().CopyString(Modules[I]->Name));
3032 Results.AddResult(Result(Builder.TakeString(),
3033 CCP_Declaration,
3034 CXCursor_NotImplemented,
3035 Modules[I]->isAvailable()
3036 ? CXAvailability_Available
3037 : CXAvailability_NotAvailable));
3038 }
3039 } else {
3040 // Load the named module.
3041 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3042 Module::AllVisible,
3043 /*IsInclusionDirective=*/false);
3044 // Enumerate submodules.
3045 if (Mod) {
3046 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3047 SubEnd = Mod->submodule_end();
3048 Sub != SubEnd; ++Sub) {
3049
3050 Builder.AddTypedTextChunk(
3051 Builder.getAllocator().CopyString((*Sub)->Name));
3052 Results.AddResult(Result(Builder.TakeString(),
3053 CCP_Declaration,
3054 CXCursor_NotImplemented,
3055 (*Sub)->isAvailable()
3056 ? CXAvailability_Available
3057 : CXAvailability_NotAvailable));
3058 }
3059 }
3060 }
3061 Results.ExitScope();
3062 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3063 Results.data(),Results.size());
3064}
3065
Douglas Gregor01dfea02010-01-10 23:08:15 +00003066void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003067 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00003068 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003069 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003070 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003071 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003072
Douglas Gregor01dfea02010-01-10 23:08:15 +00003073 // Determine how to filter results, e.g., so that the names of
3074 // values (functions, enumerators, function templates, etc.) are
3075 // only allowed where we can have an expression.
3076 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003077 case PCC_Namespace:
3078 case PCC_Class:
3079 case PCC_ObjCInterface:
3080 case PCC_ObjCImplementation:
3081 case PCC_ObjCInstanceVariableList:
3082 case PCC_Template:
3083 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003084 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003085 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003086 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3087 break;
3088
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003089 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003090 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003091 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003092 case PCC_ForInit:
3093 case PCC_Condition:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003094 if (WantTypesInContext(CompletionContext, getLangOptions()))
3095 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3096 else
3097 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003098
3099 if (getLangOptions().CPlusPlus)
3100 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003101 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003102
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003103 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003104 // Unfiltered
3105 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003106 }
3107
Douglas Gregor3cdee122010-08-26 16:36:48 +00003108 // If we are in a C++ non-static member function, check the qualifiers on
3109 // the member function to filter/prioritize the results list.
3110 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3111 if (CurMethod->isInstance())
3112 Results.setObjectTypeQualifiers(
3113 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3114
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003115 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003116 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3117 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003118
Douglas Gregorbca403c2010-01-13 23:51:12 +00003119 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003120 Results.ExitScope();
3121
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003122 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003123 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003124 case PCC_Expression:
3125 case PCC_Statement:
3126 case PCC_RecoveryInFunction:
3127 if (S->getFnParent())
3128 AddPrettyFunctionResults(PP.getLangOptions(), Results);
3129 break;
3130
3131 case PCC_Namespace:
3132 case PCC_Class:
3133 case PCC_ObjCInterface:
3134 case PCC_ObjCImplementation:
3135 case PCC_ObjCInstanceVariableList:
3136 case PCC_Template:
3137 case PCC_MemberTemplate:
3138 case PCC_ForInit:
3139 case PCC_Condition:
3140 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003141 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003142 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003143 }
3144
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003145 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003146 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003147
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003148 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003149 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003150}
3151
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003152static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3153 ParsedType Receiver,
3154 IdentifierInfo **SelIdents,
3155 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003156 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003157 bool IsSuper,
3158 ResultBuilder &Results);
3159
3160void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3161 bool AllowNonIdentifiers,
3162 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003163 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003164 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003165 AllowNestedNameSpecifiers
3166 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3167 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003168 Results.EnterNewScope();
3169
3170 // Type qualifiers can come after names.
3171 Results.AddResult(Result("const"));
3172 Results.AddResult(Result("volatile"));
3173 if (getLangOptions().C99)
3174 Results.AddResult(Result("restrict"));
3175
3176 if (getLangOptions().CPlusPlus) {
3177 if (AllowNonIdentifiers) {
3178 Results.AddResult(Result("operator"));
3179 }
3180
3181 // Add nested-name-specifiers.
3182 if (AllowNestedNameSpecifiers) {
3183 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003184 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003185 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3186 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3187 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003188 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003189 }
3190 }
3191 Results.ExitScope();
3192
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003193 // If we're in a context where we might have an expression (rather than a
3194 // declaration), and what we've seen so far is an Objective-C type that could
3195 // be a receiver of a class message, this may be a class message send with
3196 // the initial opening bracket '[' missing. Add appropriate completions.
3197 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3198 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3199 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3200 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3201 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3202 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3203 DS.getTypeQualifiers() == 0 &&
3204 S &&
3205 (S->getFlags() & Scope::DeclScope) != 0 &&
3206 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3207 Scope::FunctionPrototypeScope |
3208 Scope::AtCatchScope)) == 0) {
3209 ParsedType T = DS.getRepAsType();
3210 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003211 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003212 }
3213
Douglas Gregor4497dd42010-08-24 04:59:56 +00003214 // Note that we intentionally suppress macro results here, since we do not
3215 // encourage using macros to produce the names of entities.
3216
Douglas Gregor52779fb2010-09-23 23:01:17 +00003217 HandleCodeCompleteResults(this, CodeCompleter,
3218 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003219 Results.data(), Results.size());
3220}
3221
Douglas Gregorfb629412010-08-23 21:17:50 +00003222struct Sema::CodeCompleteExpressionData {
3223 CodeCompleteExpressionData(QualType PreferredType = QualType())
3224 : PreferredType(PreferredType), IntegralConstantExpression(false),
3225 ObjCCollection(false) { }
3226
3227 QualType PreferredType;
3228 bool IntegralConstantExpression;
3229 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003230 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003231};
3232
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003233/// \brief Perform code-completion in an expression context when we know what
3234/// type we're looking for.
Douglas Gregorf9578432010-07-28 21:50:18 +00003235///
3236/// \param IntegralConstantExpression Only permit integral constant
3237/// expressions.
Douglas Gregorfb629412010-08-23 21:17:50 +00003238void Sema::CodeCompleteExpression(Scope *S,
3239 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00003240 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003241 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3242 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003243 if (Data.ObjCCollection)
3244 Results.setFilter(&ResultBuilder::IsObjCCollection);
3245 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003246 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003247 else if (WantTypesInContext(PCC_Expression, getLangOptions()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003248 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3249 else
3250 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003251
3252 if (!Data.PreferredType.isNull())
3253 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3254
3255 // Ignore any declarations that we were told that we don't care about.
3256 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3257 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003258
3259 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003260 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3261 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003262
3263 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003264 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003265 Results.ExitScope();
3266
Douglas Gregor590c7d52010-07-08 20:55:51 +00003267 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003268 if (!Data.PreferredType.isNull())
3269 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3270 || Data.PreferredType->isMemberPointerType()
3271 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003272
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003273 if (S->getFnParent() &&
3274 !Data.ObjCCollection &&
3275 !Data.IntegralConstantExpression)
3276 AddPrettyFunctionResults(PP.getLangOptions(), Results);
3277
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003278 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003279 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003280 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003281 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3282 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003283 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003284}
3285
Douglas Gregorac5fd842010-09-18 01:28:11 +00003286void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3287 if (E.isInvalid())
3288 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
3289 else if (getLangOptions().ObjC1)
3290 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003291}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003292
Douglas Gregor73449212010-12-09 23:01:55 +00003293/// \brief The set of properties that have already been added, referenced by
3294/// property name.
3295typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3296
Douglas Gregor95ac6552009-11-18 01:29:26 +00003297static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003298 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003299 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003300 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003301 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003302 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003303 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003304
3305 // Add properties in this container.
3306 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3307 PEnd = Container->prop_end();
3308 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003309 ++P) {
3310 if (AddedProperties.insert(P->getIdentifier()))
3311 Results.MaybeAddResult(Result(*P, 0), CurContext);
3312 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003313
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003314 // Add nullary methods
3315 if (AllowNullaryMethods) {
3316 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003317 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003318 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3319 MEnd = Container->meth_end();
3320 M != MEnd; ++M) {
3321 if (M->getSelector().isUnarySelector())
3322 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3323 if (AddedProperties.insert(Name)) {
3324 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor8987b232011-09-27 23:30:47 +00003325 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003326 Builder.AddTypedTextChunk(
3327 Results.getAllocator().CopyString(Name->getName()));
3328
3329 CXAvailabilityKind Availability = CXAvailability_Available;
3330 switch (M->getAvailability()) {
3331 case AR_Available:
3332 case AR_NotYetIntroduced:
3333 Availability = CXAvailability_Available;
3334 break;
3335
3336 case AR_Deprecated:
3337 Availability = CXAvailability_Deprecated;
3338 break;
3339
3340 case AR_Unavailable:
3341 Availability = CXAvailability_NotAvailable;
3342 break;
3343 }
3344
3345 Results.MaybeAddResult(Result(Builder.TakeString(),
3346 CCP_MemberDeclaration + CCD_MethodAsProperty,
3347 M->isInstanceMethod()
3348 ? CXCursor_ObjCInstanceMethodDecl
3349 : CXCursor_ObjCClassMethodDecl,
3350 Availability),
3351 CurContext);
3352 }
3353 }
3354 }
3355
3356
Douglas Gregor95ac6552009-11-18 01:29:26 +00003357 // Add properties in referenced protocols.
3358 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3359 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3360 PEnd = Protocol->protocol_end();
3361 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003362 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3363 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003364 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003365 if (AllowCategories) {
3366 // Look through categories.
3367 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3368 Category; Category = Category->getNextClassCategory())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003369 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3370 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003371 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003372
3373 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003374 for (ObjCInterfaceDecl::all_protocol_iterator
3375 I = IFace->all_referenced_protocol_begin(),
3376 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003377 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3378 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003379
3380 // Look in the superclass.
3381 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003382 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3383 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003384 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003385 } else if (const ObjCCategoryDecl *Category
3386 = dyn_cast<ObjCCategoryDecl>(Container)) {
3387 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003388 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3389 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003390 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003391 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3392 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003393 }
3394}
3395
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003396void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003397 SourceLocation OpLoc,
3398 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003399 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003400 return;
3401
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003402 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3403 if (ConvertedBase.isInvalid())
3404 return;
3405 Base = ConvertedBase.get();
3406
John McCall0a2c5e22010-08-25 06:19:51 +00003407 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003408
Douglas Gregor81b747b2009-09-17 21:32:03 +00003409 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003410
3411 if (IsArrow) {
3412 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3413 BaseType = Ptr->getPointeeType();
3414 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003415 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003416 else
3417 return;
3418 }
3419
Douglas Gregor3da626b2011-07-07 16:03:39 +00003420 enum CodeCompletionContext::Kind contextKind;
3421
3422 if (IsArrow) {
3423 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3424 }
3425 else {
3426 if (BaseType->isObjCObjectPointerType() ||
3427 BaseType->isObjCObjectOrInterfaceType()) {
3428 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3429 }
3430 else {
3431 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3432 }
3433 }
3434
Douglas Gregor218937c2011-02-01 19:23:04 +00003435 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003436 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003437 BaseType),
3438 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003439 Results.EnterNewScope();
3440 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003441 // Indicate that we are performing a member access, and the cv-qualifiers
3442 // for the base object type.
3443 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3444
Douglas Gregor95ac6552009-11-18 01:29:26 +00003445 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003446 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003447 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003448 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3449 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003450
Douglas Gregor95ac6552009-11-18 01:29:26 +00003451 if (getLangOptions().CPlusPlus) {
3452 if (!Results.empty()) {
3453 // The "template" keyword can follow "->" or "." in the grammar.
3454 // However, we only want to suggest the template keyword if something
3455 // is dependent.
3456 bool IsDependent = BaseType->isDependentType();
3457 if (!IsDependent) {
3458 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3459 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3460 IsDependent = Ctx->isDependentContext();
3461 break;
3462 }
3463 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003464
Douglas Gregor95ac6552009-11-18 01:29:26 +00003465 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003466 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003467 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003468 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003469 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3470 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003471 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003472
3473 // Add property results based on our interface.
3474 const ObjCObjectPointerType *ObjCPtr
3475 = BaseType->getAsObjCInterfacePointerType();
3476 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003477 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3478 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003479 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003480
3481 // Add properties from the protocols in a qualified interface.
3482 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3483 E = ObjCPtr->qual_end();
3484 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003485 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3486 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003487 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003488 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003489 // Objective-C instance variable access.
3490 ObjCInterfaceDecl *Class = 0;
3491 if (const ObjCObjectPointerType *ObjCPtr
3492 = BaseType->getAs<ObjCObjectPointerType>())
3493 Class = ObjCPtr->getInterfaceDecl();
3494 else
John McCallc12c5bb2010-05-15 11:32:37 +00003495 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003496
3497 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003498 if (Class) {
3499 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3500 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003501 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3502 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003503 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003504 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003505
3506 // FIXME: How do we cope with isa?
3507
3508 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003509
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003510 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003511 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003512 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003513 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003514}
3515
Douglas Gregor374929f2009-09-18 15:37:17 +00003516void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3517 if (!CodeCompleter)
3518 return;
3519
John McCall0a2c5e22010-08-25 06:19:51 +00003520 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003521 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003522 enum CodeCompletionContext::Kind ContextKind
3523 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003524 switch ((DeclSpec::TST)TagSpec) {
3525 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003526 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003527 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003528 break;
3529
3530 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003531 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003532 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003533 break;
3534
3535 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003536 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003537 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003538 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003539 break;
3540
3541 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003542 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003543 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003544
Douglas Gregor218937c2011-02-01 19:23:04 +00003545 ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003546 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003547
3548 // First pass: look for tags.
3549 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003550 LookupVisibleDecls(S, LookupTagName, Consumer,
3551 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003552
Douglas Gregor8071e422010-08-15 06:18:01 +00003553 if (CodeCompleter->includeGlobals()) {
3554 // Second pass: look for nested name specifiers.
3555 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3556 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3557 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003558
Douglas Gregor52779fb2010-09-23 23:01:17 +00003559 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003560 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003561}
3562
Douglas Gregor1a480c42010-08-27 17:35:51 +00003563void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003564 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3565 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003566 Results.EnterNewScope();
3567 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3568 Results.AddResult("const");
3569 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3570 Results.AddResult("volatile");
3571 if (getLangOptions().C99 &&
3572 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3573 Results.AddResult("restrict");
3574 Results.ExitScope();
3575 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003576 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003577 Results.data(), Results.size());
3578}
3579
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003580void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003581 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003582 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003583
John McCall781472f2010-08-25 08:40:02 +00003584 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003585 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3586 if (!type->isEnumeralType()) {
3587 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003588 Data.IntegralConstantExpression = true;
3589 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003590 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003591 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003592
3593 // Code-complete the cases of a switch statement over an enumeration type
3594 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003595 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003596
3597 // Determine which enumerators we have already seen in the switch statement.
3598 // FIXME: Ideally, we would also be able to look *past* the code-completion
3599 // token, in case we are code-completing in the middle of the switch and not
3600 // at the end. However, we aren't able to do so at the moment.
3601 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003602 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003603 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3604 SC = SC->getNextSwitchCase()) {
3605 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3606 if (!Case)
3607 continue;
3608
3609 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3610 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3611 if (EnumConstantDecl *Enumerator
3612 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3613 // We look into the AST of the case statement to determine which
3614 // enumerator was named. Alternatively, we could compute the value of
3615 // the integral constant expression, then compare it against the
3616 // values of each enumerator. However, value-based approach would not
3617 // work as well with C++ templates where enumerators declared within a
3618 // template are type- and value-dependent.
3619 EnumeratorsSeen.insert(Enumerator);
3620
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003621 // If this is a qualified-id, keep track of the nested-name-specifier
3622 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003623 //
3624 // switch (TagD.getKind()) {
3625 // case TagDecl::TK_enum:
3626 // break;
3627 // case XXX
3628 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003629 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003630 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3631 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003632 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003633 }
3634 }
3635
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003636 if (getLangOptions().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
3637 // If there are no prior enumerators in C++, check whether we have to
3638 // qualify the names of the enumerators that we suggest, because they
3639 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003640 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003641 }
3642
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003643 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003644 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3645 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003646 Results.EnterNewScope();
3647 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3648 EEnd = Enum->enumerator_end();
3649 E != EEnd; ++E) {
3650 if (EnumeratorsSeen.count(*E))
3651 continue;
3652
Douglas Gregor5c722c702011-02-18 23:30:37 +00003653 CodeCompletionResult R(*E, Qualifier);
3654 R.Priority = CCP_EnumInCase;
3655 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003656 }
3657 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003658
Douglas Gregor3da626b2011-07-07 16:03:39 +00003659 //We need to make sure we're setting the right context,
3660 //so only say we include macros if the code completer says we do
3661 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3662 if (CodeCompleter->includeMacros()) {
Douglas Gregorbca403c2010-01-13 23:51:12 +00003663 AddMacroResults(PP, Results);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003664 kind = CodeCompletionContext::CCC_OtherWithMacros;
3665 }
3666
3667
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003668 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003669 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003670 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003671}
3672
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003673namespace {
3674 struct IsBetterOverloadCandidate {
3675 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003676 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003677
3678 public:
John McCall5769d612010-02-08 23:07:23 +00003679 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3680 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003681
3682 bool
3683 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003684 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003685 }
3686 };
3687}
3688
Douglas Gregord28dcd72010-05-30 06:10:08 +00003689static bool anyNullArguments(Expr **Args, unsigned NumArgs) {
3690 if (NumArgs && !Args)
3691 return true;
3692
3693 for (unsigned I = 0; I != NumArgs; ++I)
3694 if (!Args[I])
3695 return true;
3696
3697 return false;
3698}
3699
Richard Trieuf81e5a92011-09-09 02:00:50 +00003700void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
3701 Expr **ArgsIn, unsigned NumArgs) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003702 if (!CodeCompleter)
3703 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003704
3705 // When we're code-completing for a call, we fall back to ordinary
3706 // name code-completion whenever we can't produce specific
3707 // results. We may want to revisit this strategy in the future,
3708 // e.g., by merging the two kinds of results.
3709
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003710 Expr *Fn = (Expr *)FnIn;
3711 Expr **Args = (Expr **)ArgsIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003712
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003713 // Ignore type-dependent call expressions entirely.
Douglas Gregord28dcd72010-05-30 06:10:08 +00003714 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) ||
Douglas Gregoref96eac2009-12-11 19:06:04 +00003715 Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003716 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003717 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003718 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003719
John McCall3b4294e2009-12-16 12:17:52 +00003720 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003721 SourceLocation Loc = Fn->getExprLoc();
3722 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003723
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003724 // FIXME: What if we're calling something that isn't a function declaration?
3725 // FIXME: What if we're calling a pseudo-destructor?
3726 // FIXME: What if we're calling a member function?
3727
Douglas Gregorc0265402010-01-21 15:46:19 +00003728 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003729 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003730
John McCall3b4294e2009-12-16 12:17:52 +00003731 Expr *NakedFn = Fn->IgnoreParenCasts();
3732 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
3733 AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet,
3734 /*PartialOverloading=*/ true);
3735 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3736 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003737 if (FDecl) {
Douglas Gregord28dcd72010-05-30 06:10:08 +00003738 if (!getLangOptions().CPlusPlus ||
3739 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003740 Results.push_back(ResultCandidate(FDecl));
3741 else
John McCall86820f52010-01-26 01:37:31 +00003742 // FIXME: access?
John McCall9aa472c2010-03-19 07:35:19 +00003743 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none),
3744 Args, NumArgs, CandidateSet,
Douglas Gregorc27d6c52010-04-16 17:41:49 +00003745 false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003746 }
John McCall3b4294e2009-12-16 12:17:52 +00003747 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003748
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003749 QualType ParamType;
3750
Douglas Gregorc0265402010-01-21 15:46:19 +00003751 if (!CandidateSet.empty()) {
3752 // Sort the overload candidate set by placing the best overloads first.
3753 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003754 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003755
Douglas Gregorc0265402010-01-21 15:46:19 +00003756 // Add the remaining viable overload candidates as code-completion reslults.
3757 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3758 CandEnd = CandidateSet.end();
3759 Cand != CandEnd; ++Cand) {
3760 if (Cand->Viable)
3761 Results.push_back(ResultCandidate(Cand->Function));
3762 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003763
3764 // From the viable candidates, try to determine the type of this parameter.
3765 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3766 if (const FunctionType *FType = Results[I].getFunctionType())
3767 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
3768 if (NumArgs < Proto->getNumArgs()) {
3769 if (ParamType.isNull())
3770 ParamType = Proto->getArgType(NumArgs);
3771 else if (!Context.hasSameUnqualifiedType(
3772 ParamType.getNonReferenceType(),
3773 Proto->getArgType(NumArgs).getNonReferenceType())) {
3774 ParamType = QualType();
3775 break;
3776 }
3777 }
3778 }
3779 } else {
3780 // Try to determine the parameter type from the type of the expression
3781 // being called.
3782 QualType FunctionType = Fn->getType();
3783 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3784 FunctionType = Ptr->getPointeeType();
3785 else if (const BlockPointerType *BlockPtr
3786 = FunctionType->getAs<BlockPointerType>())
3787 FunctionType = BlockPtr->getPointeeType();
3788 else if (const MemberPointerType *MemPtr
3789 = FunctionType->getAs<MemberPointerType>())
3790 FunctionType = MemPtr->getPointeeType();
3791
3792 if (const FunctionProtoType *Proto
3793 = FunctionType->getAs<FunctionProtoType>()) {
3794 if (NumArgs < Proto->getNumArgs())
3795 ParamType = Proto->getArgType(NumArgs);
3796 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003797 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003798
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003799 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003800 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003801 else
3802 CodeCompleteExpression(S, ParamType);
3803
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003804 if (!Results.empty())
Douglas Gregoref96eac2009-12-11 19:06:04 +00003805 CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(),
3806 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003807}
3808
John McCalld226f652010-08-21 09:40:31 +00003809void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3810 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003811 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003812 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003813 return;
3814 }
3815
3816 CodeCompleteExpression(S, VD->getType());
3817}
3818
3819void Sema::CodeCompleteReturn(Scope *S) {
3820 QualType ResultType;
3821 if (isa<BlockDecl>(CurContext)) {
3822 if (BlockScopeInfo *BSI = getCurBlock())
3823 ResultType = BSI->ReturnType;
3824 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3825 ResultType = Function->getResultType();
3826 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3827 ResultType = Method->getResultType();
3828
3829 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003830 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003831 else
3832 CodeCompleteExpression(S, ResultType);
3833}
3834
Douglas Gregord2d8be62011-07-30 08:36:53 +00003835void Sema::CodeCompleteAfterIf(Scope *S) {
3836 typedef CodeCompletionResult Result;
3837 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3838 mapCodeCompletionContext(*this, PCC_Statement));
3839 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3840 Results.EnterNewScope();
3841
3842 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3843 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3844 CodeCompleter->includeGlobals());
3845
3846 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3847
3848 // "else" block
3849 CodeCompletionBuilder Builder(Results.getAllocator());
3850 Builder.AddTypedTextChunk("else");
3851 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3852 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3853 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3854 Builder.AddPlaceholderChunk("statements");
3855 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3856 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3857 Results.AddResult(Builder.TakeString());
3858
3859 // "else if" block
3860 Builder.AddTypedTextChunk("else");
3861 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3862 Builder.AddTextChunk("if");
3863 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3864 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3865 if (getLangOptions().CPlusPlus)
3866 Builder.AddPlaceholderChunk("condition");
3867 else
3868 Builder.AddPlaceholderChunk("expression");
3869 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3870 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3871 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3872 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3873 Builder.AddPlaceholderChunk("statements");
3874 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3875 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3876 Results.AddResult(Builder.TakeString());
3877
3878 Results.ExitScope();
3879
3880 if (S->getFnParent())
3881 AddPrettyFunctionResults(PP.getLangOptions(), Results);
3882
3883 if (CodeCompleter->includeMacros())
3884 AddMacroResults(PP, Results);
3885
3886 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3887 Results.data(),Results.size());
3888}
3889
Richard Trieuf81e5a92011-09-09 02:00:50 +00003890void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003891 if (LHS)
3892 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3893 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003894 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003895}
3896
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003897void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003898 bool EnteringContext) {
3899 if (!SS.getScopeRep() || !CodeCompleter)
3900 return;
3901
Douglas Gregor86d9a522009-09-21 16:56:56 +00003902 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3903 if (!Ctx)
3904 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003905
3906 // Try to instantiate any non-dependent declaration contexts before
3907 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003908 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003909 return;
3910
Douglas Gregor218937c2011-02-01 19:23:04 +00003911 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3912 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003913 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003914
Douglas Gregor86d9a522009-09-21 16:56:56 +00003915 // The "template" keyword can follow "::" in the grammar, but only
3916 // put it into the grammar if the nested-name-specifier is dependent.
3917 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3918 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003919 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003920
3921 // Add calls to overridden virtual functions, if there are any.
3922 //
3923 // FIXME: This isn't wonderful, because we don't know whether we're actually
3924 // in a context that permits expressions. This is a general issue with
3925 // qualified-id completions.
3926 if (!EnteringContext)
3927 MaybeAddOverrideCalls(*this, Ctx, Results);
3928 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003929
Douglas Gregorf6961522010-08-27 21:18:54 +00003930 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3931 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3932
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003933 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00003934 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003935 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003936}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003937
3938void Sema::CodeCompleteUsing(Scope *S) {
3939 if (!CodeCompleter)
3940 return;
3941
Douglas Gregor218937c2011-02-01 19:23:04 +00003942 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003943 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3944 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003945 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003946
3947 // If we aren't in class scope, we could see the "namespace" keyword.
3948 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00003949 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003950
3951 // After "using", we can see anything that would start a
3952 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003953 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003954 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3955 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003956 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003957
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003958 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003959 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003960 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003961}
3962
3963void Sema::CodeCompleteUsingDirective(Scope *S) {
3964 if (!CodeCompleter)
3965 return;
3966
Douglas Gregor86d9a522009-09-21 16:56:56 +00003967 // After "using namespace", we expect to see a namespace name or namespace
3968 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003969 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3970 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003971 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003972 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003973 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003974 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3975 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003976 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003977 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003978 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003979 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003980}
3981
3982void Sema::CodeCompleteNamespaceDecl(Scope *S) {
3983 if (!CodeCompleter)
3984 return;
3985
Douglas Gregor86d9a522009-09-21 16:56:56 +00003986 DeclContext *Ctx = (DeclContext *)S->getEntity();
3987 if (!S->getParent())
3988 Ctx = Context.getTranslationUnitDecl();
3989
Douglas Gregor52779fb2010-09-23 23:01:17 +00003990 bool SuppressedGlobalResults
3991 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
3992
Douglas Gregor218937c2011-02-01 19:23:04 +00003993 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003994 SuppressedGlobalResults
3995 ? CodeCompletionContext::CCC_Namespace
3996 : CodeCompletionContext::CCC_Other,
3997 &ResultBuilder::IsNamespace);
3998
3999 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004000 // We only want to see those namespaces that have already been defined
4001 // within this scope, because its likely that the user is creating an
4002 // extended namespace declaration. Keep track of the most recent
4003 // definition of each namespace.
4004 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4005 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4006 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4007 NS != NSEnd; ++NS)
4008 OrigToLatest[NS->getOriginalNamespace()] = *NS;
4009
4010 // Add the most recent definition (or extended definition) of each
4011 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004012 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004013 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
4014 NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
4015 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004016 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004017 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004018 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004019 }
4020
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004021 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004022 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004023 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004024}
4025
4026void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4027 if (!CodeCompleter)
4028 return;
4029
Douglas Gregor86d9a522009-09-21 16:56:56 +00004030 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004031 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4032 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004033 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004034 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004035 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4036 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004037 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004038 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004039 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004040}
4041
Douglas Gregored8d3222009-09-18 20:05:18 +00004042void Sema::CodeCompleteOperatorName(Scope *S) {
4043 if (!CodeCompleter)
4044 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004045
John McCall0a2c5e22010-08-25 06:19:51 +00004046 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004047 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4048 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004049 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004050 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004051
Douglas Gregor86d9a522009-09-21 16:56:56 +00004052 // Add the names of overloadable operators.
4053#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4054 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004055 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004056#include "clang/Basic/OperatorKinds.def"
4057
4058 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004059 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004060 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004061 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4062 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004063
4064 // Add any type specifiers
Douglas Gregorbca403c2010-01-13 23:51:12 +00004065 AddTypeSpecifierResults(getLangOptions(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004066 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004067
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004068 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004069 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004070 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004071}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004072
Douglas Gregor0133f522010-08-28 00:00:50 +00004073void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004074 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004075 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004076 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004077 CXXConstructorDecl *Constructor
4078 = static_cast<CXXConstructorDecl *>(ConstructorD);
4079 if (!Constructor)
4080 return;
4081
Douglas Gregor218937c2011-02-01 19:23:04 +00004082 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004083 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004084 Results.EnterNewScope();
4085
4086 // Fill in any already-initialized fields or base classes.
4087 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4088 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4089 for (unsigned I = 0; I != NumInitializers; ++I) {
4090 if (Initializers[I]->isBaseInitializer())
4091 InitializedBases.insert(
4092 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4093 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004094 InitializedFields.insert(cast<FieldDecl>(
4095 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004096 }
4097
4098 // Add completions for base classes.
Douglas Gregor218937c2011-02-01 19:23:04 +00004099 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004100 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004101 CXXRecordDecl *ClassDecl = Constructor->getParent();
4102 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4103 BaseEnd = ClassDecl->bases_end();
4104 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004105 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4106 SawLastInitializer
4107 = NumInitializers > 0 &&
4108 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4109 Context.hasSameUnqualifiedType(Base->getType(),
4110 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004111 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004112 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004113
Douglas Gregor218937c2011-02-01 19:23:04 +00004114 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004115 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004116 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004117 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4118 Builder.AddPlaceholderChunk("args");
4119 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4120 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004121 SawLastInitializer? CCP_NextInitializer
4122 : CCP_MemberDeclaration));
4123 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004124 }
4125
4126 // Add completions for virtual base classes.
4127 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4128 BaseEnd = ClassDecl->vbases_end();
4129 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004130 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4131 SawLastInitializer
4132 = NumInitializers > 0 &&
4133 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4134 Context.hasSameUnqualifiedType(Base->getType(),
4135 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004136 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004137 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004138
Douglas Gregor218937c2011-02-01 19:23:04 +00004139 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004140 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004141 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004142 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4143 Builder.AddPlaceholderChunk("args");
4144 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4145 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004146 SawLastInitializer? CCP_NextInitializer
4147 : CCP_MemberDeclaration));
4148 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004149 }
4150
4151 // Add completions for members.
4152 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4153 FieldEnd = ClassDecl->field_end();
4154 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004155 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4156 SawLastInitializer
4157 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004158 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
4159 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004160 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004161 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004162
4163 if (!Field->getDeclName())
4164 continue;
4165
Douglas Gregordae68752011-02-01 22:57:45 +00004166 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004167 Field->getIdentifier()->getName()));
4168 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4169 Builder.AddPlaceholderChunk("args");
4170 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4171 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004172 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004173 : CCP_MemberDeclaration,
4174 CXCursor_MemberRef));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004175 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004176 }
4177 Results.ExitScope();
4178
Douglas Gregor52779fb2010-09-23 23:01:17 +00004179 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004180 Results.data(), Results.size());
4181}
4182
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004183// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
4184// true or false.
4185#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorbca403c2010-01-13 23:51:12 +00004186static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004187 ResultBuilder &Results,
4188 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004189 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004190 // Since we have an implementation, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004191 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004192
Douglas Gregor218937c2011-02-01 19:23:04 +00004193 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004194 if (LangOpts.ObjC2) {
4195 // @dynamic
Douglas Gregor218937c2011-02-01 19:23:04 +00004196 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
4197 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4198 Builder.AddPlaceholderChunk("property");
4199 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004200
4201 // @synthesize
Douglas Gregor218937c2011-02-01 19:23:04 +00004202 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
4203 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4204 Builder.AddPlaceholderChunk("property");
4205 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004206 }
4207}
4208
Douglas Gregorbca403c2010-01-13 23:51:12 +00004209static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004210 ResultBuilder &Results,
4211 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004212 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004213
4214 // Since we have an interface or protocol, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004215 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004216
4217 if (LangOpts.ObjC2) {
4218 // @property
Douglas Gregora4477812010-01-14 16:01:26 +00004219 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004220
4221 // @required
Douglas Gregora4477812010-01-14 16:01:26 +00004222 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004223
4224 // @optional
Douglas Gregora4477812010-01-14 16:01:26 +00004225 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004226 }
4227}
4228
Douglas Gregorbca403c2010-01-13 23:51:12 +00004229static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004230 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004231 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004232
4233 // @class name ;
Douglas Gregor218937c2011-02-01 19:23:04 +00004234 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
4235 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4236 Builder.AddPlaceholderChunk("name");
4237 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004238
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004239 if (Results.includeCodePatterns()) {
4240 // @interface name
4241 // FIXME: Could introduce the whole pattern, including superclasses and
4242 // such.
Douglas Gregor218937c2011-02-01 19:23:04 +00004243 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
4244 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4245 Builder.AddPlaceholderChunk("class");
4246 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004247
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004248 // @protocol name
Douglas Gregor218937c2011-02-01 19:23:04 +00004249 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4250 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4251 Builder.AddPlaceholderChunk("protocol");
4252 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004253
4254 // @implementation name
Douglas Gregor218937c2011-02-01 19:23:04 +00004255 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
4256 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4257 Builder.AddPlaceholderChunk("class");
4258 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004259 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004260
4261 // @compatibility_alias name
Douglas Gregor218937c2011-02-01 19:23:04 +00004262 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
4263 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4264 Builder.AddPlaceholderChunk("alias");
4265 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4266 Builder.AddPlaceholderChunk("class");
4267 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004268}
4269
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004270void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004271 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004272 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4273 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004274 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004275 if (isa<ObjCImplDecl>(CurContext))
Douglas Gregorbca403c2010-01-13 23:51:12 +00004276 AddObjCImplementationResults(getLangOptions(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004277 else if (CurContext->isObjCContainer())
Douglas Gregorbca403c2010-01-13 23:51:12 +00004278 AddObjCInterfaceResults(getLangOptions(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004279 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004280 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004281 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004282 HandleCodeCompleteResults(this, CodeCompleter,
4283 CodeCompletionContext::CCC_Other,
4284 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004285}
4286
Douglas Gregorbca403c2010-01-13 23:51:12 +00004287static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004288 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004289 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004290
4291 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004292 const char *EncodeType = "char[]";
4293 if (Results.getSema().getLangOptions().CPlusPlus ||
4294 Results.getSema().getLangOptions().ConstStrings)
4295 EncodeType = " const char[]";
4296 Builder.AddResultTypeChunk(EncodeType);
Douglas Gregor218937c2011-02-01 19:23:04 +00004297 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
4298 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4299 Builder.AddPlaceholderChunk("type-name");
4300 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4301 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004302
4303 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004304 Builder.AddResultTypeChunk("Protocol *");
Douglas Gregor218937c2011-02-01 19:23:04 +00004305 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4306 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4307 Builder.AddPlaceholderChunk("protocol-name");
4308 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4309 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004310
4311 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004312 Builder.AddResultTypeChunk("SEL");
Douglas Gregor218937c2011-02-01 19:23:04 +00004313 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
4314 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4315 Builder.AddPlaceholderChunk("selector");
4316 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4317 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004318}
4319
Douglas Gregorbca403c2010-01-13 23:51:12 +00004320static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004321 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004322 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004323
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004324 if (Results.includeCodePatterns()) {
4325 // @try { statements } @catch ( declaration ) { statements } @finally
4326 // { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004327 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
4328 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4329 Builder.AddPlaceholderChunk("statements");
4330 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4331 Builder.AddTextChunk("@catch");
4332 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4333 Builder.AddPlaceholderChunk("parameter");
4334 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4335 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4336 Builder.AddPlaceholderChunk("statements");
4337 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4338 Builder.AddTextChunk("@finally");
4339 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4340 Builder.AddPlaceholderChunk("statements");
4341 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4342 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004343 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004344
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004345 // @throw
Douglas Gregor218937c2011-02-01 19:23:04 +00004346 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
4347 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4348 Builder.AddPlaceholderChunk("expression");
4349 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004350
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004351 if (Results.includeCodePatterns()) {
4352 // @synchronized ( expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004353 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
4354 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4355 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4356 Builder.AddPlaceholderChunk("expression");
4357 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4358 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4359 Builder.AddPlaceholderChunk("statements");
4360 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4361 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004362 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004363}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004364
Douglas Gregorbca403c2010-01-13 23:51:12 +00004365static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004366 ResultBuilder &Results,
4367 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004368 typedef CodeCompletionResult Result;
Douglas Gregora4477812010-01-14 16:01:26 +00004369 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
4370 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
4371 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004372 if (LangOpts.ObjC2)
Douglas Gregora4477812010-01-14 16:01:26 +00004373 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004374}
4375
4376void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004377 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4378 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004379 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004380 AddObjCVisibilityResults(getLangOptions(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004381 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004382 HandleCodeCompleteResults(this, CodeCompleter,
4383 CodeCompletionContext::CCC_Other,
4384 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004385}
4386
4387void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004388 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4389 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004390 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004391 AddObjCStatementResults(Results, false);
4392 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004393 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004394 HandleCodeCompleteResults(this, CodeCompleter,
4395 CodeCompletionContext::CCC_Other,
4396 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004397}
4398
4399void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004400 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4401 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004402 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004403 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004404 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004405 HandleCodeCompleteResults(this, CodeCompleter,
4406 CodeCompletionContext::CCC_Other,
4407 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004408}
4409
Douglas Gregor988358f2009-11-19 00:14:45 +00004410/// \brief Determine whether the addition of the given flag to an Objective-C
4411/// property's attributes will cause a conflict.
4412static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4413 // Check if we've already added this flag.
4414 if (Attributes & NewFlag)
4415 return true;
4416
4417 Attributes |= NewFlag;
4418
4419 // Check for collisions with "readonly".
4420 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4421 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4422 ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004423 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004424 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004425 ObjCDeclSpec::DQ_PR_retain |
4426 ObjCDeclSpec::DQ_PR_strong)))
Douglas Gregor988358f2009-11-19 00:14:45 +00004427 return true;
4428
John McCallf85e1932011-06-15 23:02:42 +00004429 // Check for more than one of { assign, copy, retain, strong }.
Douglas Gregor988358f2009-11-19 00:14:45 +00004430 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004431 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004432 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004433 ObjCDeclSpec::DQ_PR_retain|
4434 ObjCDeclSpec::DQ_PR_strong);
Douglas Gregor988358f2009-11-19 00:14:45 +00004435 if (AssignCopyRetMask &&
4436 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004437 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004438 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004439 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
4440 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
Douglas Gregor988358f2009-11-19 00:14:45 +00004441 return true;
4442
4443 return false;
4444}
4445
Douglas Gregora93b1082009-11-18 23:08:07 +00004446void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004447 if (!CodeCompleter)
4448 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004449
Steve Naroffece8e712009-10-08 21:55:05 +00004450 unsigned Attributes = ODS.getPropertyAttributes();
4451
John McCall0a2c5e22010-08-25 06:19:51 +00004452 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004453 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4454 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004455 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004456 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004457 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004458 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004459 Results.AddResult(CodeCompletionResult("assign"));
John McCallf85e1932011-06-15 23:02:42 +00004460 if (!ObjCPropertyFlagConflicts(Attributes,
4461 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4462 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004463 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004464 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004465 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004466 Results.AddResult(CodeCompletionResult("retain"));
John McCallf85e1932011-06-15 23:02:42 +00004467 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4468 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004469 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004470 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004471 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004472 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004473 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4474 Results.AddResult(CodeCompletionResult("atomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004475 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004476 CodeCompletionBuilder Setter(Results.getAllocator());
4477 Setter.AddTypedTextChunk("setter");
4478 Setter.AddTextChunk(" = ");
4479 Setter.AddPlaceholderChunk("method");
4480 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004481 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004482 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004483 CodeCompletionBuilder Getter(Results.getAllocator());
4484 Getter.AddTypedTextChunk("getter");
4485 Getter.AddTextChunk(" = ");
4486 Getter.AddPlaceholderChunk("method");
4487 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004488 }
Steve Naroffece8e712009-10-08 21:55:05 +00004489 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004490 HandleCodeCompleteResults(this, CodeCompleter,
4491 CodeCompletionContext::CCC_Other,
4492 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004493}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004494
Douglas Gregor4ad96852009-11-19 07:41:15 +00004495/// \brief Descripts the kind of Objective-C method that we want to find
4496/// via code completion.
4497enum ObjCMethodKind {
4498 MK_Any, //< Any kind of method, provided it means other specified criteria.
4499 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4500 MK_OneArgSelector //< One-argument selector.
4501};
4502
Douglas Gregor458433d2010-08-26 15:07:07 +00004503static bool isAcceptableObjCSelector(Selector Sel,
4504 ObjCMethodKind WantKind,
4505 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004506 unsigned NumSelIdents,
4507 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004508 if (NumSelIdents > Sel.getNumArgs())
4509 return false;
4510
4511 switch (WantKind) {
4512 case MK_Any: break;
4513 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4514 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4515 }
4516
Douglas Gregorcf544262010-11-17 21:36:08 +00004517 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4518 return false;
4519
Douglas Gregor458433d2010-08-26 15:07:07 +00004520 for (unsigned I = 0; I != NumSelIdents; ++I)
4521 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4522 return false;
4523
4524 return true;
4525}
4526
Douglas Gregor4ad96852009-11-19 07:41:15 +00004527static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4528 ObjCMethodKind WantKind,
4529 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004530 unsigned NumSelIdents,
4531 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004532 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004533 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004534}
Douglas Gregord36adf52010-09-16 16:06:31 +00004535
4536namespace {
4537 /// \brief A set of selectors, which is used to avoid introducing multiple
4538 /// completions with the same selector into the result set.
4539 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4540}
4541
Douglas Gregor36ecb042009-11-17 23:22:23 +00004542/// \brief Add all of the Objective-C methods in the given Objective-C
4543/// container to the set of results.
4544///
4545/// The container will be a class, protocol, category, or implementation of
4546/// any of the above. This mether will recurse to include methods from
4547/// the superclasses of classes along with their categories, protocols, and
4548/// implementations.
4549///
4550/// \param Container the container in which we'll look to find methods.
4551///
4552/// \param WantInstance whether to add instance methods (only); if false, this
4553/// routine will add factory methods (only).
4554///
4555/// \param CurContext the context in which we're performing the lookup that
4556/// finds methods.
4557///
Douglas Gregorcf544262010-11-17 21:36:08 +00004558/// \param AllowSameLength Whether we allow a method to be added to the list
4559/// when it has the same number of parameters as we have selector identifiers.
4560///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004561/// \param Results the structure into which we'll add results.
4562static void AddObjCMethods(ObjCContainerDecl *Container,
4563 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004564 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004565 IdentifierInfo **SelIdents,
4566 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004567 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004568 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004569 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004570 ResultBuilder &Results,
4571 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004572 typedef CodeCompletionResult Result;
Douglas Gregor36ecb042009-11-17 23:22:23 +00004573 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4574 MEnd = Container->meth_end();
4575 M != MEnd; ++M) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004576 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4577 // Check whether the selector identifiers we've been given are a
4578 // subset of the identifiers for this particular method.
Douglas Gregorcf544262010-11-17 21:36:08 +00004579 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4580 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004581 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004582
Douglas Gregord36adf52010-09-16 16:06:31 +00004583 if (!Selectors.insert((*M)->getSelector()))
4584 continue;
4585
Douglas Gregord3c68542009-11-19 01:08:35 +00004586 Result R = Result(*M, 0);
4587 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004588 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004589 if (!InOriginalClass)
4590 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004591 Results.MaybeAddResult(R, CurContext);
4592 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004593 }
4594
Douglas Gregore396c7b2010-09-16 15:34:59 +00004595 // Visit the protocols of protocols.
4596 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004597 if (Protocol->hasDefinition()) {
4598 const ObjCList<ObjCProtocolDecl> &Protocols
4599 = Protocol->getReferencedProtocols();
4600 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4601 E = Protocols.end();
4602 I != E; ++I)
4603 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4604 NumSelIdents, CurContext, Selectors, AllowSameLength,
4605 Results, false);
4606 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004607 }
4608
Douglas Gregor36ecb042009-11-17 23:22:23 +00004609 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004610 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004611 return;
4612
4613 // Add methods in protocols.
4614 const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols();
4615 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4616 E = Protocols.end();
4617 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004618 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004619 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004620
4621 // Add methods in categories.
4622 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4623 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004624 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004625 NumSelIdents, CurContext, Selectors, AllowSameLength,
4626 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004627
4628 // Add a categories protocol methods.
4629 const ObjCList<ObjCProtocolDecl> &Protocols
4630 = CatDecl->getReferencedProtocols();
4631 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4632 E = Protocols.end();
4633 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004634 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004635 NumSelIdents, CurContext, Selectors, AllowSameLength,
4636 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004637
4638 // Add methods in category implementations.
4639 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004640 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004641 NumSelIdents, CurContext, Selectors, AllowSameLength,
4642 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004643 }
4644
4645 // Add methods in superclass.
4646 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004647 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004648 SelIdents, NumSelIdents, CurContext, Selectors,
4649 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004650
4651 // Add methods in our implementation, if any.
4652 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004653 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004654 NumSelIdents, CurContext, Selectors, AllowSameLength,
4655 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004656}
4657
4658
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004659void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004660 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004661
4662 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004663 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004664 if (!Class) {
4665 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004666 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004667 Class = Category->getClassInterface();
4668
4669 if (!Class)
4670 return;
4671 }
4672
4673 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004674 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4675 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004676 Results.EnterNewScope();
4677
Douglas Gregord36adf52010-09-16 16:06:31 +00004678 VisitedSelectorSet Selectors;
4679 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004680 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004681 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004682 HandleCodeCompleteResults(this, CodeCompleter,
4683 CodeCompletionContext::CCC_Other,
4684 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004685}
4686
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004687void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004688 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004689
4690 // Try to find the interface where setters might live.
4691 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004692 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004693 if (!Class) {
4694 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004695 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004696 Class = Category->getClassInterface();
4697
4698 if (!Class)
4699 return;
4700 }
4701
4702 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004703 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4704 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004705 Results.EnterNewScope();
4706
Douglas Gregord36adf52010-09-16 16:06:31 +00004707 VisitedSelectorSet Selectors;
4708 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004709 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004710
4711 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004712 HandleCodeCompleteResults(this, CodeCompleter,
4713 CodeCompletionContext::CCC_Other,
4714 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004715}
4716
Douglas Gregorafc45782011-02-15 22:19:42 +00004717void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4718 bool IsParameter) {
John McCall0a2c5e22010-08-25 06:19:51 +00004719 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004720 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4721 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004722 Results.EnterNewScope();
4723
4724 // Add context-sensitive, Objective-C parameter-passing keywords.
4725 bool AddedInOut = false;
4726 if ((DS.getObjCDeclQualifier() &
4727 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4728 Results.AddResult("in");
4729 Results.AddResult("inout");
4730 AddedInOut = true;
4731 }
4732 if ((DS.getObjCDeclQualifier() &
4733 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4734 Results.AddResult("out");
4735 if (!AddedInOut)
4736 Results.AddResult("inout");
4737 }
4738 if ((DS.getObjCDeclQualifier() &
4739 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4740 ObjCDeclSpec::DQ_Oneway)) == 0) {
4741 Results.AddResult("bycopy");
4742 Results.AddResult("byref");
4743 Results.AddResult("oneway");
4744 }
4745
Douglas Gregorafc45782011-02-15 22:19:42 +00004746 // If we're completing the return type of an Objective-C method and the
4747 // identifier IBAction refers to a macro, provide a completion item for
4748 // an action, e.g.,
4749 // IBAction)<#selector#>:(id)sender
4750 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4751 Context.Idents.get("IBAction").hasMacroDefinition()) {
4752 typedef CodeCompletionString::Chunk Chunk;
4753 CodeCompletionBuilder Builder(Results.getAllocator(), CCP_CodePattern,
4754 CXAvailability_Available);
4755 Builder.AddTypedTextChunk("IBAction");
4756 Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
4757 Builder.AddPlaceholderChunk("selector");
4758 Builder.AddChunk(Chunk(CodeCompletionString::CK_Colon));
4759 Builder.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
4760 Builder.AddTextChunk("id");
4761 Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
4762 Builder.AddTextChunk("sender");
4763 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4764 }
4765
Douglas Gregord32b0222010-08-24 01:06:58 +00004766 // Add various builtin type names and specifiers.
4767 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4768 Results.ExitScope();
4769
4770 // Add the various type names
4771 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4772 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4773 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4774 CodeCompleter->includeGlobals());
4775
4776 if (CodeCompleter->includeMacros())
4777 AddMacroResults(PP, Results);
4778
4779 HandleCodeCompleteResults(this, CodeCompleter,
4780 CodeCompletionContext::CCC_Type,
4781 Results.data(), Results.size());
4782}
4783
Douglas Gregor22f56992010-04-06 19:22:33 +00004784/// \brief When we have an expression with type "id", we may assume
4785/// that it has some more-specific class type based on knowledge of
4786/// common uses of Objective-C. This routine returns that class type,
4787/// or NULL if no better result could be determined.
4788static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004789 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004790 if (!Msg)
4791 return 0;
4792
4793 Selector Sel = Msg->getSelector();
4794 if (Sel.isNull())
4795 return 0;
4796
4797 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4798 if (!Id)
4799 return 0;
4800
4801 ObjCMethodDecl *Method = Msg->getMethodDecl();
4802 if (!Method)
4803 return 0;
4804
4805 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004806 ObjCInterfaceDecl *IFace = 0;
4807 switch (Msg->getReceiverKind()) {
4808 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004809 if (const ObjCObjectType *ObjType
4810 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4811 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004812 break;
4813
4814 case ObjCMessageExpr::Instance: {
4815 QualType T = Msg->getInstanceReceiver()->getType();
4816 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4817 IFace = Ptr->getInterfaceDecl();
4818 break;
4819 }
4820
4821 case ObjCMessageExpr::SuperInstance:
4822 case ObjCMessageExpr::SuperClass:
4823 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00004824 }
4825
4826 if (!IFace)
4827 return 0;
4828
4829 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4830 if (Method->isInstanceMethod())
4831 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4832 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00004833 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00004834 .Case("autorelease", IFace)
4835 .Case("copy", IFace)
4836 .Case("copyWithZone", IFace)
4837 .Case("mutableCopy", IFace)
4838 .Case("mutableCopyWithZone", IFace)
4839 .Case("awakeFromCoder", IFace)
4840 .Case("replacementObjectFromCoder", IFace)
4841 .Case("class", IFace)
4842 .Case("classForCoder", IFace)
4843 .Case("superclass", Super)
4844 .Default(0);
4845
4846 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4847 .Case("new", IFace)
4848 .Case("alloc", IFace)
4849 .Case("allocWithZone", IFace)
4850 .Case("class", IFace)
4851 .Case("superclass", Super)
4852 .Default(0);
4853}
4854
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004855// Add a special completion for a message send to "super", which fills in the
4856// most likely case of forwarding all of our arguments to the superclass
4857// function.
4858///
4859/// \param S The semantic analysis object.
4860///
4861/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4862/// the "super" keyword. Otherwise, we just need to provide the arguments.
4863///
4864/// \param SelIdents The identifiers in the selector that have already been
4865/// provided as arguments for a send to "super".
4866///
4867/// \param NumSelIdents The number of identifiers in \p SelIdents.
4868///
4869/// \param Results The set of results to augment.
4870///
4871/// \returns the Objective-C method declaration that would be invoked by
4872/// this "super" completion. If NULL, no completion was added.
4873static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4874 IdentifierInfo **SelIdents,
4875 unsigned NumSelIdents,
4876 ResultBuilder &Results) {
4877 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
4878 if (!CurMethod)
4879 return 0;
4880
4881 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
4882 if (!Class)
4883 return 0;
4884
4885 // Try to find a superclass method with the same selector.
4886 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00004887 while ((Class = Class->getSuperClass()) && !SuperMethod) {
4888 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004889 SuperMethod = Class->getMethod(CurMethod->getSelector(),
4890 CurMethod->isInstanceMethod());
4891
Douglas Gregor78bcd912011-02-16 00:51:18 +00004892 // Check in categories or class extensions.
4893 if (!SuperMethod) {
4894 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
4895 Category = Category->getNextClassCategory())
4896 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
4897 CurMethod->isInstanceMethod())))
4898 break;
4899 }
4900 }
4901
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004902 if (!SuperMethod)
4903 return 0;
4904
4905 // Check whether the superclass method has the same signature.
4906 if (CurMethod->param_size() != SuperMethod->param_size() ||
4907 CurMethod->isVariadic() != SuperMethod->isVariadic())
4908 return 0;
4909
4910 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
4911 CurPEnd = CurMethod->param_end(),
4912 SuperP = SuperMethod->param_begin();
4913 CurP != CurPEnd; ++CurP, ++SuperP) {
4914 // Make sure the parameter types are compatible.
4915 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
4916 (*SuperP)->getType()))
4917 return 0;
4918
4919 // Make sure we have a parameter name to forward!
4920 if (!(*CurP)->getIdentifier())
4921 return 0;
4922 }
4923
4924 // We have a superclass method. Now, form the send-to-super completion.
Douglas Gregor218937c2011-02-01 19:23:04 +00004925 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004926
4927 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00004928 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
4929 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004930
4931 // If we need the "super" keyword, add it (plus some spacing).
4932 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004933 Builder.AddTypedTextChunk("super");
4934 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004935 }
4936
4937 Selector Sel = CurMethod->getSelector();
4938 if (Sel.isUnarySelector()) {
4939 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00004940 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004941 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004942 else
Douglas Gregordae68752011-02-01 22:57:45 +00004943 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004944 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004945 } else {
4946 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
4947 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
4948 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004949 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004950
4951 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004952 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004953 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004954 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004955 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004956 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004957 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004958 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00004959 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004960 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004961 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00004962 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004963 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004964 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00004965 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004966 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004967 }
4968 }
4969 }
4970
Douglas Gregor218937c2011-02-01 19:23:04 +00004971 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004972 SuperMethod->isInstanceMethod()
4973 ? CXCursor_ObjCInstanceMethodDecl
4974 : CXCursor_ObjCClassMethodDecl));
4975 return SuperMethod;
4976}
4977
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004978void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004979 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004980 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4981 CodeCompletionContext::CCC_ObjCMessageReceiver,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004982 &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004983
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004984 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4985 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00004986 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4987 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004988
4989 // If we are in an Objective-C method inside a class that has a superclass,
4990 // add "super" as an option.
4991 if (ObjCMethodDecl *Method = getCurMethodDecl())
4992 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004993 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004994 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004995
4996 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
4997 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004998
4999 Results.ExitScope();
5000
5001 if (CodeCompleter->includeMacros())
5002 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005003 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005004 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005005
5006}
5007
Douglas Gregor2725ca82010-04-21 19:57:20 +00005008void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5009 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005010 unsigned NumSelIdents,
5011 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005012 ObjCInterfaceDecl *CDecl = 0;
5013 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5014 // Figure out which interface we're in.
5015 CDecl = CurMethod->getClassInterface();
5016 if (!CDecl)
5017 return;
5018
5019 // Find the superclass of this class.
5020 CDecl = CDecl->getSuperClass();
5021 if (!CDecl)
5022 return;
5023
5024 if (CurMethod->isInstanceMethod()) {
5025 // We are inside an instance method, which means that the message
5026 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005027 // current object.
5028 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005029 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005030 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005031 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005032 }
5033
5034 // Fall through to send to the superclass in CDecl.
5035 } else {
5036 // "super" may be the name of a type or variable. Figure out which
5037 // it is.
5038 IdentifierInfo *Super = &Context.Idents.get("super");
5039 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5040 LookupOrdinaryName);
5041 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5042 // "super" names an interface. Use it.
5043 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005044 if (const ObjCObjectType *Iface
5045 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5046 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005047 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5048 // "super" names an unresolved type; we can't be more specific.
5049 } else {
5050 // Assume that "super" names some kind of value and parse that way.
5051 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005052 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005053 UnqualifiedId id;
5054 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005055 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5056 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005057 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005058 SelIdents, NumSelIdents,
5059 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005060 }
5061
5062 // Fall through
5063 }
5064
John McCallb3d87482010-08-24 05:47:05 +00005065 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005066 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005067 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005068 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005069 NumSelIdents, AtArgumentExpression,
5070 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005071}
5072
Douglas Gregorb9d77572010-09-21 00:03:25 +00005073/// \brief Given a set of code-completion results for the argument of a message
5074/// send, determine the preferred type (if any) for that argument expression.
5075static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5076 unsigned NumSelIdents) {
5077 typedef CodeCompletionResult Result;
5078 ASTContext &Context = Results.getSema().Context;
5079
5080 QualType PreferredType;
5081 unsigned BestPriority = CCP_Unlikely * 2;
5082 Result *ResultsData = Results.data();
5083 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5084 Result &R = ResultsData[I];
5085 if (R.Kind == Result::RK_Declaration &&
5086 isa<ObjCMethodDecl>(R.Declaration)) {
5087 if (R.Priority <= BestPriority) {
5088 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5089 if (NumSelIdents <= Method->param_size()) {
5090 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5091 ->getType();
5092 if (R.Priority < BestPriority || PreferredType.isNull()) {
5093 BestPriority = R.Priority;
5094 PreferredType = MyPreferredType;
5095 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5096 MyPreferredType)) {
5097 PreferredType = QualType();
5098 }
5099 }
5100 }
5101 }
5102 }
5103
5104 return PreferredType;
5105}
5106
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005107static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5108 ParsedType Receiver,
5109 IdentifierInfo **SelIdents,
5110 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005111 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005112 bool IsSuper,
5113 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005114 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005115 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005116
Douglas Gregor24a069f2009-11-17 17:59:40 +00005117 // If the given name refers to an interface type, retrieve the
5118 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005119 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005120 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005121 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005122 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5123 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005124 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005125
Douglas Gregor36ecb042009-11-17 23:22:23 +00005126 // Add all of the factory methods in this Objective-C class, its protocols,
5127 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005128 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005129
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005130 // If this is a send-to-super, try to add the special "super" send
5131 // completion.
5132 if (IsSuper) {
5133 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005134 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5135 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005136 Results.Ignore(SuperMethod);
5137 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005138
Douglas Gregor265f7492010-08-27 15:29:55 +00005139 // If we're inside an Objective-C method definition, prefer its selector to
5140 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005141 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005142 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005143
Douglas Gregord36adf52010-09-16 16:06:31 +00005144 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005145 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005146 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005147 SemaRef.CurContext, Selectors, AtArgumentExpression,
5148 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005149 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005150 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005151
Douglas Gregor719770d2010-04-06 17:30:22 +00005152 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005153 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005154 if (SemaRef.ExternalSource) {
5155 for (uint32_t I = 0,
5156 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005157 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005158 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5159 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005160 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005161
5162 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005163 }
5164 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005165
5166 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5167 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005168 M != MEnd; ++M) {
5169 for (ObjCMethodList *MethList = &M->second.second;
5170 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005171 MethList = MethList->Next) {
5172 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5173 NumSelIdents))
5174 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005175
Douglas Gregor13438f92010-04-06 16:40:00 +00005176 Result R(MethList->Method, 0);
5177 R.StartParameter = NumSelIdents;
5178 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005179 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005180 }
5181 }
5182 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005183
5184 Results.ExitScope();
5185}
Douglas Gregor13438f92010-04-06 16:40:00 +00005186
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005187void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5188 IdentifierInfo **SelIdents,
5189 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005190 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005191 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005192
5193 QualType T = this->GetTypeFromParser(Receiver);
5194
Douglas Gregor218937c2011-02-01 19:23:04 +00005195 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005196 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005197 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005198
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005199 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5200 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005201
5202 // If we're actually at the argument expression (rather than prior to the
5203 // selector), we're actually performing code completion for an expression.
5204 // Determine whether we have a single, best method. If so, we can
5205 // code-complete the expression using the corresponding parameter type as
5206 // our preferred type, improving completion results.
5207 if (AtArgumentExpression) {
5208 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005209 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005210 if (PreferredType.isNull())
5211 CodeCompleteOrdinaryName(S, PCC_Expression);
5212 else
5213 CodeCompleteExpression(S, PreferredType);
5214 return;
5215 }
5216
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005217 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005218 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005219 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005220}
5221
Richard Trieuf81e5a92011-09-09 02:00:50 +00005222void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005223 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005224 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005225 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005226 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005227 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005228
5229 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005230
Douglas Gregor36ecb042009-11-17 23:22:23 +00005231 // If necessary, apply function/array conversion to the receiver.
5232 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005233 if (RecExpr) {
5234 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5235 if (Conv.isInvalid()) // conversion failed. bail.
5236 return;
5237 RecExpr = Conv.take();
5238 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005239 QualType ReceiverType = RecExpr? RecExpr->getType()
5240 : Super? Context.getObjCObjectPointerType(
5241 Context.getObjCInterfaceType(Super))
5242 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005243
Douglas Gregorda892642010-11-08 21:12:30 +00005244 // If we're messaging an expression with type "id" or "Class", check
5245 // whether we know something special about the receiver that allows
5246 // us to assume a more-specific receiver type.
5247 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5248 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5249 if (ReceiverType->isObjCClassType())
5250 return CodeCompleteObjCClassMessage(S,
5251 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5252 SelIdents, NumSelIdents,
5253 AtArgumentExpression, Super);
5254
5255 ReceiverType = Context.getObjCObjectPointerType(
5256 Context.getObjCInterfaceType(IFace));
5257 }
5258
Douglas Gregor36ecb042009-11-17 23:22:23 +00005259 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005260 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005261 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005262 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005263
Douglas Gregor36ecb042009-11-17 23:22:23 +00005264 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005265
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005266 // If this is a send-to-super, try to add the special "super" send
5267 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005268 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005269 if (ObjCMethodDecl *SuperMethod
5270 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5271 Results))
5272 Results.Ignore(SuperMethod);
5273 }
5274
Douglas Gregor265f7492010-08-27 15:29:55 +00005275 // If we're inside an Objective-C method definition, prefer its selector to
5276 // others.
5277 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5278 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005279
Douglas Gregord36adf52010-09-16 16:06:31 +00005280 // Keep track of the selectors we've already added.
5281 VisitedSelectorSet Selectors;
5282
Douglas Gregorf74a4192009-11-18 00:06:18 +00005283 // Handle messages to Class. This really isn't a message to an instance
5284 // method, so we treat it the same way we would treat a message send to a
5285 // class method.
5286 if (ReceiverType->isObjCClassType() ||
5287 ReceiverType->isObjCQualifiedClassType()) {
5288 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5289 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005290 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005291 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005292 }
5293 }
5294 // Handle messages to a qualified ID ("id<foo>").
5295 else if (const ObjCObjectPointerType *QualID
5296 = ReceiverType->getAsObjCQualifiedIdType()) {
5297 // Search protocols for instance methods.
5298 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5299 E = QualID->qual_end();
5300 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005301 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005302 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005303 }
5304 // Handle messages to a pointer to interface type.
5305 else if (const ObjCObjectPointerType *IFacePtr
5306 = ReceiverType->getAsObjCInterfacePointerType()) {
5307 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005308 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005309 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5310 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005311
5312 // Search protocols for instance methods.
5313 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5314 E = IFacePtr->qual_end();
5315 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005316 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005317 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005318 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005319 // Handle messages to "id".
5320 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005321 // We're messaging "id", so provide all instance methods we know
5322 // about as code-completion results.
5323
5324 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005325 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005326 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005327 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5328 I != N; ++I) {
5329 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005330 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005331 continue;
5332
Sebastian Redldb9d2142010-08-02 23:18:59 +00005333 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005334 }
5335 }
5336
Sebastian Redldb9d2142010-08-02 23:18:59 +00005337 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5338 MEnd = MethodPool.end();
5339 M != MEnd; ++M) {
5340 for (ObjCMethodList *MethList = &M->second.first;
5341 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005342 MethList = MethList->Next) {
5343 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5344 NumSelIdents))
5345 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005346
5347 if (!Selectors.insert(MethList->Method->getSelector()))
5348 continue;
5349
Douglas Gregor13438f92010-04-06 16:40:00 +00005350 Result R(MethList->Method, 0);
5351 R.StartParameter = NumSelIdents;
5352 R.AllParametersAreInformative = false;
5353 Results.MaybeAddResult(R, CurContext);
5354 }
5355 }
5356 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005357 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005358
5359
5360 // If we're actually at the argument expression (rather than prior to the
5361 // selector), we're actually performing code completion for an expression.
5362 // Determine whether we have a single, best method. If so, we can
5363 // code-complete the expression using the corresponding parameter type as
5364 // our preferred type, improving completion results.
5365 if (AtArgumentExpression) {
5366 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5367 NumSelIdents);
5368 if (PreferredType.isNull())
5369 CodeCompleteOrdinaryName(S, PCC_Expression);
5370 else
5371 CodeCompleteExpression(S, PreferredType);
5372 return;
5373 }
5374
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005375 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005376 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005377 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005378}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005379
Douglas Gregorfb629412010-08-23 21:17:50 +00005380void Sema::CodeCompleteObjCForCollection(Scope *S,
5381 DeclGroupPtrTy IterationVar) {
5382 CodeCompleteExpressionData Data;
5383 Data.ObjCCollection = true;
5384
5385 if (IterationVar.getAsOpaquePtr()) {
5386 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5387 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5388 if (*I)
5389 Data.IgnoreDecls.push_back(*I);
5390 }
5391 }
5392
5393 CodeCompleteExpression(S, Data);
5394}
5395
Douglas Gregor458433d2010-08-26 15:07:07 +00005396void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5397 unsigned NumSelIdents) {
5398 // If we have an external source, load the entire class method
5399 // pool from the AST file.
5400 if (ExternalSource) {
5401 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5402 I != N; ++I) {
5403 Selector Sel = ExternalSource->GetExternalSelector(I);
5404 if (Sel.isNull() || MethodPool.count(Sel))
5405 continue;
5406
5407 ReadMethodPool(Sel);
5408 }
5409 }
5410
Douglas Gregor218937c2011-02-01 19:23:04 +00005411 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5412 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005413 Results.EnterNewScope();
5414 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5415 MEnd = MethodPool.end();
5416 M != MEnd; ++M) {
5417
5418 Selector Sel = M->first;
5419 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5420 continue;
5421
Douglas Gregor218937c2011-02-01 19:23:04 +00005422 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor458433d2010-08-26 15:07:07 +00005423 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005424 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005425 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005426 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005427 continue;
5428 }
5429
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005430 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005431 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005432 if (I == NumSelIdents) {
5433 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005434 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005435 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005436 Accumulator.clear();
5437 }
5438 }
5439
Benjamin Kramera0651c52011-07-26 16:59:25 +00005440 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005441 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005442 }
Douglas Gregordae68752011-02-01 22:57:45 +00005443 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005444 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005445 }
5446 Results.ExitScope();
5447
5448 HandleCodeCompleteResults(this, CodeCompleter,
5449 CodeCompletionContext::CCC_SelectorName,
5450 Results.data(), Results.size());
5451}
5452
Douglas Gregor55385fe2009-11-18 04:19:12 +00005453/// \brief Add all of the protocol declarations that we find in the given
5454/// (translation unit) context.
5455static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005456 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005457 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005458 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005459
5460 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5461 DEnd = Ctx->decls_end();
5462 D != DEnd; ++D) {
5463 // Record any protocols we find.
5464 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005465 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005466 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005467 }
5468}
5469
5470void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5471 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005472 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5473 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005474
Douglas Gregor70c23352010-12-09 21:44:02 +00005475 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5476 Results.EnterNewScope();
5477
5478 // Tell the result set to ignore all of the protocols we have
5479 // already seen.
5480 // FIXME: This doesn't work when caching code-completion results.
5481 for (unsigned I = 0; I != NumProtocols; ++I)
5482 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5483 Protocols[I].second))
5484 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005485
Douglas Gregor70c23352010-12-09 21:44:02 +00005486 // Add all protocols.
5487 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5488 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005489
Douglas Gregor70c23352010-12-09 21:44:02 +00005490 Results.ExitScope();
5491 }
5492
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005493 HandleCodeCompleteResults(this, CodeCompleter,
5494 CodeCompletionContext::CCC_ObjCProtocolName,
5495 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005496}
5497
5498void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005499 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5500 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005501
Douglas Gregor70c23352010-12-09 21:44:02 +00005502 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5503 Results.EnterNewScope();
5504
5505 // Add all protocols.
5506 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5507 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005508
Douglas Gregor70c23352010-12-09 21:44:02 +00005509 Results.ExitScope();
5510 }
5511
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005512 HandleCodeCompleteResults(this, CodeCompleter,
5513 CodeCompletionContext::CCC_ObjCProtocolName,
5514 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005515}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005516
5517/// \brief Add all of the Objective-C interface declarations that we find in
5518/// the given (translation unit) context.
5519static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5520 bool OnlyForwardDeclarations,
5521 bool OnlyUnimplemented,
5522 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005523 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005524
5525 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5526 DEnd = Ctx->decls_end();
5527 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005528 // Record any interfaces we find.
5529 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005530 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005531 (!OnlyUnimplemented || !Class->getImplementation()))
5532 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005533 }
5534}
5535
5536void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005537 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5538 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005539 Results.EnterNewScope();
5540
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005541 if (CodeCompleter->includeGlobals()) {
5542 // Add all classes.
5543 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5544 false, Results);
5545 }
5546
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005547 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005548
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005549 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005550 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005551 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005552}
5553
Douglas Gregorc83c6872010-04-15 22:33:43 +00005554void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5555 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005556 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005557 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005558 Results.EnterNewScope();
5559
5560 // Make sure that we ignore the class we're currently defining.
5561 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005562 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005563 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005564 Results.Ignore(CurClass);
5565
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005566 if (CodeCompleter->includeGlobals()) {
5567 // Add all classes.
5568 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5569 false, Results);
5570 }
5571
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005572 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005573
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005574 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005575 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005576 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005577}
5578
5579void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005580 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5581 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005582 Results.EnterNewScope();
5583
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005584 if (CodeCompleter->includeGlobals()) {
5585 // Add all unimplemented classes.
5586 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5587 true, Results);
5588 }
5589
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005590 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005591
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005592 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005593 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005594 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005595}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005596
5597void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005598 IdentifierInfo *ClassName,
5599 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005600 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005601
Douglas Gregor218937c2011-02-01 19:23:04 +00005602 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005603 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005604
5605 // Ignore any categories we find that have already been implemented by this
5606 // interface.
5607 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5608 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005609 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005610 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5611 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5612 Category = Category->getNextClassCategory())
5613 CategoryNames.insert(Category->getIdentifier());
5614
5615 // Add all of the categories we know about.
5616 Results.EnterNewScope();
5617 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5618 for (DeclContext::decl_iterator D = TU->decls_begin(),
5619 DEnd = TU->decls_end();
5620 D != DEnd; ++D)
5621 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5622 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005623 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005624 Results.ExitScope();
5625
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005626 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005627 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005628 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005629}
5630
5631void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005632 IdentifierInfo *ClassName,
5633 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005634 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005635
5636 // Find the corresponding interface. If we couldn't find the interface, the
5637 // program itself is ill-formed. However, we'll try to be helpful still by
5638 // providing the list of all of the categories we know about.
5639 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005640 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005641 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5642 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005643 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005644
Douglas Gregor218937c2011-02-01 19:23:04 +00005645 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005646 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005647
5648 // Add all of the categories that have have corresponding interface
5649 // declarations in this class and any of its superclasses, except for
5650 // already-implemented categories in the class itself.
5651 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5652 Results.EnterNewScope();
5653 bool IgnoreImplemented = true;
5654 while (Class) {
5655 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5656 Category = Category->getNextClassCategory())
5657 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5658 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005659 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005660
5661 Class = Class->getSuperClass();
5662 IgnoreImplemented = false;
5663 }
5664 Results.ExitScope();
5665
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005666 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005667 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005668 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005669}
Douglas Gregor322328b2009-11-18 22:32:06 +00005670
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005671void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005672 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005673 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5674 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005675
5676 // Figure out where this @synthesize lives.
5677 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005678 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005679 if (!Container ||
5680 (!isa<ObjCImplementationDecl>(Container) &&
5681 !isa<ObjCCategoryImplDecl>(Container)))
5682 return;
5683
5684 // Ignore any properties that have already been implemented.
5685 for (DeclContext::decl_iterator D = Container->decls_begin(),
5686 DEnd = Container->decls_end();
5687 D != DEnd; ++D)
5688 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5689 Results.Ignore(PropertyImpl->getPropertyDecl());
5690
5691 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005692 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005693 Results.EnterNewScope();
5694 if (ObjCImplementationDecl *ClassImpl
5695 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005696 AddObjCProperties(ClassImpl->getClassInterface(), false,
5697 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005698 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005699 else
5700 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005701 false, /*AllowNullaryMethods=*/false, CurContext,
5702 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005703 Results.ExitScope();
5704
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005705 HandleCodeCompleteResults(this, CodeCompleter,
5706 CodeCompletionContext::CCC_Other,
5707 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005708}
5709
5710void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005711 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005712 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005713 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5714 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005715
5716 // Figure out where this @synthesize lives.
5717 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005718 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005719 if (!Container ||
5720 (!isa<ObjCImplementationDecl>(Container) &&
5721 !isa<ObjCCategoryImplDecl>(Container)))
5722 return;
5723
5724 // Figure out which interface we're looking into.
5725 ObjCInterfaceDecl *Class = 0;
5726 if (ObjCImplementationDecl *ClassImpl
5727 = dyn_cast<ObjCImplementationDecl>(Container))
5728 Class = ClassImpl->getClassInterface();
5729 else
5730 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5731 ->getClassInterface();
5732
Douglas Gregore8426052011-04-18 14:40:46 +00005733 // Determine the type of the property we're synthesizing.
5734 QualType PropertyType = Context.getObjCIdType();
5735 if (Class) {
5736 if (ObjCPropertyDecl *Property
5737 = Class->FindPropertyDeclaration(PropertyName)) {
5738 PropertyType
5739 = Property->getType().getNonReferenceType().getUnqualifiedType();
5740
5741 // Give preference to ivars
5742 Results.setPreferredType(PropertyType);
5743 }
5744 }
5745
Douglas Gregor322328b2009-11-18 22:32:06 +00005746 // Add all of the instance variables in this class and its superclasses.
5747 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005748 bool SawSimilarlyNamedIvar = false;
5749 std::string NameWithPrefix;
5750 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005751 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005752 std::string NameWithSuffix = PropertyName->getName().str();
5753 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005754 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005755 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5756 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005757 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5758
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005759 // Determine whether we've seen an ivar with a name similar to the
5760 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005761 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005762 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005763 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005764 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005765
5766 // Reduce the priority of this result by one, to give it a slight
5767 // advantage over other results whose names don't match so closely.
5768 if (Results.size() &&
5769 Results.data()[Results.size() - 1].Kind
5770 == CodeCompletionResult::RK_Declaration &&
5771 Results.data()[Results.size() - 1].Declaration == Ivar)
5772 Results.data()[Results.size() - 1].Priority--;
5773 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005774 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005775 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005776
5777 if (!SawSimilarlyNamedIvar) {
5778 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005779 // an ivar of the appropriate type.
5780 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005781 typedef CodeCompletionResult Result;
5782 CodeCompletionAllocator &Allocator = Results.getAllocator();
5783 CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available);
5784
Douglas Gregor8987b232011-09-27 23:30:47 +00005785 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00005786 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005787 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005788 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5789 Results.AddResult(Result(Builder.TakeString(), Priority,
5790 CXCursor_ObjCIvarDecl));
5791 }
5792
Douglas Gregor322328b2009-11-18 22:32:06 +00005793 Results.ExitScope();
5794
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005795 HandleCodeCompleteResults(this, CodeCompleter,
5796 CodeCompletionContext::CCC_Other,
5797 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005798}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005799
Douglas Gregor408be5a2010-08-25 01:08:01 +00005800// Mapping from selectors to the methods that implement that selector, along
5801// with the "in original class" flag.
5802typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5803 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005804
5805/// \brief Find all of the methods that reside in the given container
5806/// (and its superclasses, protocols, etc.) that meet the given
5807/// criteria. Insert those methods into the map of known methods,
5808/// indexed by selector so they can be easily found.
5809static void FindImplementableMethods(ASTContext &Context,
5810 ObjCContainerDecl *Container,
5811 bool WantInstanceMethods,
5812 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00005813 KnownMethodsMap &KnownMethods,
5814 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005815 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5816 // Recurse into protocols.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00005817 if (!IFace->hasDefinition())
5818 return;
5819
Douglas Gregore8f5a172010-04-07 00:21:17 +00005820 const ObjCList<ObjCProtocolDecl> &Protocols
5821 = IFace->getReferencedProtocols();
5822 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005823 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005824 I != E; ++I)
5825 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005826 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005827
Douglas Gregorea766182010-10-18 18:21:28 +00005828 // Add methods from any class extensions and categories.
5829 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5830 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00005831 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5832 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005833 KnownMethods, false);
5834
5835 // Visit the superclass.
5836 if (IFace->getSuperClass())
5837 FindImplementableMethods(Context, IFace->getSuperClass(),
5838 WantInstanceMethods, ReturnType,
5839 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005840 }
5841
5842 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5843 // Recurse into protocols.
5844 const ObjCList<ObjCProtocolDecl> &Protocols
5845 = Category->getReferencedProtocols();
5846 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005847 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005848 I != E; ++I)
5849 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005850 KnownMethods, InOriginalClass);
5851
5852 // If this category is the original class, jump to the interface.
5853 if (InOriginalClass && Category->getClassInterface())
5854 FindImplementableMethods(Context, Category->getClassInterface(),
5855 WantInstanceMethods, ReturnType, KnownMethods,
5856 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005857 }
5858
5859 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005860 if (Protocol->hasDefinition()) {
5861 // Recurse into protocols.
5862 const ObjCList<ObjCProtocolDecl> &Protocols
5863 = Protocol->getReferencedProtocols();
5864 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5865 E = Protocols.end();
5866 I != E; ++I)
5867 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
5868 KnownMethods, false);
5869 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00005870 }
5871
5872 // Add methods in this container. This operation occurs last because
5873 // we want the methods from this container to override any methods
5874 // we've previously seen with the same selector.
5875 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
5876 MEnd = Container->meth_end();
5877 M != MEnd; ++M) {
5878 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
5879 if (!ReturnType.isNull() &&
5880 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
5881 continue;
5882
Douglas Gregor408be5a2010-08-25 01:08:01 +00005883 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005884 }
5885 }
5886}
5887
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005888/// \brief Add the parenthesized return or parameter type chunk to a code
5889/// completion string.
5890static void AddObjCPassingTypeChunk(QualType Type,
5891 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005892 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005893 CodeCompletionBuilder &Builder) {
5894 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor8987b232011-09-27 23:30:47 +00005895 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005896 Builder.getAllocator()));
5897 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5898}
5899
5900/// \brief Determine whether the given class is or inherits from a class by
5901/// the given name.
5902static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00005903 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005904 if (!Class)
5905 return false;
5906
5907 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
5908 return true;
5909
5910 return InheritsFromClassNamed(Class->getSuperClass(), Name);
5911}
5912
5913/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
5914/// Key-Value Observing (KVO).
5915static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
5916 bool IsInstanceMethod,
5917 QualType ReturnType,
5918 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00005919 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005920 ResultBuilder &Results) {
5921 IdentifierInfo *PropName = Property->getIdentifier();
5922 if (!PropName || PropName->getLength() == 0)
5923 return;
5924
Douglas Gregor8987b232011-09-27 23:30:47 +00005925 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
5926
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005927 // Builder that will create each code completion.
5928 typedef CodeCompletionResult Result;
5929 CodeCompletionAllocator &Allocator = Results.getAllocator();
5930 CodeCompletionBuilder Builder(Allocator);
5931
5932 // The selector table.
5933 SelectorTable &Selectors = Context.Selectors;
5934
5935 // The property name, copied into the code completion allocation region
5936 // on demand.
5937 struct KeyHolder {
5938 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00005939 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005940 const char *CopiedKey;
5941
Chris Lattner5f9e2722011-07-23 10:55:15 +00005942 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005943 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
5944
5945 operator const char *() {
5946 if (CopiedKey)
5947 return CopiedKey;
5948
5949 return CopiedKey = Allocator.CopyString(Key);
5950 }
5951 } Key(Allocator, PropName->getName());
5952
5953 // The uppercased name of the property name.
5954 std::string UpperKey = PropName->getName();
5955 if (!UpperKey.empty())
5956 UpperKey[0] = toupper(UpperKey[0]);
5957
5958 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
5959 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
5960 Property->getType());
5961 bool ReturnTypeMatchesVoid
5962 = ReturnType.isNull() || ReturnType->isVoidType();
5963
5964 // Add the normal accessor -(type)key.
5965 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00005966 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005967 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
5968 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00005969 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005970
5971 Builder.AddTypedTextChunk(Key);
5972 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
5973 CXCursor_ObjCInstanceMethodDecl));
5974 }
5975
5976 // If we have an integral or boolean property (or the user has provided
5977 // an integral or boolean return type), add the accessor -(type)isKey.
5978 if (IsInstanceMethod &&
5979 ((!ReturnType.isNull() &&
5980 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
5981 (ReturnType.isNull() &&
5982 (Property->getType()->isIntegerType() ||
5983 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00005984 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00005985 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00005986 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005987 if (ReturnType.isNull()) {
5988 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5989 Builder.AddTextChunk("BOOL");
5990 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5991 }
5992
5993 Builder.AddTypedTextChunk(
5994 Allocator.CopyString(SelectorId->getName()));
5995 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
5996 CXCursor_ObjCInstanceMethodDecl));
5997 }
5998 }
5999
6000 // Add the normal mutator.
6001 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6002 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006003 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006004 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006005 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006006 if (ReturnType.isNull()) {
6007 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6008 Builder.AddTextChunk("void");
6009 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6010 }
6011
6012 Builder.AddTypedTextChunk(
6013 Allocator.CopyString(SelectorId->getName()));
6014 Builder.AddTypedTextChunk(":");
Douglas Gregor8987b232011-09-27 23:30:47 +00006015 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006016 Builder.AddTextChunk(Key);
6017 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6018 CXCursor_ObjCInstanceMethodDecl));
6019 }
6020 }
6021
6022 // Indexed and unordered accessors
6023 unsigned IndexedGetterPriority = CCP_CodePattern;
6024 unsigned IndexedSetterPriority = CCP_CodePattern;
6025 unsigned UnorderedGetterPriority = CCP_CodePattern;
6026 unsigned UnorderedSetterPriority = CCP_CodePattern;
6027 if (const ObjCObjectPointerType *ObjCPointer
6028 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6029 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6030 // If this interface type is not provably derived from a known
6031 // collection, penalize the corresponding completions.
6032 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6033 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6034 if (!InheritsFromClassNamed(IFace, "NSArray"))
6035 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6036 }
6037
6038 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6039 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6040 if (!InheritsFromClassNamed(IFace, "NSSet"))
6041 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6042 }
6043 }
6044 } else {
6045 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6046 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6047 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6048 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6049 }
6050
6051 // Add -(NSUInteger)countOf<key>
6052 if (IsInstanceMethod &&
6053 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006054 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006055 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006056 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006057 if (ReturnType.isNull()) {
6058 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6059 Builder.AddTextChunk("NSUInteger");
6060 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6061 }
6062
6063 Builder.AddTypedTextChunk(
6064 Allocator.CopyString(SelectorId->getName()));
6065 Results.AddResult(Result(Builder.TakeString(),
6066 std::min(IndexedGetterPriority,
6067 UnorderedGetterPriority),
6068 CXCursor_ObjCInstanceMethodDecl));
6069 }
6070 }
6071
6072 // Indexed getters
6073 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6074 if (IsInstanceMethod &&
6075 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006076 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006077 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006078 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006079 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006080 if (ReturnType.isNull()) {
6081 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6082 Builder.AddTextChunk("id");
6083 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6084 }
6085
6086 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6087 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6088 Builder.AddTextChunk("NSUInteger");
6089 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6090 Builder.AddTextChunk("index");
6091 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6092 CXCursor_ObjCInstanceMethodDecl));
6093 }
6094 }
6095
6096 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6097 if (IsInstanceMethod &&
6098 (ReturnType.isNull() ||
6099 (ReturnType->isObjCObjectPointerType() &&
6100 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6101 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6102 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006103 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006104 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006105 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006106 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006107 if (ReturnType.isNull()) {
6108 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6109 Builder.AddTextChunk("NSArray *");
6110 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6111 }
6112
6113 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6114 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6115 Builder.AddTextChunk("NSIndexSet *");
6116 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6117 Builder.AddTextChunk("indexes");
6118 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6119 CXCursor_ObjCInstanceMethodDecl));
6120 }
6121 }
6122
6123 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6124 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006125 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006126 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006127 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006128 &Context.Idents.get("range")
6129 };
6130
Douglas Gregore74c25c2011-05-04 23:50:46 +00006131 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006132 if (ReturnType.isNull()) {
6133 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6134 Builder.AddTextChunk("void");
6135 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6136 }
6137
6138 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6139 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6140 Builder.AddPlaceholderChunk("object-type");
6141 Builder.AddTextChunk(" **");
6142 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6143 Builder.AddTextChunk("buffer");
6144 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6145 Builder.AddTypedTextChunk("range:");
6146 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6147 Builder.AddTextChunk("NSRange");
6148 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6149 Builder.AddTextChunk("inRange");
6150 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6151 CXCursor_ObjCInstanceMethodDecl));
6152 }
6153 }
6154
6155 // Mutable indexed accessors
6156
6157 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6158 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006159 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006160 IdentifierInfo *SelectorIds[2] = {
6161 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006162 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006163 };
6164
Douglas Gregore74c25c2011-05-04 23:50:46 +00006165 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006166 if (ReturnType.isNull()) {
6167 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6168 Builder.AddTextChunk("void");
6169 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6170 }
6171
6172 Builder.AddTypedTextChunk("insertObject:");
6173 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6174 Builder.AddPlaceholderChunk("object-type");
6175 Builder.AddTextChunk(" *");
6176 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6177 Builder.AddTextChunk("object");
6178 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6179 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6180 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6181 Builder.AddPlaceholderChunk("NSUInteger");
6182 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6183 Builder.AddTextChunk("index");
6184 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6185 CXCursor_ObjCInstanceMethodDecl));
6186 }
6187 }
6188
6189 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6190 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006191 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006192 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006193 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006194 &Context.Idents.get("atIndexes")
6195 };
6196
Douglas Gregore74c25c2011-05-04 23:50:46 +00006197 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006198 if (ReturnType.isNull()) {
6199 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6200 Builder.AddTextChunk("void");
6201 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6202 }
6203
6204 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6205 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6206 Builder.AddTextChunk("NSArray *");
6207 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6208 Builder.AddTextChunk("array");
6209 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6210 Builder.AddTypedTextChunk("atIndexes:");
6211 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6212 Builder.AddPlaceholderChunk("NSIndexSet *");
6213 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6214 Builder.AddTextChunk("indexes");
6215 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6216 CXCursor_ObjCInstanceMethodDecl));
6217 }
6218 }
6219
6220 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6221 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006222 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006223 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006224 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006225 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
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.AddTextChunk("NSUInteger");
6235 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6236 Builder.AddTextChunk("index");
6237 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6238 CXCursor_ObjCInstanceMethodDecl));
6239 }
6240 }
6241
6242 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6243 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006244 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006245 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006246 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006247 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006248 if (ReturnType.isNull()) {
6249 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6250 Builder.AddTextChunk("void");
6251 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6252 }
6253
6254 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6255 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6256 Builder.AddTextChunk("NSIndexSet *");
6257 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6258 Builder.AddTextChunk("indexes");
6259 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6260 CXCursor_ObjCInstanceMethodDecl));
6261 }
6262 }
6263
6264 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6265 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006266 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006267 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006268 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006269 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006270 &Context.Idents.get("withObject")
6271 };
6272
Douglas Gregore74c25c2011-05-04 23:50:46 +00006273 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006274 if (ReturnType.isNull()) {
6275 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6276 Builder.AddTextChunk("void");
6277 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6278 }
6279
6280 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6281 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6282 Builder.AddPlaceholderChunk("NSUInteger");
6283 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6284 Builder.AddTextChunk("index");
6285 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6286 Builder.AddTypedTextChunk("withObject:");
6287 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6288 Builder.AddTextChunk("id");
6289 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6290 Builder.AddTextChunk("object");
6291 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6292 CXCursor_ObjCInstanceMethodDecl));
6293 }
6294 }
6295
6296 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6297 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006298 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006299 = (Twine("replace") + UpperKey + "AtIndexes").str();
6300 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006301 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006302 &Context.Idents.get(SelectorName1),
6303 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006304 };
6305
Douglas Gregore74c25c2011-05-04 23:50:46 +00006306 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006307 if (ReturnType.isNull()) {
6308 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6309 Builder.AddTextChunk("void");
6310 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6311 }
6312
6313 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6314 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6315 Builder.AddPlaceholderChunk("NSIndexSet *");
6316 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6317 Builder.AddTextChunk("indexes");
6318 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6319 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6320 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6321 Builder.AddTextChunk("NSArray *");
6322 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6323 Builder.AddTextChunk("array");
6324 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6325 CXCursor_ObjCInstanceMethodDecl));
6326 }
6327 }
6328
6329 // Unordered getters
6330 // - (NSEnumerator *)enumeratorOfKey
6331 if (IsInstanceMethod &&
6332 (ReturnType.isNull() ||
6333 (ReturnType->isObjCObjectPointerType() &&
6334 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6335 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6336 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006337 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006338 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006339 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006340 if (ReturnType.isNull()) {
6341 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6342 Builder.AddTextChunk("NSEnumerator *");
6343 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6344 }
6345
6346 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6347 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6348 CXCursor_ObjCInstanceMethodDecl));
6349 }
6350 }
6351
6352 // - (type *)memberOfKey:(type *)object
6353 if (IsInstanceMethod &&
6354 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006355 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006356 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006357 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006358 if (ReturnType.isNull()) {
6359 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6360 Builder.AddPlaceholderChunk("object-type");
6361 Builder.AddTextChunk(" *");
6362 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6363 }
6364
6365 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6366 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6367 if (ReturnType.isNull()) {
6368 Builder.AddPlaceholderChunk("object-type");
6369 Builder.AddTextChunk(" *");
6370 } else {
6371 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006372 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006373 Builder.getAllocator()));
6374 }
6375 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6376 Builder.AddTextChunk("object");
6377 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6378 CXCursor_ObjCInstanceMethodDecl));
6379 }
6380 }
6381
6382 // Mutable unordered accessors
6383 // - (void)addKeyObject:(type *)object
6384 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006385 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006386 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006387 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006388 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006389 if (ReturnType.isNull()) {
6390 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6391 Builder.AddTextChunk("void");
6392 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6393 }
6394
6395 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6396 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6397 Builder.AddPlaceholderChunk("object-type");
6398 Builder.AddTextChunk(" *");
6399 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6400 Builder.AddTextChunk("object");
6401 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6402 CXCursor_ObjCInstanceMethodDecl));
6403 }
6404 }
6405
6406 // - (void)addKey:(NSSet *)objects
6407 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006408 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006409 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006410 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006411 if (ReturnType.isNull()) {
6412 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6413 Builder.AddTextChunk("void");
6414 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6415 }
6416
6417 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6418 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6419 Builder.AddTextChunk("NSSet *");
6420 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6421 Builder.AddTextChunk("objects");
6422 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6423 CXCursor_ObjCInstanceMethodDecl));
6424 }
6425 }
6426
6427 // - (void)removeKeyObject:(type *)object
6428 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006429 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006430 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006431 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006432 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006433 if (ReturnType.isNull()) {
6434 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6435 Builder.AddTextChunk("void");
6436 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6437 }
6438
6439 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6440 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6441 Builder.AddPlaceholderChunk("object-type");
6442 Builder.AddTextChunk(" *");
6443 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6444 Builder.AddTextChunk("object");
6445 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6446 CXCursor_ObjCInstanceMethodDecl));
6447 }
6448 }
6449
6450 // - (void)removeKey:(NSSet *)objects
6451 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006452 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006453 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006454 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006455 if (ReturnType.isNull()) {
6456 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6457 Builder.AddTextChunk("void");
6458 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6459 }
6460
6461 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6462 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6463 Builder.AddTextChunk("NSSet *");
6464 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6465 Builder.AddTextChunk("objects");
6466 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6467 CXCursor_ObjCInstanceMethodDecl));
6468 }
6469 }
6470
6471 // - (void)intersectKey:(NSSet *)objects
6472 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006473 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006474 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006475 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006476 if (ReturnType.isNull()) {
6477 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6478 Builder.AddTextChunk("void");
6479 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6480 }
6481
6482 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6483 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6484 Builder.AddTextChunk("NSSet *");
6485 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6486 Builder.AddTextChunk("objects");
6487 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6488 CXCursor_ObjCInstanceMethodDecl));
6489 }
6490 }
6491
6492 // Key-Value Observing
6493 // + (NSSet *)keyPathsForValuesAffectingKey
6494 if (!IsInstanceMethod &&
6495 (ReturnType.isNull() ||
6496 (ReturnType->isObjCObjectPointerType() &&
6497 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6498 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6499 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006500 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006501 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006502 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006503 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006504 if (ReturnType.isNull()) {
6505 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6506 Builder.AddTextChunk("NSSet *");
6507 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6508 }
6509
6510 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6511 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006512 CXCursor_ObjCClassMethodDecl));
6513 }
6514 }
6515
6516 // + (BOOL)automaticallyNotifiesObserversForKey
6517 if (!IsInstanceMethod &&
6518 (ReturnType.isNull() ||
6519 ReturnType->isIntegerType() ||
6520 ReturnType->isBooleanType())) {
6521 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006522 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006523 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6524 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6525 if (ReturnType.isNull()) {
6526 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6527 Builder.AddTextChunk("BOOL");
6528 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6529 }
6530
6531 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6532 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6533 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006534 }
6535 }
6536}
6537
Douglas Gregore8f5a172010-04-07 00:21:17 +00006538void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6539 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006540 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006541 // Determine the return type of the method we're declaring, if
6542 // provided.
6543 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006544 Decl *IDecl = 0;
6545 if (CurContext->isObjCContainer()) {
6546 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6547 IDecl = cast<Decl>(OCD);
6548 }
Douglas Gregorea766182010-10-18 18:21:28 +00006549 // Determine where we should start searching for methods.
6550 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006551 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006552 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006553 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6554 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006555 IsInImplementation = true;
6556 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006557 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006558 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006559 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006560 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006561 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006562 }
6563
6564 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006565 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006566 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006567 }
6568
Douglas Gregorea766182010-10-18 18:21:28 +00006569 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006570 HandleCodeCompleteResults(this, CodeCompleter,
6571 CodeCompletionContext::CCC_Other,
6572 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006573 return;
6574 }
6575
6576 // Find all of the methods that we could declare/implement here.
6577 KnownMethodsMap KnownMethods;
6578 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006579 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006580
Douglas Gregore8f5a172010-04-07 00:21:17 +00006581 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006582 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006583 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6584 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006585 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006586 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006587 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6588 MEnd = KnownMethods.end();
6589 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006590 ObjCMethodDecl *Method = M->second.first;
Douglas Gregor218937c2011-02-01 19:23:04 +00006591 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006592
6593 // If the result type was not already provided, add it to the
6594 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006595 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00006596 AddObjCPassingTypeChunk(Method->getResultType(), Context, Policy,
6597 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006598
6599 Selector Sel = Method->getSelector();
6600
6601 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006602 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006603 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006604
6605 // Add parameters to the pattern.
6606 unsigned I = 0;
6607 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6608 PEnd = Method->param_end();
6609 P != PEnd; (void)++P, ++I) {
6610 // Add the part of the selector name.
6611 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006612 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006613 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006614 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6615 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006616 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006617 } else
6618 break;
6619
6620 // Add the parameter type.
Douglas Gregor8987b232011-09-27 23:30:47 +00006621 AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Policy,
6622 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006623
6624 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006625 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006626 }
6627
6628 if (Method->isVariadic()) {
6629 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006630 Builder.AddChunk(CodeCompletionString::CK_Comma);
6631 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006632 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006633
Douglas Gregor447107d2010-05-28 00:57:46 +00006634 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006635 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006636 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6637 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6638 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006639 if (!Method->getResultType()->isVoidType()) {
6640 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006641 Builder.AddTextChunk("return");
6642 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6643 Builder.AddPlaceholderChunk("expression");
6644 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006645 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006646 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006647
Douglas Gregor218937c2011-02-01 19:23:04 +00006648 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6649 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006650 }
6651
Douglas Gregor408be5a2010-08-25 01:08:01 +00006652 unsigned Priority = CCP_CodePattern;
6653 if (!M->second.second)
6654 Priority += CCD_InBaseClass;
6655
Douglas Gregor218937c2011-02-01 19:23:04 +00006656 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor16ed9ad2010-08-17 16:06:07 +00006657 Method->isInstanceMethod()
6658 ? CXCursor_ObjCInstanceMethodDecl
6659 : CXCursor_ObjCClassMethodDecl));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006660 }
6661
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006662 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6663 // the properties in this class and its categories.
6664 if (Context.getLangOptions().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006665 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006666 Containers.push_back(SearchDecl);
6667
Douglas Gregore74c25c2011-05-04 23:50:46 +00006668 VisitedSelectorSet KnownSelectors;
6669 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6670 MEnd = KnownMethods.end();
6671 M != MEnd; ++M)
6672 KnownSelectors.insert(M->first);
6673
6674
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006675 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6676 if (!IFace)
6677 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6678 IFace = Category->getClassInterface();
6679
6680 if (IFace) {
6681 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6682 Category = Category->getNextClassCategory())
6683 Containers.push_back(Category);
6684 }
6685
6686 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6687 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6688 PEnd = Containers[I]->prop_end();
6689 P != PEnd; ++P) {
6690 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006691 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006692 }
6693 }
6694 }
6695
Douglas Gregore8f5a172010-04-07 00:21:17 +00006696 Results.ExitScope();
6697
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006698 HandleCodeCompleteResults(this, CodeCompleter,
6699 CodeCompletionContext::CCC_Other,
6700 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006701}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006702
6703void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6704 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006705 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006706 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006707 IdentifierInfo **SelIdents,
6708 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006709 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006710 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006711 if (ExternalSource) {
6712 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6713 I != N; ++I) {
6714 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006715 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006716 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006717
6718 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006719 }
6720 }
6721
6722 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006723 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006724 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6725 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006726
6727 if (ReturnTy)
6728 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006729
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006730 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006731 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6732 MEnd = MethodPool.end();
6733 M != MEnd; ++M) {
6734 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6735 &M->second.second;
6736 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006737 MethList = MethList->Next) {
6738 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6739 NumSelIdents))
6740 continue;
6741
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006742 if (AtParameterName) {
6743 // Suggest parameter names we've seen before.
6744 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6745 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6746 if (Param->getIdentifier()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006747 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregordae68752011-02-01 22:57:45 +00006748 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006749 Param->getIdentifier()->getName()));
6750 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006751 }
6752 }
6753
6754 continue;
6755 }
6756
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006757 Result R(MethList->Method, 0);
6758 R.StartParameter = NumSelIdents;
6759 R.AllParametersAreInformative = false;
6760 R.DeclaringEntity = true;
6761 Results.MaybeAddResult(R, CurContext);
6762 }
6763 }
6764
6765 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006766 HandleCodeCompleteResults(this, CodeCompleter,
6767 CodeCompletionContext::CCC_Other,
6768 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006769}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006770
Douglas Gregorf29c5232010-08-24 22:20:20 +00006771void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006772 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006773 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006774 Results.EnterNewScope();
6775
6776 // #if <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006777 CodeCompletionBuilder Builder(Results.getAllocator());
6778 Builder.AddTypedTextChunk("if");
6779 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6780 Builder.AddPlaceholderChunk("condition");
6781 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006782
6783 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006784 Builder.AddTypedTextChunk("ifdef");
6785 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6786 Builder.AddPlaceholderChunk("macro");
6787 Results.AddResult(Builder.TakeString());
6788
Douglas Gregorf44e8542010-08-24 19:08:16 +00006789 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006790 Builder.AddTypedTextChunk("ifndef");
6791 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6792 Builder.AddPlaceholderChunk("macro");
6793 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006794
6795 if (InConditional) {
6796 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006797 Builder.AddTypedTextChunk("elif");
6798 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6799 Builder.AddPlaceholderChunk("condition");
6800 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006801
6802 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00006803 Builder.AddTypedTextChunk("else");
6804 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006805
6806 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00006807 Builder.AddTypedTextChunk("endif");
6808 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006809 }
6810
6811 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006812 Builder.AddTypedTextChunk("include");
6813 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6814 Builder.AddTextChunk("\"");
6815 Builder.AddPlaceholderChunk("header");
6816 Builder.AddTextChunk("\"");
6817 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006818
6819 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006820 Builder.AddTypedTextChunk("include");
6821 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6822 Builder.AddTextChunk("<");
6823 Builder.AddPlaceholderChunk("header");
6824 Builder.AddTextChunk(">");
6825 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006826
6827 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006828 Builder.AddTypedTextChunk("define");
6829 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6830 Builder.AddPlaceholderChunk("macro");
6831 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006832
6833 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00006834 Builder.AddTypedTextChunk("define");
6835 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6836 Builder.AddPlaceholderChunk("macro");
6837 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6838 Builder.AddPlaceholderChunk("args");
6839 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6840 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006841
6842 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006843 Builder.AddTypedTextChunk("undef");
6844 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6845 Builder.AddPlaceholderChunk("macro");
6846 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006847
6848 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00006849 Builder.AddTypedTextChunk("line");
6850 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6851 Builder.AddPlaceholderChunk("number");
6852 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006853
6854 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00006855 Builder.AddTypedTextChunk("line");
6856 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6857 Builder.AddPlaceholderChunk("number");
6858 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6859 Builder.AddTextChunk("\"");
6860 Builder.AddPlaceholderChunk("filename");
6861 Builder.AddTextChunk("\"");
6862 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006863
6864 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006865 Builder.AddTypedTextChunk("error");
6866 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6867 Builder.AddPlaceholderChunk("message");
6868 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006869
6870 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00006871 Builder.AddTypedTextChunk("pragma");
6872 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6873 Builder.AddPlaceholderChunk("arguments");
6874 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006875
6876 if (getLangOptions().ObjC1) {
6877 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006878 Builder.AddTypedTextChunk("import");
6879 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6880 Builder.AddTextChunk("\"");
6881 Builder.AddPlaceholderChunk("header");
6882 Builder.AddTextChunk("\"");
6883 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006884
6885 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006886 Builder.AddTypedTextChunk("import");
6887 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6888 Builder.AddTextChunk("<");
6889 Builder.AddPlaceholderChunk("header");
6890 Builder.AddTextChunk(">");
6891 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006892 }
6893
6894 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006895 Builder.AddTypedTextChunk("include_next");
6896 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6897 Builder.AddTextChunk("\"");
6898 Builder.AddPlaceholderChunk("header");
6899 Builder.AddTextChunk("\"");
6900 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006901
6902 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006903 Builder.AddTypedTextChunk("include_next");
6904 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6905 Builder.AddTextChunk("<");
6906 Builder.AddPlaceholderChunk("header");
6907 Builder.AddTextChunk(">");
6908 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006909
6910 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006911 Builder.AddTypedTextChunk("warning");
6912 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6913 Builder.AddPlaceholderChunk("message");
6914 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006915
6916 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
6917 // completions for them. And __include_macros is a Clang-internal extension
6918 // that we don't want to encourage anyone to use.
6919
6920 // FIXME: we don't support #assert or #unassert, so don't suggest them.
6921 Results.ExitScope();
6922
Douglas Gregorf44e8542010-08-24 19:08:16 +00006923 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00006924 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00006925 Results.data(), Results.size());
6926}
6927
6928void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00006929 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00006930 S->getFnParent()? Sema::PCC_RecoveryInFunction
6931 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006932}
6933
Douglas Gregorf29c5232010-08-24 22:20:20 +00006934void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006935 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006936 IsDefinition? CodeCompletionContext::CCC_MacroName
6937 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006938 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
6939 // Add just the names of macros, not their arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00006940 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006941 Results.EnterNewScope();
6942 for (Preprocessor::macro_iterator M = PP.macro_begin(),
6943 MEnd = PP.macro_end();
6944 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00006945 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006946 M->first->getName()));
6947 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006948 }
6949 Results.ExitScope();
6950 } else if (IsDefinition) {
6951 // FIXME: Can we detect when the user just wrote an include guard above?
6952 }
6953
Douglas Gregor52779fb2010-09-23 23:01:17 +00006954 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006955 Results.data(), Results.size());
6956}
6957
Douglas Gregorf29c5232010-08-24 22:20:20 +00006958void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00006959 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006960 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00006961
6962 if (!CodeCompleter || CodeCompleter->includeMacros())
6963 AddMacroResults(PP, Results);
6964
6965 // defined (<macro>)
6966 Results.EnterNewScope();
Douglas Gregor218937c2011-02-01 19:23:04 +00006967 CodeCompletionBuilder Builder(Results.getAllocator());
6968 Builder.AddTypedTextChunk("defined");
6969 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6970 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6971 Builder.AddPlaceholderChunk("macro");
6972 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6973 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00006974 Results.ExitScope();
6975
6976 HandleCodeCompleteResults(this, CodeCompleter,
6977 CodeCompletionContext::CCC_PreprocessorExpression,
6978 Results.data(), Results.size());
6979}
6980
6981void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
6982 IdentifierInfo *Macro,
6983 MacroInfo *MacroInfo,
6984 unsigned Argument) {
6985 // FIXME: In the future, we could provide "overload" results, much like we
6986 // do for function calls.
6987
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00006988 // Now just ignore this. There will be another code-completion callback
6989 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00006990}
6991
Douglas Gregor55817af2010-08-25 17:04:25 +00006992void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00006993 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00006994 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00006995 0, 0);
6996}
6997
Douglas Gregordae68752011-02-01 22:57:45 +00006998void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Chris Lattner5f9e2722011-07-23 10:55:15 +00006999 SmallVectorImpl<CodeCompletionResult> &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007000 ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007001 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7002 CodeCompletionDeclConsumer Consumer(Builder,
7003 Context.getTranslationUnitDecl());
7004 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7005 Consumer);
7006 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007007
7008 if (!CodeCompleter || CodeCompleter->includeMacros())
7009 AddMacroResults(PP, Builder);
7010
7011 Results.clear();
7012 Results.insert(Results.end(),
7013 Builder.data(), Builder.data() + Builder.size());
7014}