blob: f20558c201f01d3d92d335a3b6e31eacb689eb18 [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.
3640 Qualifier = getRequiredQualification(Context, CurContext,
3641 Enum->getDeclContext());
3642
3643 // FIXME: Scoped enums need to start with "EnumDecl" as the context!
3644 }
3645
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003646 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003647 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3648 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003649 Results.EnterNewScope();
3650 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3651 EEnd = Enum->enumerator_end();
3652 E != EEnd; ++E) {
3653 if (EnumeratorsSeen.count(*E))
3654 continue;
3655
Douglas Gregor5c722c702011-02-18 23:30:37 +00003656 CodeCompletionResult R(*E, Qualifier);
3657 R.Priority = CCP_EnumInCase;
3658 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003659 }
3660 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003661
Douglas Gregor3da626b2011-07-07 16:03:39 +00003662 //We need to make sure we're setting the right context,
3663 //so only say we include macros if the code completer says we do
3664 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3665 if (CodeCompleter->includeMacros()) {
Douglas Gregorbca403c2010-01-13 23:51:12 +00003666 AddMacroResults(PP, Results);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003667 kind = CodeCompletionContext::CCC_OtherWithMacros;
3668 }
3669
3670
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003671 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003672 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003673 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003674}
3675
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003676namespace {
3677 struct IsBetterOverloadCandidate {
3678 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003679 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003680
3681 public:
John McCall5769d612010-02-08 23:07:23 +00003682 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3683 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003684
3685 bool
3686 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003687 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003688 }
3689 };
3690}
3691
Douglas Gregord28dcd72010-05-30 06:10:08 +00003692static bool anyNullArguments(Expr **Args, unsigned NumArgs) {
3693 if (NumArgs && !Args)
3694 return true;
3695
3696 for (unsigned I = 0; I != NumArgs; ++I)
3697 if (!Args[I])
3698 return true;
3699
3700 return false;
3701}
3702
Richard Trieuf81e5a92011-09-09 02:00:50 +00003703void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
3704 Expr **ArgsIn, unsigned NumArgs) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003705 if (!CodeCompleter)
3706 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003707
3708 // When we're code-completing for a call, we fall back to ordinary
3709 // name code-completion whenever we can't produce specific
3710 // results. We may want to revisit this strategy in the future,
3711 // e.g., by merging the two kinds of results.
3712
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003713 Expr *Fn = (Expr *)FnIn;
3714 Expr **Args = (Expr **)ArgsIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003715
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003716 // Ignore type-dependent call expressions entirely.
Douglas Gregord28dcd72010-05-30 06:10:08 +00003717 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) ||
Douglas Gregoref96eac2009-12-11 19:06:04 +00003718 Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003719 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003720 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003721 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003722
John McCall3b4294e2009-12-16 12:17:52 +00003723 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003724 SourceLocation Loc = Fn->getExprLoc();
3725 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003726
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003727 // FIXME: What if we're calling something that isn't a function declaration?
3728 // FIXME: What if we're calling a pseudo-destructor?
3729 // FIXME: What if we're calling a member function?
3730
Douglas Gregorc0265402010-01-21 15:46:19 +00003731 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003732 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003733
John McCall3b4294e2009-12-16 12:17:52 +00003734 Expr *NakedFn = Fn->IgnoreParenCasts();
3735 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
3736 AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet,
3737 /*PartialOverloading=*/ true);
3738 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3739 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003740 if (FDecl) {
Douglas Gregord28dcd72010-05-30 06:10:08 +00003741 if (!getLangOptions().CPlusPlus ||
3742 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003743 Results.push_back(ResultCandidate(FDecl));
3744 else
John McCall86820f52010-01-26 01:37:31 +00003745 // FIXME: access?
John McCall9aa472c2010-03-19 07:35:19 +00003746 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none),
3747 Args, NumArgs, CandidateSet,
Douglas Gregorc27d6c52010-04-16 17:41:49 +00003748 false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003749 }
John McCall3b4294e2009-12-16 12:17:52 +00003750 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003751
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003752 QualType ParamType;
3753
Douglas Gregorc0265402010-01-21 15:46:19 +00003754 if (!CandidateSet.empty()) {
3755 // Sort the overload candidate set by placing the best overloads first.
3756 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003757 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003758
Douglas Gregorc0265402010-01-21 15:46:19 +00003759 // Add the remaining viable overload candidates as code-completion reslults.
3760 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3761 CandEnd = CandidateSet.end();
3762 Cand != CandEnd; ++Cand) {
3763 if (Cand->Viable)
3764 Results.push_back(ResultCandidate(Cand->Function));
3765 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003766
3767 // From the viable candidates, try to determine the type of this parameter.
3768 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3769 if (const FunctionType *FType = Results[I].getFunctionType())
3770 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
3771 if (NumArgs < Proto->getNumArgs()) {
3772 if (ParamType.isNull())
3773 ParamType = Proto->getArgType(NumArgs);
3774 else if (!Context.hasSameUnqualifiedType(
3775 ParamType.getNonReferenceType(),
3776 Proto->getArgType(NumArgs).getNonReferenceType())) {
3777 ParamType = QualType();
3778 break;
3779 }
3780 }
3781 }
3782 } else {
3783 // Try to determine the parameter type from the type of the expression
3784 // being called.
3785 QualType FunctionType = Fn->getType();
3786 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3787 FunctionType = Ptr->getPointeeType();
3788 else if (const BlockPointerType *BlockPtr
3789 = FunctionType->getAs<BlockPointerType>())
3790 FunctionType = BlockPtr->getPointeeType();
3791 else if (const MemberPointerType *MemPtr
3792 = FunctionType->getAs<MemberPointerType>())
3793 FunctionType = MemPtr->getPointeeType();
3794
3795 if (const FunctionProtoType *Proto
3796 = FunctionType->getAs<FunctionProtoType>()) {
3797 if (NumArgs < Proto->getNumArgs())
3798 ParamType = Proto->getArgType(NumArgs);
3799 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003800 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003801
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003802 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003803 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003804 else
3805 CodeCompleteExpression(S, ParamType);
3806
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003807 if (!Results.empty())
Douglas Gregoref96eac2009-12-11 19:06:04 +00003808 CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(),
3809 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003810}
3811
John McCalld226f652010-08-21 09:40:31 +00003812void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3813 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003814 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003815 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003816 return;
3817 }
3818
3819 CodeCompleteExpression(S, VD->getType());
3820}
3821
3822void Sema::CodeCompleteReturn(Scope *S) {
3823 QualType ResultType;
3824 if (isa<BlockDecl>(CurContext)) {
3825 if (BlockScopeInfo *BSI = getCurBlock())
3826 ResultType = BSI->ReturnType;
3827 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3828 ResultType = Function->getResultType();
3829 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3830 ResultType = Method->getResultType();
3831
3832 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003833 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003834 else
3835 CodeCompleteExpression(S, ResultType);
3836}
3837
Douglas Gregord2d8be62011-07-30 08:36:53 +00003838void Sema::CodeCompleteAfterIf(Scope *S) {
3839 typedef CodeCompletionResult Result;
3840 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3841 mapCodeCompletionContext(*this, PCC_Statement));
3842 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3843 Results.EnterNewScope();
3844
3845 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3846 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3847 CodeCompleter->includeGlobals());
3848
3849 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3850
3851 // "else" block
3852 CodeCompletionBuilder Builder(Results.getAllocator());
3853 Builder.AddTypedTextChunk("else");
3854 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3855 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3856 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3857 Builder.AddPlaceholderChunk("statements");
3858 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3859 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3860 Results.AddResult(Builder.TakeString());
3861
3862 // "else if" block
3863 Builder.AddTypedTextChunk("else");
3864 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3865 Builder.AddTextChunk("if");
3866 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3867 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3868 if (getLangOptions().CPlusPlus)
3869 Builder.AddPlaceholderChunk("condition");
3870 else
3871 Builder.AddPlaceholderChunk("expression");
3872 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3873 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3874 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3875 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3876 Builder.AddPlaceholderChunk("statements");
3877 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3878 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3879 Results.AddResult(Builder.TakeString());
3880
3881 Results.ExitScope();
3882
3883 if (S->getFnParent())
3884 AddPrettyFunctionResults(PP.getLangOptions(), Results);
3885
3886 if (CodeCompleter->includeMacros())
3887 AddMacroResults(PP, Results);
3888
3889 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3890 Results.data(),Results.size());
3891}
3892
Richard Trieuf81e5a92011-09-09 02:00:50 +00003893void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003894 if (LHS)
3895 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3896 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003897 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003898}
3899
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003900void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003901 bool EnteringContext) {
3902 if (!SS.getScopeRep() || !CodeCompleter)
3903 return;
3904
Douglas Gregor86d9a522009-09-21 16:56:56 +00003905 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3906 if (!Ctx)
3907 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003908
3909 // Try to instantiate any non-dependent declaration contexts before
3910 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003911 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003912 return;
3913
Douglas Gregor218937c2011-02-01 19:23:04 +00003914 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3915 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003916 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003917
Douglas Gregor86d9a522009-09-21 16:56:56 +00003918 // The "template" keyword can follow "::" in the grammar, but only
3919 // put it into the grammar if the nested-name-specifier is dependent.
3920 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3921 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003922 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003923
3924 // Add calls to overridden virtual functions, if there are any.
3925 //
3926 // FIXME: This isn't wonderful, because we don't know whether we're actually
3927 // in a context that permits expressions. This is a general issue with
3928 // qualified-id completions.
3929 if (!EnteringContext)
3930 MaybeAddOverrideCalls(*this, Ctx, Results);
3931 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003932
Douglas Gregorf6961522010-08-27 21:18:54 +00003933 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3934 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3935
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003936 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00003937 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003938 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003939}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003940
3941void Sema::CodeCompleteUsing(Scope *S) {
3942 if (!CodeCompleter)
3943 return;
3944
Douglas Gregor218937c2011-02-01 19:23:04 +00003945 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003946 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3947 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003948 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003949
3950 // If we aren't in class scope, we could see the "namespace" keyword.
3951 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00003952 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003953
3954 // After "using", we can see anything that would start a
3955 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003956 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003957 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3958 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003959 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003960
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003961 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003962 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003963 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003964}
3965
3966void Sema::CodeCompleteUsingDirective(Scope *S) {
3967 if (!CodeCompleter)
3968 return;
3969
Douglas Gregor86d9a522009-09-21 16:56:56 +00003970 // After "using namespace", we expect to see a namespace name or namespace
3971 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003972 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3973 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003974 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003975 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003976 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003977 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3978 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003979 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003980 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003981 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003982 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003983}
3984
3985void Sema::CodeCompleteNamespaceDecl(Scope *S) {
3986 if (!CodeCompleter)
3987 return;
3988
Douglas Gregor86d9a522009-09-21 16:56:56 +00003989 DeclContext *Ctx = (DeclContext *)S->getEntity();
3990 if (!S->getParent())
3991 Ctx = Context.getTranslationUnitDecl();
3992
Douglas Gregor52779fb2010-09-23 23:01:17 +00003993 bool SuppressedGlobalResults
3994 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
3995
Douglas Gregor218937c2011-02-01 19:23:04 +00003996 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003997 SuppressedGlobalResults
3998 ? CodeCompletionContext::CCC_Namespace
3999 : CodeCompletionContext::CCC_Other,
4000 &ResultBuilder::IsNamespace);
4001
4002 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004003 // We only want to see those namespaces that have already been defined
4004 // within this scope, because its likely that the user is creating an
4005 // extended namespace declaration. Keep track of the most recent
4006 // definition of each namespace.
4007 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4008 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4009 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4010 NS != NSEnd; ++NS)
4011 OrigToLatest[NS->getOriginalNamespace()] = *NS;
4012
4013 // Add the most recent definition (or extended definition) of each
4014 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004015 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004016 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
4017 NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
4018 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004019 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004020 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004021 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004022 }
4023
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004024 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004025 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004026 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004027}
4028
4029void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4030 if (!CodeCompleter)
4031 return;
4032
Douglas Gregor86d9a522009-09-21 16:56:56 +00004033 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004034 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4035 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004036 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004037 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004038 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4039 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004040 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004041 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004042 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004043}
4044
Douglas Gregored8d3222009-09-18 20:05:18 +00004045void Sema::CodeCompleteOperatorName(Scope *S) {
4046 if (!CodeCompleter)
4047 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004048
John McCall0a2c5e22010-08-25 06:19:51 +00004049 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004050 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4051 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004052 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004053 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004054
Douglas Gregor86d9a522009-09-21 16:56:56 +00004055 // Add the names of overloadable operators.
4056#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4057 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004058 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004059#include "clang/Basic/OperatorKinds.def"
4060
4061 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004062 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004063 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004064 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4065 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004066
4067 // Add any type specifiers
Douglas Gregorbca403c2010-01-13 23:51:12 +00004068 AddTypeSpecifierResults(getLangOptions(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004069 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004070
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004071 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004072 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004073 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004074}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004075
Douglas Gregor0133f522010-08-28 00:00:50 +00004076void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004077 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004078 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004079 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004080 CXXConstructorDecl *Constructor
4081 = static_cast<CXXConstructorDecl *>(ConstructorD);
4082 if (!Constructor)
4083 return;
4084
Douglas Gregor218937c2011-02-01 19:23:04 +00004085 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004086 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004087 Results.EnterNewScope();
4088
4089 // Fill in any already-initialized fields or base classes.
4090 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4091 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4092 for (unsigned I = 0; I != NumInitializers; ++I) {
4093 if (Initializers[I]->isBaseInitializer())
4094 InitializedBases.insert(
4095 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4096 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004097 InitializedFields.insert(cast<FieldDecl>(
4098 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004099 }
4100
4101 // Add completions for base classes.
Douglas Gregor218937c2011-02-01 19:23:04 +00004102 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004103 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004104 CXXRecordDecl *ClassDecl = Constructor->getParent();
4105 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4106 BaseEnd = ClassDecl->bases_end();
4107 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004108 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4109 SawLastInitializer
4110 = NumInitializers > 0 &&
4111 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4112 Context.hasSameUnqualifiedType(Base->getType(),
4113 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004114 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004115 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004116
Douglas Gregor218937c2011-02-01 19:23:04 +00004117 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004118 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004119 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004120 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4121 Builder.AddPlaceholderChunk("args");
4122 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4123 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004124 SawLastInitializer? CCP_NextInitializer
4125 : CCP_MemberDeclaration));
4126 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004127 }
4128
4129 // Add completions for virtual base classes.
4130 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4131 BaseEnd = ClassDecl->vbases_end();
4132 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004133 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4134 SawLastInitializer
4135 = NumInitializers > 0 &&
4136 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4137 Context.hasSameUnqualifiedType(Base->getType(),
4138 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004139 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004140 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004141
Douglas Gregor218937c2011-02-01 19:23:04 +00004142 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004143 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004144 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004145 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4146 Builder.AddPlaceholderChunk("args");
4147 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4148 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004149 SawLastInitializer? CCP_NextInitializer
4150 : CCP_MemberDeclaration));
4151 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004152 }
4153
4154 // Add completions for members.
4155 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4156 FieldEnd = ClassDecl->field_end();
4157 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004158 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4159 SawLastInitializer
4160 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004161 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
4162 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004163 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004164 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004165
4166 if (!Field->getDeclName())
4167 continue;
4168
Douglas Gregordae68752011-02-01 22:57:45 +00004169 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004170 Field->getIdentifier()->getName()));
4171 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4172 Builder.AddPlaceholderChunk("args");
4173 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4174 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004175 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004176 : CCP_MemberDeclaration,
4177 CXCursor_MemberRef));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004178 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004179 }
4180 Results.ExitScope();
4181
Douglas Gregor52779fb2010-09-23 23:01:17 +00004182 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004183 Results.data(), Results.size());
4184}
4185
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004186// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
4187// true or false.
4188#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorbca403c2010-01-13 23:51:12 +00004189static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004190 ResultBuilder &Results,
4191 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004192 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004193 // Since we have an implementation, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004194 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004195
Douglas Gregor218937c2011-02-01 19:23:04 +00004196 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004197 if (LangOpts.ObjC2) {
4198 // @dynamic
Douglas Gregor218937c2011-02-01 19:23:04 +00004199 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
4200 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4201 Builder.AddPlaceholderChunk("property");
4202 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004203
4204 // @synthesize
Douglas Gregor218937c2011-02-01 19:23:04 +00004205 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
4206 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4207 Builder.AddPlaceholderChunk("property");
4208 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004209 }
4210}
4211
Douglas Gregorbca403c2010-01-13 23:51:12 +00004212static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004213 ResultBuilder &Results,
4214 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004215 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004216
4217 // Since we have an interface or protocol, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004218 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004219
4220 if (LangOpts.ObjC2) {
4221 // @property
Douglas Gregora4477812010-01-14 16:01:26 +00004222 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004223
4224 // @required
Douglas Gregora4477812010-01-14 16:01:26 +00004225 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004226
4227 // @optional
Douglas Gregora4477812010-01-14 16:01:26 +00004228 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004229 }
4230}
4231
Douglas Gregorbca403c2010-01-13 23:51:12 +00004232static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004233 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004234 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004235
4236 // @class name ;
Douglas Gregor218937c2011-02-01 19:23:04 +00004237 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
4238 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4239 Builder.AddPlaceholderChunk("name");
4240 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004241
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004242 if (Results.includeCodePatterns()) {
4243 // @interface name
4244 // FIXME: Could introduce the whole pattern, including superclasses and
4245 // such.
Douglas Gregor218937c2011-02-01 19:23:04 +00004246 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
4247 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4248 Builder.AddPlaceholderChunk("class");
4249 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004250
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004251 // @protocol name
Douglas Gregor218937c2011-02-01 19:23:04 +00004252 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4253 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4254 Builder.AddPlaceholderChunk("protocol");
4255 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004256
4257 // @implementation name
Douglas Gregor218937c2011-02-01 19:23:04 +00004258 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
4259 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4260 Builder.AddPlaceholderChunk("class");
4261 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004262 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004263
4264 // @compatibility_alias name
Douglas Gregor218937c2011-02-01 19:23:04 +00004265 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
4266 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4267 Builder.AddPlaceholderChunk("alias");
4268 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4269 Builder.AddPlaceholderChunk("class");
4270 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004271}
4272
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004273void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004274 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004275 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4276 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004277 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004278 if (isa<ObjCImplDecl>(CurContext))
Douglas Gregorbca403c2010-01-13 23:51:12 +00004279 AddObjCImplementationResults(getLangOptions(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004280 else if (CurContext->isObjCContainer())
Douglas Gregorbca403c2010-01-13 23:51:12 +00004281 AddObjCInterfaceResults(getLangOptions(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004282 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004283 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004284 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004285 HandleCodeCompleteResults(this, CodeCompleter,
4286 CodeCompletionContext::CCC_Other,
4287 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004288}
4289
Douglas Gregorbca403c2010-01-13 23:51:12 +00004290static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004291 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004292 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004293
4294 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004295 const char *EncodeType = "char[]";
4296 if (Results.getSema().getLangOptions().CPlusPlus ||
4297 Results.getSema().getLangOptions().ConstStrings)
4298 EncodeType = " const char[]";
4299 Builder.AddResultTypeChunk(EncodeType);
Douglas Gregor218937c2011-02-01 19:23:04 +00004300 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
4301 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4302 Builder.AddPlaceholderChunk("type-name");
4303 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4304 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004305
4306 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004307 Builder.AddResultTypeChunk("Protocol *");
Douglas Gregor218937c2011-02-01 19:23:04 +00004308 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4309 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4310 Builder.AddPlaceholderChunk("protocol-name");
4311 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4312 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004313
4314 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004315 Builder.AddResultTypeChunk("SEL");
Douglas Gregor218937c2011-02-01 19:23:04 +00004316 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
4317 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4318 Builder.AddPlaceholderChunk("selector");
4319 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4320 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004321}
4322
Douglas Gregorbca403c2010-01-13 23:51:12 +00004323static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004324 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004325 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004326
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004327 if (Results.includeCodePatterns()) {
4328 // @try { statements } @catch ( declaration ) { statements } @finally
4329 // { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004330 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
4331 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4332 Builder.AddPlaceholderChunk("statements");
4333 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4334 Builder.AddTextChunk("@catch");
4335 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4336 Builder.AddPlaceholderChunk("parameter");
4337 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4338 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4339 Builder.AddPlaceholderChunk("statements");
4340 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4341 Builder.AddTextChunk("@finally");
4342 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4343 Builder.AddPlaceholderChunk("statements");
4344 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4345 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004346 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004347
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004348 // @throw
Douglas Gregor218937c2011-02-01 19:23:04 +00004349 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
4350 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4351 Builder.AddPlaceholderChunk("expression");
4352 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004353
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004354 if (Results.includeCodePatterns()) {
4355 // @synchronized ( expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004356 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
4357 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4358 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4359 Builder.AddPlaceholderChunk("expression");
4360 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4361 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4362 Builder.AddPlaceholderChunk("statements");
4363 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4364 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004365 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004366}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004367
Douglas Gregorbca403c2010-01-13 23:51:12 +00004368static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004369 ResultBuilder &Results,
4370 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004371 typedef CodeCompletionResult Result;
Douglas Gregora4477812010-01-14 16:01:26 +00004372 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
4373 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
4374 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004375 if (LangOpts.ObjC2)
Douglas Gregora4477812010-01-14 16:01:26 +00004376 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004377}
4378
4379void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004380 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4381 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004382 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004383 AddObjCVisibilityResults(getLangOptions(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004384 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004385 HandleCodeCompleteResults(this, CodeCompleter,
4386 CodeCompletionContext::CCC_Other,
4387 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004388}
4389
4390void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004391 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4392 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004393 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004394 AddObjCStatementResults(Results, false);
4395 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004396 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004397 HandleCodeCompleteResults(this, CodeCompleter,
4398 CodeCompletionContext::CCC_Other,
4399 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004400}
4401
4402void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004403 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4404 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004405 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004406 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004407 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004408 HandleCodeCompleteResults(this, CodeCompleter,
4409 CodeCompletionContext::CCC_Other,
4410 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004411}
4412
Douglas Gregor988358f2009-11-19 00:14:45 +00004413/// \brief Determine whether the addition of the given flag to an Objective-C
4414/// property's attributes will cause a conflict.
4415static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4416 // Check if we've already added this flag.
4417 if (Attributes & NewFlag)
4418 return true;
4419
4420 Attributes |= NewFlag;
4421
4422 // Check for collisions with "readonly".
4423 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4424 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4425 ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004426 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004427 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004428 ObjCDeclSpec::DQ_PR_retain |
4429 ObjCDeclSpec::DQ_PR_strong)))
Douglas Gregor988358f2009-11-19 00:14:45 +00004430 return true;
4431
John McCallf85e1932011-06-15 23:02:42 +00004432 // Check for more than one of { assign, copy, retain, strong }.
Douglas Gregor988358f2009-11-19 00:14:45 +00004433 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004434 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004435 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004436 ObjCDeclSpec::DQ_PR_retain|
4437 ObjCDeclSpec::DQ_PR_strong);
Douglas Gregor988358f2009-11-19 00:14:45 +00004438 if (AssignCopyRetMask &&
4439 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004440 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004441 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004442 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
4443 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
Douglas Gregor988358f2009-11-19 00:14:45 +00004444 return true;
4445
4446 return false;
4447}
4448
Douglas Gregora93b1082009-11-18 23:08:07 +00004449void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004450 if (!CodeCompleter)
4451 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004452
Steve Naroffece8e712009-10-08 21:55:05 +00004453 unsigned Attributes = ODS.getPropertyAttributes();
4454
John McCall0a2c5e22010-08-25 06:19:51 +00004455 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004456 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4457 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004458 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004459 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004460 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004461 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004462 Results.AddResult(CodeCompletionResult("assign"));
John McCallf85e1932011-06-15 23:02:42 +00004463 if (!ObjCPropertyFlagConflicts(Attributes,
4464 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4465 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004466 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004467 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004468 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004469 Results.AddResult(CodeCompletionResult("retain"));
John McCallf85e1932011-06-15 23:02:42 +00004470 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4471 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004472 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004473 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004474 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004475 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004476 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4477 Results.AddResult(CodeCompletionResult("atomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004478 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004479 CodeCompletionBuilder Setter(Results.getAllocator());
4480 Setter.AddTypedTextChunk("setter");
4481 Setter.AddTextChunk(" = ");
4482 Setter.AddPlaceholderChunk("method");
4483 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004484 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004485 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004486 CodeCompletionBuilder Getter(Results.getAllocator());
4487 Getter.AddTypedTextChunk("getter");
4488 Getter.AddTextChunk(" = ");
4489 Getter.AddPlaceholderChunk("method");
4490 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004491 }
Steve Naroffece8e712009-10-08 21:55:05 +00004492 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004493 HandleCodeCompleteResults(this, CodeCompleter,
4494 CodeCompletionContext::CCC_Other,
4495 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004496}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004497
Douglas Gregor4ad96852009-11-19 07:41:15 +00004498/// \brief Descripts the kind of Objective-C method that we want to find
4499/// via code completion.
4500enum ObjCMethodKind {
4501 MK_Any, //< Any kind of method, provided it means other specified criteria.
4502 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4503 MK_OneArgSelector //< One-argument selector.
4504};
4505
Douglas Gregor458433d2010-08-26 15:07:07 +00004506static bool isAcceptableObjCSelector(Selector Sel,
4507 ObjCMethodKind WantKind,
4508 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004509 unsigned NumSelIdents,
4510 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004511 if (NumSelIdents > Sel.getNumArgs())
4512 return false;
4513
4514 switch (WantKind) {
4515 case MK_Any: break;
4516 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4517 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4518 }
4519
Douglas Gregorcf544262010-11-17 21:36:08 +00004520 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4521 return false;
4522
Douglas Gregor458433d2010-08-26 15:07:07 +00004523 for (unsigned I = 0; I != NumSelIdents; ++I)
4524 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4525 return false;
4526
4527 return true;
4528}
4529
Douglas Gregor4ad96852009-11-19 07:41:15 +00004530static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4531 ObjCMethodKind WantKind,
4532 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004533 unsigned NumSelIdents,
4534 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004535 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004536 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004537}
Douglas Gregord36adf52010-09-16 16:06:31 +00004538
4539namespace {
4540 /// \brief A set of selectors, which is used to avoid introducing multiple
4541 /// completions with the same selector into the result set.
4542 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4543}
4544
Douglas Gregor36ecb042009-11-17 23:22:23 +00004545/// \brief Add all of the Objective-C methods in the given Objective-C
4546/// container to the set of results.
4547///
4548/// The container will be a class, protocol, category, or implementation of
4549/// any of the above. This mether will recurse to include methods from
4550/// the superclasses of classes along with their categories, protocols, and
4551/// implementations.
4552///
4553/// \param Container the container in which we'll look to find methods.
4554///
4555/// \param WantInstance whether to add instance methods (only); if false, this
4556/// routine will add factory methods (only).
4557///
4558/// \param CurContext the context in which we're performing the lookup that
4559/// finds methods.
4560///
Douglas Gregorcf544262010-11-17 21:36:08 +00004561/// \param AllowSameLength Whether we allow a method to be added to the list
4562/// when it has the same number of parameters as we have selector identifiers.
4563///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004564/// \param Results the structure into which we'll add results.
4565static void AddObjCMethods(ObjCContainerDecl *Container,
4566 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004567 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004568 IdentifierInfo **SelIdents,
4569 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004570 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004571 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004572 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004573 ResultBuilder &Results,
4574 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004575 typedef CodeCompletionResult Result;
Douglas Gregor36ecb042009-11-17 23:22:23 +00004576 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4577 MEnd = Container->meth_end();
4578 M != MEnd; ++M) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004579 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4580 // Check whether the selector identifiers we've been given are a
4581 // subset of the identifiers for this particular method.
Douglas Gregorcf544262010-11-17 21:36:08 +00004582 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4583 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004584 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004585
Douglas Gregord36adf52010-09-16 16:06:31 +00004586 if (!Selectors.insert((*M)->getSelector()))
4587 continue;
4588
Douglas Gregord3c68542009-11-19 01:08:35 +00004589 Result R = Result(*M, 0);
4590 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004591 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004592 if (!InOriginalClass)
4593 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004594 Results.MaybeAddResult(R, CurContext);
4595 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004596 }
4597
Douglas Gregore396c7b2010-09-16 15:34:59 +00004598 // Visit the protocols of protocols.
4599 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004600 if (Protocol->hasDefinition()) {
4601 const ObjCList<ObjCProtocolDecl> &Protocols
4602 = Protocol->getReferencedProtocols();
4603 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4604 E = Protocols.end();
4605 I != E; ++I)
4606 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4607 NumSelIdents, CurContext, Selectors, AllowSameLength,
4608 Results, false);
4609 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004610 }
4611
Douglas Gregor36ecb042009-11-17 23:22:23 +00004612 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004613 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004614 return;
4615
4616 // Add methods in protocols.
4617 const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols();
4618 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4619 E = Protocols.end();
4620 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004621 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004622 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004623
4624 // Add methods in categories.
4625 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4626 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004627 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004628 NumSelIdents, CurContext, Selectors, AllowSameLength,
4629 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004630
4631 // Add a categories protocol methods.
4632 const ObjCList<ObjCProtocolDecl> &Protocols
4633 = CatDecl->getReferencedProtocols();
4634 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4635 E = Protocols.end();
4636 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004637 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004638 NumSelIdents, CurContext, Selectors, AllowSameLength,
4639 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004640
4641 // Add methods in category implementations.
4642 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004643 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004644 NumSelIdents, CurContext, Selectors, AllowSameLength,
4645 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004646 }
4647
4648 // Add methods in superclass.
4649 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004650 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004651 SelIdents, NumSelIdents, CurContext, Selectors,
4652 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004653
4654 // Add methods in our implementation, if any.
4655 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004656 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004657 NumSelIdents, CurContext, Selectors, AllowSameLength,
4658 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004659}
4660
4661
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004662void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004663 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004664
4665 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004666 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004667 if (!Class) {
4668 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004669 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004670 Class = Category->getClassInterface();
4671
4672 if (!Class)
4673 return;
4674 }
4675
4676 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004677 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4678 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004679 Results.EnterNewScope();
4680
Douglas Gregord36adf52010-09-16 16:06:31 +00004681 VisitedSelectorSet Selectors;
4682 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004683 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004684 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004685 HandleCodeCompleteResults(this, CodeCompleter,
4686 CodeCompletionContext::CCC_Other,
4687 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004688}
4689
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004690void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004691 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004692
4693 // Try to find the interface where setters might live.
4694 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004695 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004696 if (!Class) {
4697 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004698 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004699 Class = Category->getClassInterface();
4700
4701 if (!Class)
4702 return;
4703 }
4704
4705 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004706 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4707 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004708 Results.EnterNewScope();
4709
Douglas Gregord36adf52010-09-16 16:06:31 +00004710 VisitedSelectorSet Selectors;
4711 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004712 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004713
4714 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004715 HandleCodeCompleteResults(this, CodeCompleter,
4716 CodeCompletionContext::CCC_Other,
4717 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004718}
4719
Douglas Gregorafc45782011-02-15 22:19:42 +00004720void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4721 bool IsParameter) {
John McCall0a2c5e22010-08-25 06:19:51 +00004722 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004723 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4724 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004725 Results.EnterNewScope();
4726
4727 // Add context-sensitive, Objective-C parameter-passing keywords.
4728 bool AddedInOut = false;
4729 if ((DS.getObjCDeclQualifier() &
4730 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4731 Results.AddResult("in");
4732 Results.AddResult("inout");
4733 AddedInOut = true;
4734 }
4735 if ((DS.getObjCDeclQualifier() &
4736 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4737 Results.AddResult("out");
4738 if (!AddedInOut)
4739 Results.AddResult("inout");
4740 }
4741 if ((DS.getObjCDeclQualifier() &
4742 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4743 ObjCDeclSpec::DQ_Oneway)) == 0) {
4744 Results.AddResult("bycopy");
4745 Results.AddResult("byref");
4746 Results.AddResult("oneway");
4747 }
4748
Douglas Gregorafc45782011-02-15 22:19:42 +00004749 // If we're completing the return type of an Objective-C method and the
4750 // identifier IBAction refers to a macro, provide a completion item for
4751 // an action, e.g.,
4752 // IBAction)<#selector#>:(id)sender
4753 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4754 Context.Idents.get("IBAction").hasMacroDefinition()) {
4755 typedef CodeCompletionString::Chunk Chunk;
4756 CodeCompletionBuilder Builder(Results.getAllocator(), CCP_CodePattern,
4757 CXAvailability_Available);
4758 Builder.AddTypedTextChunk("IBAction");
4759 Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
4760 Builder.AddPlaceholderChunk("selector");
4761 Builder.AddChunk(Chunk(CodeCompletionString::CK_Colon));
4762 Builder.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
4763 Builder.AddTextChunk("id");
4764 Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
4765 Builder.AddTextChunk("sender");
4766 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4767 }
4768
Douglas Gregord32b0222010-08-24 01:06:58 +00004769 // Add various builtin type names and specifiers.
4770 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4771 Results.ExitScope();
4772
4773 // Add the various type names
4774 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4775 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4776 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4777 CodeCompleter->includeGlobals());
4778
4779 if (CodeCompleter->includeMacros())
4780 AddMacroResults(PP, Results);
4781
4782 HandleCodeCompleteResults(this, CodeCompleter,
4783 CodeCompletionContext::CCC_Type,
4784 Results.data(), Results.size());
4785}
4786
Douglas Gregor22f56992010-04-06 19:22:33 +00004787/// \brief When we have an expression with type "id", we may assume
4788/// that it has some more-specific class type based on knowledge of
4789/// common uses of Objective-C. This routine returns that class type,
4790/// or NULL if no better result could be determined.
4791static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004792 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004793 if (!Msg)
4794 return 0;
4795
4796 Selector Sel = Msg->getSelector();
4797 if (Sel.isNull())
4798 return 0;
4799
4800 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4801 if (!Id)
4802 return 0;
4803
4804 ObjCMethodDecl *Method = Msg->getMethodDecl();
4805 if (!Method)
4806 return 0;
4807
4808 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004809 ObjCInterfaceDecl *IFace = 0;
4810 switch (Msg->getReceiverKind()) {
4811 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004812 if (const ObjCObjectType *ObjType
4813 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4814 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004815 break;
4816
4817 case ObjCMessageExpr::Instance: {
4818 QualType T = Msg->getInstanceReceiver()->getType();
4819 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4820 IFace = Ptr->getInterfaceDecl();
4821 break;
4822 }
4823
4824 case ObjCMessageExpr::SuperInstance:
4825 case ObjCMessageExpr::SuperClass:
4826 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00004827 }
4828
4829 if (!IFace)
4830 return 0;
4831
4832 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4833 if (Method->isInstanceMethod())
4834 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4835 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00004836 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00004837 .Case("autorelease", IFace)
4838 .Case("copy", IFace)
4839 .Case("copyWithZone", IFace)
4840 .Case("mutableCopy", IFace)
4841 .Case("mutableCopyWithZone", IFace)
4842 .Case("awakeFromCoder", IFace)
4843 .Case("replacementObjectFromCoder", IFace)
4844 .Case("class", IFace)
4845 .Case("classForCoder", IFace)
4846 .Case("superclass", Super)
4847 .Default(0);
4848
4849 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4850 .Case("new", IFace)
4851 .Case("alloc", IFace)
4852 .Case("allocWithZone", IFace)
4853 .Case("class", IFace)
4854 .Case("superclass", Super)
4855 .Default(0);
4856}
4857
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004858// Add a special completion for a message send to "super", which fills in the
4859// most likely case of forwarding all of our arguments to the superclass
4860// function.
4861///
4862/// \param S The semantic analysis object.
4863///
4864/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4865/// the "super" keyword. Otherwise, we just need to provide the arguments.
4866///
4867/// \param SelIdents The identifiers in the selector that have already been
4868/// provided as arguments for a send to "super".
4869///
4870/// \param NumSelIdents The number of identifiers in \p SelIdents.
4871///
4872/// \param Results The set of results to augment.
4873///
4874/// \returns the Objective-C method declaration that would be invoked by
4875/// this "super" completion. If NULL, no completion was added.
4876static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4877 IdentifierInfo **SelIdents,
4878 unsigned NumSelIdents,
4879 ResultBuilder &Results) {
4880 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
4881 if (!CurMethod)
4882 return 0;
4883
4884 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
4885 if (!Class)
4886 return 0;
4887
4888 // Try to find a superclass method with the same selector.
4889 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00004890 while ((Class = Class->getSuperClass()) && !SuperMethod) {
4891 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004892 SuperMethod = Class->getMethod(CurMethod->getSelector(),
4893 CurMethod->isInstanceMethod());
4894
Douglas Gregor78bcd912011-02-16 00:51:18 +00004895 // Check in categories or class extensions.
4896 if (!SuperMethod) {
4897 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
4898 Category = Category->getNextClassCategory())
4899 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
4900 CurMethod->isInstanceMethod())))
4901 break;
4902 }
4903 }
4904
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004905 if (!SuperMethod)
4906 return 0;
4907
4908 // Check whether the superclass method has the same signature.
4909 if (CurMethod->param_size() != SuperMethod->param_size() ||
4910 CurMethod->isVariadic() != SuperMethod->isVariadic())
4911 return 0;
4912
4913 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
4914 CurPEnd = CurMethod->param_end(),
4915 SuperP = SuperMethod->param_begin();
4916 CurP != CurPEnd; ++CurP, ++SuperP) {
4917 // Make sure the parameter types are compatible.
4918 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
4919 (*SuperP)->getType()))
4920 return 0;
4921
4922 // Make sure we have a parameter name to forward!
4923 if (!(*CurP)->getIdentifier())
4924 return 0;
4925 }
4926
4927 // We have a superclass method. Now, form the send-to-super completion.
Douglas Gregor218937c2011-02-01 19:23:04 +00004928 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004929
4930 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00004931 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
4932 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004933
4934 // If we need the "super" keyword, add it (plus some spacing).
4935 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004936 Builder.AddTypedTextChunk("super");
4937 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004938 }
4939
4940 Selector Sel = CurMethod->getSelector();
4941 if (Sel.isUnarySelector()) {
4942 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00004943 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004944 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004945 else
Douglas Gregordae68752011-02-01 22:57:45 +00004946 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004947 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004948 } else {
4949 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
4950 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
4951 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004952 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004953
4954 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004955 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004956 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004957 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004958 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004959 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004960 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004961 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00004962 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004963 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004964 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00004965 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004966 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004967 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00004968 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004969 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004970 }
4971 }
4972 }
4973
Douglas Gregor218937c2011-02-01 19:23:04 +00004974 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004975 SuperMethod->isInstanceMethod()
4976 ? CXCursor_ObjCInstanceMethodDecl
4977 : CXCursor_ObjCClassMethodDecl));
4978 return SuperMethod;
4979}
4980
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004981void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004982 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004983 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4984 CodeCompletionContext::CCC_ObjCMessageReceiver,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004985 &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004986
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004987 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4988 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00004989 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4990 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004991
4992 // If we are in an Objective-C method inside a class that has a superclass,
4993 // add "super" as an option.
4994 if (ObjCMethodDecl *Method = getCurMethodDecl())
4995 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004996 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004997 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004998
4999 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5000 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005001
5002 Results.ExitScope();
5003
5004 if (CodeCompleter->includeMacros())
5005 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005006 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005007 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005008
5009}
5010
Douglas Gregor2725ca82010-04-21 19:57:20 +00005011void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5012 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005013 unsigned NumSelIdents,
5014 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005015 ObjCInterfaceDecl *CDecl = 0;
5016 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5017 // Figure out which interface we're in.
5018 CDecl = CurMethod->getClassInterface();
5019 if (!CDecl)
5020 return;
5021
5022 // Find the superclass of this class.
5023 CDecl = CDecl->getSuperClass();
5024 if (!CDecl)
5025 return;
5026
5027 if (CurMethod->isInstanceMethod()) {
5028 // We are inside an instance method, which means that the message
5029 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005030 // current object.
5031 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005032 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005033 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005034 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005035 }
5036
5037 // Fall through to send to the superclass in CDecl.
5038 } else {
5039 // "super" may be the name of a type or variable. Figure out which
5040 // it is.
5041 IdentifierInfo *Super = &Context.Idents.get("super");
5042 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5043 LookupOrdinaryName);
5044 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5045 // "super" names an interface. Use it.
5046 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005047 if (const ObjCObjectType *Iface
5048 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5049 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005050 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5051 // "super" names an unresolved type; we can't be more specific.
5052 } else {
5053 // Assume that "super" names some kind of value and parse that way.
5054 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005055 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005056 UnqualifiedId id;
5057 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005058 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5059 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005060 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005061 SelIdents, NumSelIdents,
5062 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005063 }
5064
5065 // Fall through
5066 }
5067
John McCallb3d87482010-08-24 05:47:05 +00005068 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005069 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005070 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005071 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005072 NumSelIdents, AtArgumentExpression,
5073 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005074}
5075
Douglas Gregorb9d77572010-09-21 00:03:25 +00005076/// \brief Given a set of code-completion results for the argument of a message
5077/// send, determine the preferred type (if any) for that argument expression.
5078static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5079 unsigned NumSelIdents) {
5080 typedef CodeCompletionResult Result;
5081 ASTContext &Context = Results.getSema().Context;
5082
5083 QualType PreferredType;
5084 unsigned BestPriority = CCP_Unlikely * 2;
5085 Result *ResultsData = Results.data();
5086 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5087 Result &R = ResultsData[I];
5088 if (R.Kind == Result::RK_Declaration &&
5089 isa<ObjCMethodDecl>(R.Declaration)) {
5090 if (R.Priority <= BestPriority) {
5091 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5092 if (NumSelIdents <= Method->param_size()) {
5093 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5094 ->getType();
5095 if (R.Priority < BestPriority || PreferredType.isNull()) {
5096 BestPriority = R.Priority;
5097 PreferredType = MyPreferredType;
5098 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5099 MyPreferredType)) {
5100 PreferredType = QualType();
5101 }
5102 }
5103 }
5104 }
5105 }
5106
5107 return PreferredType;
5108}
5109
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005110static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5111 ParsedType Receiver,
5112 IdentifierInfo **SelIdents,
5113 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005114 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005115 bool IsSuper,
5116 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005117 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005118 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005119
Douglas Gregor24a069f2009-11-17 17:59:40 +00005120 // If the given name refers to an interface type, retrieve the
5121 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005122 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005123 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005124 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005125 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5126 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005127 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005128
Douglas Gregor36ecb042009-11-17 23:22:23 +00005129 // Add all of the factory methods in this Objective-C class, its protocols,
5130 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005131 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005132
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005133 // If this is a send-to-super, try to add the special "super" send
5134 // completion.
5135 if (IsSuper) {
5136 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005137 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5138 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005139 Results.Ignore(SuperMethod);
5140 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005141
Douglas Gregor265f7492010-08-27 15:29:55 +00005142 // If we're inside an Objective-C method definition, prefer its selector to
5143 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005144 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005145 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005146
Douglas Gregord36adf52010-09-16 16:06:31 +00005147 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005148 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005149 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005150 SemaRef.CurContext, Selectors, AtArgumentExpression,
5151 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005152 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005153 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005154
Douglas Gregor719770d2010-04-06 17:30:22 +00005155 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005156 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005157 if (SemaRef.ExternalSource) {
5158 for (uint32_t I = 0,
5159 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005160 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005161 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5162 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005163 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005164
5165 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005166 }
5167 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005168
5169 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5170 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005171 M != MEnd; ++M) {
5172 for (ObjCMethodList *MethList = &M->second.second;
5173 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005174 MethList = MethList->Next) {
5175 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5176 NumSelIdents))
5177 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005178
Douglas Gregor13438f92010-04-06 16:40:00 +00005179 Result R(MethList->Method, 0);
5180 R.StartParameter = NumSelIdents;
5181 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005182 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005183 }
5184 }
5185 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005186
5187 Results.ExitScope();
5188}
Douglas Gregor13438f92010-04-06 16:40:00 +00005189
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005190void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5191 IdentifierInfo **SelIdents,
5192 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005193 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005194 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005195
5196 QualType T = this->GetTypeFromParser(Receiver);
5197
Douglas Gregor218937c2011-02-01 19:23:04 +00005198 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005199 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005200 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005201
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005202 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5203 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005204
5205 // If we're actually at the argument expression (rather than prior to the
5206 // selector), we're actually performing code completion for an expression.
5207 // Determine whether we have a single, best method. If so, we can
5208 // code-complete the expression using the corresponding parameter type as
5209 // our preferred type, improving completion results.
5210 if (AtArgumentExpression) {
5211 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005212 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005213 if (PreferredType.isNull())
5214 CodeCompleteOrdinaryName(S, PCC_Expression);
5215 else
5216 CodeCompleteExpression(S, PreferredType);
5217 return;
5218 }
5219
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005220 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005221 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005222 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005223}
5224
Richard Trieuf81e5a92011-09-09 02:00:50 +00005225void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005226 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005227 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005228 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005229 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005230 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005231
5232 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005233
Douglas Gregor36ecb042009-11-17 23:22:23 +00005234 // If necessary, apply function/array conversion to the receiver.
5235 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005236 if (RecExpr) {
5237 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5238 if (Conv.isInvalid()) // conversion failed. bail.
5239 return;
5240 RecExpr = Conv.take();
5241 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005242 QualType ReceiverType = RecExpr? RecExpr->getType()
5243 : Super? Context.getObjCObjectPointerType(
5244 Context.getObjCInterfaceType(Super))
5245 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005246
Douglas Gregorda892642010-11-08 21:12:30 +00005247 // If we're messaging an expression with type "id" or "Class", check
5248 // whether we know something special about the receiver that allows
5249 // us to assume a more-specific receiver type.
5250 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5251 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5252 if (ReceiverType->isObjCClassType())
5253 return CodeCompleteObjCClassMessage(S,
5254 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5255 SelIdents, NumSelIdents,
5256 AtArgumentExpression, Super);
5257
5258 ReceiverType = Context.getObjCObjectPointerType(
5259 Context.getObjCInterfaceType(IFace));
5260 }
5261
Douglas Gregor36ecb042009-11-17 23:22:23 +00005262 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005263 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005264 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005265 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005266
Douglas Gregor36ecb042009-11-17 23:22:23 +00005267 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005268
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005269 // If this is a send-to-super, try to add the special "super" send
5270 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005271 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005272 if (ObjCMethodDecl *SuperMethod
5273 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5274 Results))
5275 Results.Ignore(SuperMethod);
5276 }
5277
Douglas Gregor265f7492010-08-27 15:29:55 +00005278 // If we're inside an Objective-C method definition, prefer its selector to
5279 // others.
5280 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5281 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005282
Douglas Gregord36adf52010-09-16 16:06:31 +00005283 // Keep track of the selectors we've already added.
5284 VisitedSelectorSet Selectors;
5285
Douglas Gregorf74a4192009-11-18 00:06:18 +00005286 // Handle messages to Class. This really isn't a message to an instance
5287 // method, so we treat it the same way we would treat a message send to a
5288 // class method.
5289 if (ReceiverType->isObjCClassType() ||
5290 ReceiverType->isObjCQualifiedClassType()) {
5291 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5292 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005293 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005294 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005295 }
5296 }
5297 // Handle messages to a qualified ID ("id<foo>").
5298 else if (const ObjCObjectPointerType *QualID
5299 = ReceiverType->getAsObjCQualifiedIdType()) {
5300 // Search protocols for instance methods.
5301 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5302 E = QualID->qual_end();
5303 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005304 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005305 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005306 }
5307 // Handle messages to a pointer to interface type.
5308 else if (const ObjCObjectPointerType *IFacePtr
5309 = ReceiverType->getAsObjCInterfacePointerType()) {
5310 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005311 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005312 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5313 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005314
5315 // Search protocols for instance methods.
5316 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5317 E = IFacePtr->qual_end();
5318 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005319 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005320 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005321 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005322 // Handle messages to "id".
5323 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005324 // We're messaging "id", so provide all instance methods we know
5325 // about as code-completion results.
5326
5327 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005328 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005329 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005330 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5331 I != N; ++I) {
5332 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005333 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005334 continue;
5335
Sebastian Redldb9d2142010-08-02 23:18:59 +00005336 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005337 }
5338 }
5339
Sebastian Redldb9d2142010-08-02 23:18:59 +00005340 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5341 MEnd = MethodPool.end();
5342 M != MEnd; ++M) {
5343 for (ObjCMethodList *MethList = &M->second.first;
5344 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005345 MethList = MethList->Next) {
5346 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5347 NumSelIdents))
5348 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005349
5350 if (!Selectors.insert(MethList->Method->getSelector()))
5351 continue;
5352
Douglas Gregor13438f92010-04-06 16:40:00 +00005353 Result R(MethList->Method, 0);
5354 R.StartParameter = NumSelIdents;
5355 R.AllParametersAreInformative = false;
5356 Results.MaybeAddResult(R, CurContext);
5357 }
5358 }
5359 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005360 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005361
5362
5363 // If we're actually at the argument expression (rather than prior to the
5364 // selector), we're actually performing code completion for an expression.
5365 // Determine whether we have a single, best method. If so, we can
5366 // code-complete the expression using the corresponding parameter type as
5367 // our preferred type, improving completion results.
5368 if (AtArgumentExpression) {
5369 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5370 NumSelIdents);
5371 if (PreferredType.isNull())
5372 CodeCompleteOrdinaryName(S, PCC_Expression);
5373 else
5374 CodeCompleteExpression(S, PreferredType);
5375 return;
5376 }
5377
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005378 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005379 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005380 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005381}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005382
Douglas Gregorfb629412010-08-23 21:17:50 +00005383void Sema::CodeCompleteObjCForCollection(Scope *S,
5384 DeclGroupPtrTy IterationVar) {
5385 CodeCompleteExpressionData Data;
5386 Data.ObjCCollection = true;
5387
5388 if (IterationVar.getAsOpaquePtr()) {
5389 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5390 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5391 if (*I)
5392 Data.IgnoreDecls.push_back(*I);
5393 }
5394 }
5395
5396 CodeCompleteExpression(S, Data);
5397}
5398
Douglas Gregor458433d2010-08-26 15:07:07 +00005399void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5400 unsigned NumSelIdents) {
5401 // If we have an external source, load the entire class method
5402 // pool from the AST file.
5403 if (ExternalSource) {
5404 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5405 I != N; ++I) {
5406 Selector Sel = ExternalSource->GetExternalSelector(I);
5407 if (Sel.isNull() || MethodPool.count(Sel))
5408 continue;
5409
5410 ReadMethodPool(Sel);
5411 }
5412 }
5413
Douglas Gregor218937c2011-02-01 19:23:04 +00005414 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5415 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005416 Results.EnterNewScope();
5417 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5418 MEnd = MethodPool.end();
5419 M != MEnd; ++M) {
5420
5421 Selector Sel = M->first;
5422 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5423 continue;
5424
Douglas Gregor218937c2011-02-01 19:23:04 +00005425 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor458433d2010-08-26 15:07:07 +00005426 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005427 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005428 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005429 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005430 continue;
5431 }
5432
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005433 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005434 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005435 if (I == NumSelIdents) {
5436 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005437 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005438 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005439 Accumulator.clear();
5440 }
5441 }
5442
Benjamin Kramera0651c52011-07-26 16:59:25 +00005443 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005444 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005445 }
Douglas Gregordae68752011-02-01 22:57:45 +00005446 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005447 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005448 }
5449 Results.ExitScope();
5450
5451 HandleCodeCompleteResults(this, CodeCompleter,
5452 CodeCompletionContext::CCC_SelectorName,
5453 Results.data(), Results.size());
5454}
5455
Douglas Gregor55385fe2009-11-18 04:19:12 +00005456/// \brief Add all of the protocol declarations that we find in the given
5457/// (translation unit) context.
5458static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005459 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005460 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005461 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005462
5463 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5464 DEnd = Ctx->decls_end();
5465 D != DEnd; ++D) {
5466 // Record any protocols we find.
5467 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005468 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005469 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005470 }
5471}
5472
5473void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5474 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005475 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5476 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005477
Douglas Gregor70c23352010-12-09 21:44:02 +00005478 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5479 Results.EnterNewScope();
5480
5481 // Tell the result set to ignore all of the protocols we have
5482 // already seen.
5483 // FIXME: This doesn't work when caching code-completion results.
5484 for (unsigned I = 0; I != NumProtocols; ++I)
5485 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5486 Protocols[I].second))
5487 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005488
Douglas Gregor70c23352010-12-09 21:44:02 +00005489 // Add all protocols.
5490 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5491 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005492
Douglas Gregor70c23352010-12-09 21:44:02 +00005493 Results.ExitScope();
5494 }
5495
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005496 HandleCodeCompleteResults(this, CodeCompleter,
5497 CodeCompletionContext::CCC_ObjCProtocolName,
5498 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005499}
5500
5501void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005502 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5503 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005504
Douglas Gregor70c23352010-12-09 21:44:02 +00005505 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5506 Results.EnterNewScope();
5507
5508 // Add all protocols.
5509 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5510 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005511
Douglas Gregor70c23352010-12-09 21:44:02 +00005512 Results.ExitScope();
5513 }
5514
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005515 HandleCodeCompleteResults(this, CodeCompleter,
5516 CodeCompletionContext::CCC_ObjCProtocolName,
5517 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005518}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005519
5520/// \brief Add all of the Objective-C interface declarations that we find in
5521/// the given (translation unit) context.
5522static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5523 bool OnlyForwardDeclarations,
5524 bool OnlyUnimplemented,
5525 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005526 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005527
5528 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5529 DEnd = Ctx->decls_end();
5530 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005531 // Record any interfaces we find.
5532 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005533 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005534 (!OnlyUnimplemented || !Class->getImplementation()))
5535 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005536 }
5537}
5538
5539void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005540 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5541 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005542 Results.EnterNewScope();
5543
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005544 if (CodeCompleter->includeGlobals()) {
5545 // Add all classes.
5546 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5547 false, Results);
5548 }
5549
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005550 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005551
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005552 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005553 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005554 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005555}
5556
Douglas Gregorc83c6872010-04-15 22:33:43 +00005557void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5558 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005559 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005560 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005561 Results.EnterNewScope();
5562
5563 // Make sure that we ignore the class we're currently defining.
5564 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005565 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005566 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005567 Results.Ignore(CurClass);
5568
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005569 if (CodeCompleter->includeGlobals()) {
5570 // Add all classes.
5571 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5572 false, Results);
5573 }
5574
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005575 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005576
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005577 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005578 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005579 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005580}
5581
5582void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005583 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5584 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005585 Results.EnterNewScope();
5586
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005587 if (CodeCompleter->includeGlobals()) {
5588 // Add all unimplemented classes.
5589 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5590 true, Results);
5591 }
5592
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005593 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005594
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005595 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005596 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005597 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005598}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005599
5600void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005601 IdentifierInfo *ClassName,
5602 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005603 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005604
Douglas Gregor218937c2011-02-01 19:23:04 +00005605 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005606 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005607
5608 // Ignore any categories we find that have already been implemented by this
5609 // interface.
5610 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5611 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005612 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005613 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5614 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5615 Category = Category->getNextClassCategory())
5616 CategoryNames.insert(Category->getIdentifier());
5617
5618 // Add all of the categories we know about.
5619 Results.EnterNewScope();
5620 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5621 for (DeclContext::decl_iterator D = TU->decls_begin(),
5622 DEnd = TU->decls_end();
5623 D != DEnd; ++D)
5624 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5625 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005626 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005627 Results.ExitScope();
5628
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005629 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005630 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005631 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005632}
5633
5634void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005635 IdentifierInfo *ClassName,
5636 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005637 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005638
5639 // Find the corresponding interface. If we couldn't find the interface, the
5640 // program itself is ill-formed. However, we'll try to be helpful still by
5641 // providing the list of all of the categories we know about.
5642 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005643 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005644 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5645 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005646 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005647
Douglas Gregor218937c2011-02-01 19:23:04 +00005648 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005649 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005650
5651 // Add all of the categories that have have corresponding interface
5652 // declarations in this class and any of its superclasses, except for
5653 // already-implemented categories in the class itself.
5654 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5655 Results.EnterNewScope();
5656 bool IgnoreImplemented = true;
5657 while (Class) {
5658 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5659 Category = Category->getNextClassCategory())
5660 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5661 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005662 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005663
5664 Class = Class->getSuperClass();
5665 IgnoreImplemented = false;
5666 }
5667 Results.ExitScope();
5668
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005669 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005670 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005671 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005672}
Douglas Gregor322328b2009-11-18 22:32:06 +00005673
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005674void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005675 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005676 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5677 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005678
5679 // Figure out where this @synthesize lives.
5680 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005681 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005682 if (!Container ||
5683 (!isa<ObjCImplementationDecl>(Container) &&
5684 !isa<ObjCCategoryImplDecl>(Container)))
5685 return;
5686
5687 // Ignore any properties that have already been implemented.
5688 for (DeclContext::decl_iterator D = Container->decls_begin(),
5689 DEnd = Container->decls_end();
5690 D != DEnd; ++D)
5691 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5692 Results.Ignore(PropertyImpl->getPropertyDecl());
5693
5694 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005695 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005696 Results.EnterNewScope();
5697 if (ObjCImplementationDecl *ClassImpl
5698 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005699 AddObjCProperties(ClassImpl->getClassInterface(), false,
5700 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005701 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005702 else
5703 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005704 false, /*AllowNullaryMethods=*/false, CurContext,
5705 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005706 Results.ExitScope();
5707
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005708 HandleCodeCompleteResults(this, CodeCompleter,
5709 CodeCompletionContext::CCC_Other,
5710 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005711}
5712
5713void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005714 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005715 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005716 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5717 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005718
5719 // Figure out where this @synthesize lives.
5720 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005721 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005722 if (!Container ||
5723 (!isa<ObjCImplementationDecl>(Container) &&
5724 !isa<ObjCCategoryImplDecl>(Container)))
5725 return;
5726
5727 // Figure out which interface we're looking into.
5728 ObjCInterfaceDecl *Class = 0;
5729 if (ObjCImplementationDecl *ClassImpl
5730 = dyn_cast<ObjCImplementationDecl>(Container))
5731 Class = ClassImpl->getClassInterface();
5732 else
5733 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5734 ->getClassInterface();
5735
Douglas Gregore8426052011-04-18 14:40:46 +00005736 // Determine the type of the property we're synthesizing.
5737 QualType PropertyType = Context.getObjCIdType();
5738 if (Class) {
5739 if (ObjCPropertyDecl *Property
5740 = Class->FindPropertyDeclaration(PropertyName)) {
5741 PropertyType
5742 = Property->getType().getNonReferenceType().getUnqualifiedType();
5743
5744 // Give preference to ivars
5745 Results.setPreferredType(PropertyType);
5746 }
5747 }
5748
Douglas Gregor322328b2009-11-18 22:32:06 +00005749 // Add all of the instance variables in this class and its superclasses.
5750 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005751 bool SawSimilarlyNamedIvar = false;
5752 std::string NameWithPrefix;
5753 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005754 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005755 std::string NameWithSuffix = PropertyName->getName().str();
5756 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005757 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005758 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5759 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005760 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5761
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005762 // Determine whether we've seen an ivar with a name similar to the
5763 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005764 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005765 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005766 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005767 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005768
5769 // Reduce the priority of this result by one, to give it a slight
5770 // advantage over other results whose names don't match so closely.
5771 if (Results.size() &&
5772 Results.data()[Results.size() - 1].Kind
5773 == CodeCompletionResult::RK_Declaration &&
5774 Results.data()[Results.size() - 1].Declaration == Ivar)
5775 Results.data()[Results.size() - 1].Priority--;
5776 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005777 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005778 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005779
5780 if (!SawSimilarlyNamedIvar) {
5781 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005782 // an ivar of the appropriate type.
5783 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005784 typedef CodeCompletionResult Result;
5785 CodeCompletionAllocator &Allocator = Results.getAllocator();
5786 CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available);
5787
Douglas Gregor8987b232011-09-27 23:30:47 +00005788 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00005789 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005790 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005791 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5792 Results.AddResult(Result(Builder.TakeString(), Priority,
5793 CXCursor_ObjCIvarDecl));
5794 }
5795
Douglas Gregor322328b2009-11-18 22:32:06 +00005796 Results.ExitScope();
5797
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005798 HandleCodeCompleteResults(this, CodeCompleter,
5799 CodeCompletionContext::CCC_Other,
5800 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005801}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005802
Douglas Gregor408be5a2010-08-25 01:08:01 +00005803// Mapping from selectors to the methods that implement that selector, along
5804// with the "in original class" flag.
5805typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5806 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005807
5808/// \brief Find all of the methods that reside in the given container
5809/// (and its superclasses, protocols, etc.) that meet the given
5810/// criteria. Insert those methods into the map of known methods,
5811/// indexed by selector so they can be easily found.
5812static void FindImplementableMethods(ASTContext &Context,
5813 ObjCContainerDecl *Container,
5814 bool WantInstanceMethods,
5815 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00005816 KnownMethodsMap &KnownMethods,
5817 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005818 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5819 // Recurse into protocols.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00005820 if (!IFace->hasDefinition())
5821 return;
5822
Douglas Gregore8f5a172010-04-07 00:21:17 +00005823 const ObjCList<ObjCProtocolDecl> &Protocols
5824 = IFace->getReferencedProtocols();
5825 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005826 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005827 I != E; ++I)
5828 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005829 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005830
Douglas Gregorea766182010-10-18 18:21:28 +00005831 // Add methods from any class extensions and categories.
5832 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5833 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00005834 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5835 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005836 KnownMethods, false);
5837
5838 // Visit the superclass.
5839 if (IFace->getSuperClass())
5840 FindImplementableMethods(Context, IFace->getSuperClass(),
5841 WantInstanceMethods, ReturnType,
5842 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005843 }
5844
5845 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5846 // Recurse into protocols.
5847 const ObjCList<ObjCProtocolDecl> &Protocols
5848 = Category->getReferencedProtocols();
5849 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005850 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005851 I != E; ++I)
5852 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005853 KnownMethods, InOriginalClass);
5854
5855 // If this category is the original class, jump to the interface.
5856 if (InOriginalClass && Category->getClassInterface())
5857 FindImplementableMethods(Context, Category->getClassInterface(),
5858 WantInstanceMethods, ReturnType, KnownMethods,
5859 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005860 }
5861
5862 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005863 if (Protocol->hasDefinition()) {
5864 // Recurse into protocols.
5865 const ObjCList<ObjCProtocolDecl> &Protocols
5866 = Protocol->getReferencedProtocols();
5867 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5868 E = Protocols.end();
5869 I != E; ++I)
5870 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
5871 KnownMethods, false);
5872 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00005873 }
5874
5875 // Add methods in this container. This operation occurs last because
5876 // we want the methods from this container to override any methods
5877 // we've previously seen with the same selector.
5878 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
5879 MEnd = Container->meth_end();
5880 M != MEnd; ++M) {
5881 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
5882 if (!ReturnType.isNull() &&
5883 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
5884 continue;
5885
Douglas Gregor408be5a2010-08-25 01:08:01 +00005886 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005887 }
5888 }
5889}
5890
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005891/// \brief Add the parenthesized return or parameter type chunk to a code
5892/// completion string.
5893static void AddObjCPassingTypeChunk(QualType Type,
5894 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005895 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005896 CodeCompletionBuilder &Builder) {
5897 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor8987b232011-09-27 23:30:47 +00005898 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005899 Builder.getAllocator()));
5900 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5901}
5902
5903/// \brief Determine whether the given class is or inherits from a class by
5904/// the given name.
5905static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00005906 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005907 if (!Class)
5908 return false;
5909
5910 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
5911 return true;
5912
5913 return InheritsFromClassNamed(Class->getSuperClass(), Name);
5914}
5915
5916/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
5917/// Key-Value Observing (KVO).
5918static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
5919 bool IsInstanceMethod,
5920 QualType ReturnType,
5921 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00005922 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005923 ResultBuilder &Results) {
5924 IdentifierInfo *PropName = Property->getIdentifier();
5925 if (!PropName || PropName->getLength() == 0)
5926 return;
5927
Douglas Gregor8987b232011-09-27 23:30:47 +00005928 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
5929
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005930 // Builder that will create each code completion.
5931 typedef CodeCompletionResult Result;
5932 CodeCompletionAllocator &Allocator = Results.getAllocator();
5933 CodeCompletionBuilder Builder(Allocator);
5934
5935 // The selector table.
5936 SelectorTable &Selectors = Context.Selectors;
5937
5938 // The property name, copied into the code completion allocation region
5939 // on demand.
5940 struct KeyHolder {
5941 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00005942 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005943 const char *CopiedKey;
5944
Chris Lattner5f9e2722011-07-23 10:55:15 +00005945 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005946 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
5947
5948 operator const char *() {
5949 if (CopiedKey)
5950 return CopiedKey;
5951
5952 return CopiedKey = Allocator.CopyString(Key);
5953 }
5954 } Key(Allocator, PropName->getName());
5955
5956 // The uppercased name of the property name.
5957 std::string UpperKey = PropName->getName();
5958 if (!UpperKey.empty())
5959 UpperKey[0] = toupper(UpperKey[0]);
5960
5961 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
5962 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
5963 Property->getType());
5964 bool ReturnTypeMatchesVoid
5965 = ReturnType.isNull() || ReturnType->isVoidType();
5966
5967 // Add the normal accessor -(type)key.
5968 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00005969 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005970 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
5971 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00005972 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005973
5974 Builder.AddTypedTextChunk(Key);
5975 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
5976 CXCursor_ObjCInstanceMethodDecl));
5977 }
5978
5979 // If we have an integral or boolean property (or the user has provided
5980 // an integral or boolean return type), add the accessor -(type)isKey.
5981 if (IsInstanceMethod &&
5982 ((!ReturnType.isNull() &&
5983 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
5984 (ReturnType.isNull() &&
5985 (Property->getType()->isIntegerType() ||
5986 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00005987 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00005988 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00005989 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005990 if (ReturnType.isNull()) {
5991 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5992 Builder.AddTextChunk("BOOL");
5993 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5994 }
5995
5996 Builder.AddTypedTextChunk(
5997 Allocator.CopyString(SelectorId->getName()));
5998 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
5999 CXCursor_ObjCInstanceMethodDecl));
6000 }
6001 }
6002
6003 // Add the normal mutator.
6004 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6005 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006006 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006007 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006008 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006009 if (ReturnType.isNull()) {
6010 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6011 Builder.AddTextChunk("void");
6012 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6013 }
6014
6015 Builder.AddTypedTextChunk(
6016 Allocator.CopyString(SelectorId->getName()));
6017 Builder.AddTypedTextChunk(":");
Douglas Gregor8987b232011-09-27 23:30:47 +00006018 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006019 Builder.AddTextChunk(Key);
6020 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6021 CXCursor_ObjCInstanceMethodDecl));
6022 }
6023 }
6024
6025 // Indexed and unordered accessors
6026 unsigned IndexedGetterPriority = CCP_CodePattern;
6027 unsigned IndexedSetterPriority = CCP_CodePattern;
6028 unsigned UnorderedGetterPriority = CCP_CodePattern;
6029 unsigned UnorderedSetterPriority = CCP_CodePattern;
6030 if (const ObjCObjectPointerType *ObjCPointer
6031 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6032 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6033 // If this interface type is not provably derived from a known
6034 // collection, penalize the corresponding completions.
6035 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6036 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6037 if (!InheritsFromClassNamed(IFace, "NSArray"))
6038 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6039 }
6040
6041 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6042 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6043 if (!InheritsFromClassNamed(IFace, "NSSet"))
6044 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6045 }
6046 }
6047 } else {
6048 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6049 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6050 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6051 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6052 }
6053
6054 // Add -(NSUInteger)countOf<key>
6055 if (IsInstanceMethod &&
6056 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006057 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006058 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006059 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006060 if (ReturnType.isNull()) {
6061 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6062 Builder.AddTextChunk("NSUInteger");
6063 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6064 }
6065
6066 Builder.AddTypedTextChunk(
6067 Allocator.CopyString(SelectorId->getName()));
6068 Results.AddResult(Result(Builder.TakeString(),
6069 std::min(IndexedGetterPriority,
6070 UnorderedGetterPriority),
6071 CXCursor_ObjCInstanceMethodDecl));
6072 }
6073 }
6074
6075 // Indexed getters
6076 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6077 if (IsInstanceMethod &&
6078 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006079 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006080 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006081 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006082 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006083 if (ReturnType.isNull()) {
6084 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6085 Builder.AddTextChunk("id");
6086 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6087 }
6088
6089 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6090 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6091 Builder.AddTextChunk("NSUInteger");
6092 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6093 Builder.AddTextChunk("index");
6094 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6095 CXCursor_ObjCInstanceMethodDecl));
6096 }
6097 }
6098
6099 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6100 if (IsInstanceMethod &&
6101 (ReturnType.isNull() ||
6102 (ReturnType->isObjCObjectPointerType() &&
6103 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6104 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6105 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006106 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006107 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006108 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006109 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006110 if (ReturnType.isNull()) {
6111 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6112 Builder.AddTextChunk("NSArray *");
6113 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6114 }
6115
6116 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6117 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6118 Builder.AddTextChunk("NSIndexSet *");
6119 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6120 Builder.AddTextChunk("indexes");
6121 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6122 CXCursor_ObjCInstanceMethodDecl));
6123 }
6124 }
6125
6126 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6127 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006128 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006129 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006130 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006131 &Context.Idents.get("range")
6132 };
6133
Douglas Gregore74c25c2011-05-04 23:50:46 +00006134 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006135 if (ReturnType.isNull()) {
6136 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6137 Builder.AddTextChunk("void");
6138 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6139 }
6140
6141 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6142 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6143 Builder.AddPlaceholderChunk("object-type");
6144 Builder.AddTextChunk(" **");
6145 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6146 Builder.AddTextChunk("buffer");
6147 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6148 Builder.AddTypedTextChunk("range:");
6149 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6150 Builder.AddTextChunk("NSRange");
6151 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6152 Builder.AddTextChunk("inRange");
6153 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6154 CXCursor_ObjCInstanceMethodDecl));
6155 }
6156 }
6157
6158 // Mutable indexed accessors
6159
6160 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6161 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006162 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006163 IdentifierInfo *SelectorIds[2] = {
6164 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006165 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006166 };
6167
Douglas Gregore74c25c2011-05-04 23:50:46 +00006168 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006169 if (ReturnType.isNull()) {
6170 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6171 Builder.AddTextChunk("void");
6172 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6173 }
6174
6175 Builder.AddTypedTextChunk("insertObject:");
6176 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6177 Builder.AddPlaceholderChunk("object-type");
6178 Builder.AddTextChunk(" *");
6179 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6180 Builder.AddTextChunk("object");
6181 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6182 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6183 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6184 Builder.AddPlaceholderChunk("NSUInteger");
6185 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6186 Builder.AddTextChunk("index");
6187 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6188 CXCursor_ObjCInstanceMethodDecl));
6189 }
6190 }
6191
6192 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6193 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006194 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006195 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006196 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006197 &Context.Idents.get("atIndexes")
6198 };
6199
Douglas Gregore74c25c2011-05-04 23:50:46 +00006200 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006201 if (ReturnType.isNull()) {
6202 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6203 Builder.AddTextChunk("void");
6204 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6205 }
6206
6207 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6208 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6209 Builder.AddTextChunk("NSArray *");
6210 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6211 Builder.AddTextChunk("array");
6212 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6213 Builder.AddTypedTextChunk("atIndexes:");
6214 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6215 Builder.AddPlaceholderChunk("NSIndexSet *");
6216 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6217 Builder.AddTextChunk("indexes");
6218 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6219 CXCursor_ObjCInstanceMethodDecl));
6220 }
6221 }
6222
6223 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6224 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006225 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006226 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006227 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006228 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006229 if (ReturnType.isNull()) {
6230 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6231 Builder.AddTextChunk("void");
6232 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6233 }
6234
6235 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6236 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6237 Builder.AddTextChunk("NSUInteger");
6238 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6239 Builder.AddTextChunk("index");
6240 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6241 CXCursor_ObjCInstanceMethodDecl));
6242 }
6243 }
6244
6245 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6246 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006247 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006248 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006249 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006250 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006251 if (ReturnType.isNull()) {
6252 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6253 Builder.AddTextChunk("void");
6254 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6255 }
6256
6257 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6258 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6259 Builder.AddTextChunk("NSIndexSet *");
6260 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6261 Builder.AddTextChunk("indexes");
6262 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6263 CXCursor_ObjCInstanceMethodDecl));
6264 }
6265 }
6266
6267 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6268 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006269 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006270 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006271 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006272 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006273 &Context.Idents.get("withObject")
6274 };
6275
Douglas Gregore74c25c2011-05-04 23:50:46 +00006276 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006277 if (ReturnType.isNull()) {
6278 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6279 Builder.AddTextChunk("void");
6280 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6281 }
6282
6283 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6284 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6285 Builder.AddPlaceholderChunk("NSUInteger");
6286 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6287 Builder.AddTextChunk("index");
6288 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6289 Builder.AddTypedTextChunk("withObject:");
6290 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6291 Builder.AddTextChunk("id");
6292 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6293 Builder.AddTextChunk("object");
6294 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6295 CXCursor_ObjCInstanceMethodDecl));
6296 }
6297 }
6298
6299 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6300 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006301 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006302 = (Twine("replace") + UpperKey + "AtIndexes").str();
6303 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006304 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006305 &Context.Idents.get(SelectorName1),
6306 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006307 };
6308
Douglas Gregore74c25c2011-05-04 23:50:46 +00006309 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006310 if (ReturnType.isNull()) {
6311 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6312 Builder.AddTextChunk("void");
6313 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6314 }
6315
6316 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6317 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6318 Builder.AddPlaceholderChunk("NSIndexSet *");
6319 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6320 Builder.AddTextChunk("indexes");
6321 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6322 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6323 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6324 Builder.AddTextChunk("NSArray *");
6325 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6326 Builder.AddTextChunk("array");
6327 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6328 CXCursor_ObjCInstanceMethodDecl));
6329 }
6330 }
6331
6332 // Unordered getters
6333 // - (NSEnumerator *)enumeratorOfKey
6334 if (IsInstanceMethod &&
6335 (ReturnType.isNull() ||
6336 (ReturnType->isObjCObjectPointerType() &&
6337 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6338 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6339 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006340 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006341 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006342 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006343 if (ReturnType.isNull()) {
6344 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6345 Builder.AddTextChunk("NSEnumerator *");
6346 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6347 }
6348
6349 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6350 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6351 CXCursor_ObjCInstanceMethodDecl));
6352 }
6353 }
6354
6355 // - (type *)memberOfKey:(type *)object
6356 if (IsInstanceMethod &&
6357 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006358 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006359 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006360 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006361 if (ReturnType.isNull()) {
6362 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6363 Builder.AddPlaceholderChunk("object-type");
6364 Builder.AddTextChunk(" *");
6365 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6366 }
6367
6368 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6369 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6370 if (ReturnType.isNull()) {
6371 Builder.AddPlaceholderChunk("object-type");
6372 Builder.AddTextChunk(" *");
6373 } else {
6374 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006375 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006376 Builder.getAllocator()));
6377 }
6378 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6379 Builder.AddTextChunk("object");
6380 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6381 CXCursor_ObjCInstanceMethodDecl));
6382 }
6383 }
6384
6385 // Mutable unordered accessors
6386 // - (void)addKeyObject:(type *)object
6387 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006388 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006389 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006390 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006391 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006392 if (ReturnType.isNull()) {
6393 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6394 Builder.AddTextChunk("void");
6395 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6396 }
6397
6398 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6399 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6400 Builder.AddPlaceholderChunk("object-type");
6401 Builder.AddTextChunk(" *");
6402 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6403 Builder.AddTextChunk("object");
6404 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6405 CXCursor_ObjCInstanceMethodDecl));
6406 }
6407 }
6408
6409 // - (void)addKey:(NSSet *)objects
6410 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006411 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006412 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006413 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006414 if (ReturnType.isNull()) {
6415 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6416 Builder.AddTextChunk("void");
6417 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6418 }
6419
6420 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6421 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6422 Builder.AddTextChunk("NSSet *");
6423 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6424 Builder.AddTextChunk("objects");
6425 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6426 CXCursor_ObjCInstanceMethodDecl));
6427 }
6428 }
6429
6430 // - (void)removeKeyObject:(type *)object
6431 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006432 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006433 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006434 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006435 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006436 if (ReturnType.isNull()) {
6437 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6438 Builder.AddTextChunk("void");
6439 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6440 }
6441
6442 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6443 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6444 Builder.AddPlaceholderChunk("object-type");
6445 Builder.AddTextChunk(" *");
6446 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6447 Builder.AddTextChunk("object");
6448 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6449 CXCursor_ObjCInstanceMethodDecl));
6450 }
6451 }
6452
6453 // - (void)removeKey:(NSSet *)objects
6454 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006455 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006456 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006457 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006458 if (ReturnType.isNull()) {
6459 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6460 Builder.AddTextChunk("void");
6461 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6462 }
6463
6464 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6465 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6466 Builder.AddTextChunk("NSSet *");
6467 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6468 Builder.AddTextChunk("objects");
6469 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6470 CXCursor_ObjCInstanceMethodDecl));
6471 }
6472 }
6473
6474 // - (void)intersectKey:(NSSet *)objects
6475 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006476 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006477 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006478 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006479 if (ReturnType.isNull()) {
6480 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6481 Builder.AddTextChunk("void");
6482 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6483 }
6484
6485 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6486 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6487 Builder.AddTextChunk("NSSet *");
6488 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6489 Builder.AddTextChunk("objects");
6490 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6491 CXCursor_ObjCInstanceMethodDecl));
6492 }
6493 }
6494
6495 // Key-Value Observing
6496 // + (NSSet *)keyPathsForValuesAffectingKey
6497 if (!IsInstanceMethod &&
6498 (ReturnType.isNull() ||
6499 (ReturnType->isObjCObjectPointerType() &&
6500 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6501 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6502 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006503 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006504 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006505 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006506 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006507 if (ReturnType.isNull()) {
6508 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6509 Builder.AddTextChunk("NSSet *");
6510 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6511 }
6512
6513 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6514 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006515 CXCursor_ObjCClassMethodDecl));
6516 }
6517 }
6518
6519 // + (BOOL)automaticallyNotifiesObserversForKey
6520 if (!IsInstanceMethod &&
6521 (ReturnType.isNull() ||
6522 ReturnType->isIntegerType() ||
6523 ReturnType->isBooleanType())) {
6524 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006525 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006526 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6527 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6528 if (ReturnType.isNull()) {
6529 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6530 Builder.AddTextChunk("BOOL");
6531 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6532 }
6533
6534 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6535 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6536 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006537 }
6538 }
6539}
6540
Douglas Gregore8f5a172010-04-07 00:21:17 +00006541void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6542 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006543 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006544 // Determine the return type of the method we're declaring, if
6545 // provided.
6546 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006547 Decl *IDecl = 0;
6548 if (CurContext->isObjCContainer()) {
6549 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6550 IDecl = cast<Decl>(OCD);
6551 }
Douglas Gregorea766182010-10-18 18:21:28 +00006552 // Determine where we should start searching for methods.
6553 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006554 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006555 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006556 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6557 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006558 IsInImplementation = true;
6559 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006560 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006561 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006562 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006563 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006564 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006565 }
6566
6567 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006568 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006569 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006570 }
6571
Douglas Gregorea766182010-10-18 18:21:28 +00006572 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006573 HandleCodeCompleteResults(this, CodeCompleter,
6574 CodeCompletionContext::CCC_Other,
6575 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006576 return;
6577 }
6578
6579 // Find all of the methods that we could declare/implement here.
6580 KnownMethodsMap KnownMethods;
6581 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006582 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006583
Douglas Gregore8f5a172010-04-07 00:21:17 +00006584 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006585 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006586 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6587 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006588 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006589 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006590 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6591 MEnd = KnownMethods.end();
6592 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006593 ObjCMethodDecl *Method = M->second.first;
Douglas Gregor218937c2011-02-01 19:23:04 +00006594 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006595
6596 // If the result type was not already provided, add it to the
6597 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006598 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00006599 AddObjCPassingTypeChunk(Method->getResultType(), Context, Policy,
6600 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006601
6602 Selector Sel = Method->getSelector();
6603
6604 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006605 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006606 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006607
6608 // Add parameters to the pattern.
6609 unsigned I = 0;
6610 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6611 PEnd = Method->param_end();
6612 P != PEnd; (void)++P, ++I) {
6613 // Add the part of the selector name.
6614 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006615 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006616 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006617 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6618 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006619 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006620 } else
6621 break;
6622
6623 // Add the parameter type.
Douglas Gregor8987b232011-09-27 23:30:47 +00006624 AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Policy,
6625 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006626
6627 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006628 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006629 }
6630
6631 if (Method->isVariadic()) {
6632 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006633 Builder.AddChunk(CodeCompletionString::CK_Comma);
6634 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006635 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006636
Douglas Gregor447107d2010-05-28 00:57:46 +00006637 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006638 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006639 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6640 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6641 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006642 if (!Method->getResultType()->isVoidType()) {
6643 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006644 Builder.AddTextChunk("return");
6645 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6646 Builder.AddPlaceholderChunk("expression");
6647 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006648 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006649 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006650
Douglas Gregor218937c2011-02-01 19:23:04 +00006651 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6652 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006653 }
6654
Douglas Gregor408be5a2010-08-25 01:08:01 +00006655 unsigned Priority = CCP_CodePattern;
6656 if (!M->second.second)
6657 Priority += CCD_InBaseClass;
6658
Douglas Gregor218937c2011-02-01 19:23:04 +00006659 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor16ed9ad2010-08-17 16:06:07 +00006660 Method->isInstanceMethod()
6661 ? CXCursor_ObjCInstanceMethodDecl
6662 : CXCursor_ObjCClassMethodDecl));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006663 }
6664
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006665 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6666 // the properties in this class and its categories.
6667 if (Context.getLangOptions().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006668 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006669 Containers.push_back(SearchDecl);
6670
Douglas Gregore74c25c2011-05-04 23:50:46 +00006671 VisitedSelectorSet KnownSelectors;
6672 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6673 MEnd = KnownMethods.end();
6674 M != MEnd; ++M)
6675 KnownSelectors.insert(M->first);
6676
6677
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006678 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6679 if (!IFace)
6680 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6681 IFace = Category->getClassInterface();
6682
6683 if (IFace) {
6684 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6685 Category = Category->getNextClassCategory())
6686 Containers.push_back(Category);
6687 }
6688
6689 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6690 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6691 PEnd = Containers[I]->prop_end();
6692 P != PEnd; ++P) {
6693 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006694 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006695 }
6696 }
6697 }
6698
Douglas Gregore8f5a172010-04-07 00:21:17 +00006699 Results.ExitScope();
6700
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006701 HandleCodeCompleteResults(this, CodeCompleter,
6702 CodeCompletionContext::CCC_Other,
6703 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006704}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006705
6706void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6707 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006708 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006709 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006710 IdentifierInfo **SelIdents,
6711 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006712 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006713 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006714 if (ExternalSource) {
6715 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6716 I != N; ++I) {
6717 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006718 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006719 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006720
6721 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006722 }
6723 }
6724
6725 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006726 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006727 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6728 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006729
6730 if (ReturnTy)
6731 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006732
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006733 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006734 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6735 MEnd = MethodPool.end();
6736 M != MEnd; ++M) {
6737 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6738 &M->second.second;
6739 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006740 MethList = MethList->Next) {
6741 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6742 NumSelIdents))
6743 continue;
6744
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006745 if (AtParameterName) {
6746 // Suggest parameter names we've seen before.
6747 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6748 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6749 if (Param->getIdentifier()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006750 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregordae68752011-02-01 22:57:45 +00006751 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006752 Param->getIdentifier()->getName()));
6753 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006754 }
6755 }
6756
6757 continue;
6758 }
6759
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006760 Result R(MethList->Method, 0);
6761 R.StartParameter = NumSelIdents;
6762 R.AllParametersAreInformative = false;
6763 R.DeclaringEntity = true;
6764 Results.MaybeAddResult(R, CurContext);
6765 }
6766 }
6767
6768 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006769 HandleCodeCompleteResults(this, CodeCompleter,
6770 CodeCompletionContext::CCC_Other,
6771 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006772}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006773
Douglas Gregorf29c5232010-08-24 22:20:20 +00006774void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006775 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006776 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006777 Results.EnterNewScope();
6778
6779 // #if <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006780 CodeCompletionBuilder Builder(Results.getAllocator());
6781 Builder.AddTypedTextChunk("if");
6782 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6783 Builder.AddPlaceholderChunk("condition");
6784 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006785
6786 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006787 Builder.AddTypedTextChunk("ifdef");
6788 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6789 Builder.AddPlaceholderChunk("macro");
6790 Results.AddResult(Builder.TakeString());
6791
Douglas Gregorf44e8542010-08-24 19:08:16 +00006792 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006793 Builder.AddTypedTextChunk("ifndef");
6794 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6795 Builder.AddPlaceholderChunk("macro");
6796 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006797
6798 if (InConditional) {
6799 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006800 Builder.AddTypedTextChunk("elif");
6801 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6802 Builder.AddPlaceholderChunk("condition");
6803 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006804
6805 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00006806 Builder.AddTypedTextChunk("else");
6807 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006808
6809 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00006810 Builder.AddTypedTextChunk("endif");
6811 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006812 }
6813
6814 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006815 Builder.AddTypedTextChunk("include");
6816 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6817 Builder.AddTextChunk("\"");
6818 Builder.AddPlaceholderChunk("header");
6819 Builder.AddTextChunk("\"");
6820 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006821
6822 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006823 Builder.AddTypedTextChunk("include");
6824 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6825 Builder.AddTextChunk("<");
6826 Builder.AddPlaceholderChunk("header");
6827 Builder.AddTextChunk(">");
6828 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006829
6830 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006831 Builder.AddTypedTextChunk("define");
6832 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6833 Builder.AddPlaceholderChunk("macro");
6834 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006835
6836 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00006837 Builder.AddTypedTextChunk("define");
6838 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6839 Builder.AddPlaceholderChunk("macro");
6840 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6841 Builder.AddPlaceholderChunk("args");
6842 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6843 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006844
6845 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006846 Builder.AddTypedTextChunk("undef");
6847 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6848 Builder.AddPlaceholderChunk("macro");
6849 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006850
6851 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00006852 Builder.AddTypedTextChunk("line");
6853 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6854 Builder.AddPlaceholderChunk("number");
6855 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006856
6857 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00006858 Builder.AddTypedTextChunk("line");
6859 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6860 Builder.AddPlaceholderChunk("number");
6861 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6862 Builder.AddTextChunk("\"");
6863 Builder.AddPlaceholderChunk("filename");
6864 Builder.AddTextChunk("\"");
6865 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006866
6867 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006868 Builder.AddTypedTextChunk("error");
6869 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6870 Builder.AddPlaceholderChunk("message");
6871 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006872
6873 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00006874 Builder.AddTypedTextChunk("pragma");
6875 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6876 Builder.AddPlaceholderChunk("arguments");
6877 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006878
6879 if (getLangOptions().ObjC1) {
6880 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006881 Builder.AddTypedTextChunk("import");
6882 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6883 Builder.AddTextChunk("\"");
6884 Builder.AddPlaceholderChunk("header");
6885 Builder.AddTextChunk("\"");
6886 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006887
6888 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006889 Builder.AddTypedTextChunk("import");
6890 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6891 Builder.AddTextChunk("<");
6892 Builder.AddPlaceholderChunk("header");
6893 Builder.AddTextChunk(">");
6894 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006895 }
6896
6897 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006898 Builder.AddTypedTextChunk("include_next");
6899 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6900 Builder.AddTextChunk("\"");
6901 Builder.AddPlaceholderChunk("header");
6902 Builder.AddTextChunk("\"");
6903 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006904
6905 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006906 Builder.AddTypedTextChunk("include_next");
6907 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6908 Builder.AddTextChunk("<");
6909 Builder.AddPlaceholderChunk("header");
6910 Builder.AddTextChunk(">");
6911 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006912
6913 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006914 Builder.AddTypedTextChunk("warning");
6915 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6916 Builder.AddPlaceholderChunk("message");
6917 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006918
6919 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
6920 // completions for them. And __include_macros is a Clang-internal extension
6921 // that we don't want to encourage anyone to use.
6922
6923 // FIXME: we don't support #assert or #unassert, so don't suggest them.
6924 Results.ExitScope();
6925
Douglas Gregorf44e8542010-08-24 19:08:16 +00006926 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00006927 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00006928 Results.data(), Results.size());
6929}
6930
6931void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00006932 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00006933 S->getFnParent()? Sema::PCC_RecoveryInFunction
6934 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006935}
6936
Douglas Gregorf29c5232010-08-24 22:20:20 +00006937void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006938 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006939 IsDefinition? CodeCompletionContext::CCC_MacroName
6940 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006941 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
6942 // Add just the names of macros, not their arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00006943 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006944 Results.EnterNewScope();
6945 for (Preprocessor::macro_iterator M = PP.macro_begin(),
6946 MEnd = PP.macro_end();
6947 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00006948 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006949 M->first->getName()));
6950 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006951 }
6952 Results.ExitScope();
6953 } else if (IsDefinition) {
6954 // FIXME: Can we detect when the user just wrote an include guard above?
6955 }
6956
Douglas Gregor52779fb2010-09-23 23:01:17 +00006957 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006958 Results.data(), Results.size());
6959}
6960
Douglas Gregorf29c5232010-08-24 22:20:20 +00006961void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00006962 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006963 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00006964
6965 if (!CodeCompleter || CodeCompleter->includeMacros())
6966 AddMacroResults(PP, Results);
6967
6968 // defined (<macro>)
6969 Results.EnterNewScope();
Douglas Gregor218937c2011-02-01 19:23:04 +00006970 CodeCompletionBuilder Builder(Results.getAllocator());
6971 Builder.AddTypedTextChunk("defined");
6972 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6973 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6974 Builder.AddPlaceholderChunk("macro");
6975 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6976 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00006977 Results.ExitScope();
6978
6979 HandleCodeCompleteResults(this, CodeCompleter,
6980 CodeCompletionContext::CCC_PreprocessorExpression,
6981 Results.data(), Results.size());
6982}
6983
6984void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
6985 IdentifierInfo *Macro,
6986 MacroInfo *MacroInfo,
6987 unsigned Argument) {
6988 // FIXME: In the future, we could provide "overload" results, much like we
6989 // do for function calls.
6990
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00006991 // Now just ignore this. There will be another code-completion callback
6992 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00006993}
6994
Douglas Gregor55817af2010-08-25 17:04:25 +00006995void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00006996 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00006997 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00006998 0, 0);
6999}
7000
Douglas Gregordae68752011-02-01 22:57:45 +00007001void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007002 SmallVectorImpl<CodeCompletionResult> &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007003 ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007004 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7005 CodeCompletionDeclConsumer Consumer(Builder,
7006 Context.getTranslationUnitDecl());
7007 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7008 Consumer);
7009 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007010
7011 if (!CodeCompleter || CodeCompleter->includeMacros())
7012 AddMacroResults(PP, Builder);
7013
7014 Results.clear();
7015 Results.insert(Results.end(),
7016 Builder.data(), Builder.data() + Builder.size());
7017}